修改权限

This commit is contained in:
wuyanwen 2019-12-28 21:20:27 +08:00
parent a634aa4f93
commit 1798cbcd0c
12 changed files with 104 additions and 345 deletions

View File

@ -31,10 +31,7 @@ export function getSmsCaptcha (parameter) {
export function getInfo () {
return axios({
url: '/user/info',
method: 'get',
headers: {
'Content-Type': 'application/json;charset=UTF-8'
}
method: 'get'
})
}

View File

@ -0,0 +1,12 @@
/**
* export component map
*/
export default {
workplace: () => import('@/views/dashboard/Workplace'),
users: () => import('@/views/permissions/users/users'),
roles: () => import('@/views/permissions/roles/roles'),
rules: () => import('@/views/permissions/rules/rules'),
database: () => import('@/views/system/database/index'),
loginLog: () => import('@/views/system/log/login'),
operateLog: () => import('@/views/system/log/operate')
}

View File

@ -19,60 +19,15 @@ export const asyncRouterMap = [
component: RouteView,
meta: { title: '仪表盘', keepAlive: true, icon: bxAnaalyse, permission: [ 'dashboard' ] },
children: [
{
path: '/dashboard/analysis',
name: 'Analysis',
component: () => import('@/views/dashboard/Analysis'),
meta: { title: '分析页', keepAlive: false, permission: [ 'dashboard' ] }
},
// 外部链接
{
path: 'https://www.baidu.com/',
name: 'Monitor',
meta: { title: '监控页(外部)', target: '_blank' }
},
{
path: '/dashboard/workplace',
name: 'Workplace',
component: () => import('@/views/dashboard/Workplace'),
meta: { title: '工作台', keepAlive: true, permission: [ 'dashboard' ] }
},
{
path: '/dashboard/test-work',
name: 'TestWork',
component: () => import('@/views/dashboard/TestWork'),
meta: { title: '测试功能', keepAlive: true, permission: [ 'dashboard' ] }
}
]
},
// forms
{
path: '/form',
redirect: '/form/base-form',
component: PageView,
meta: { title: '表单页', icon: 'form', permission: [ 'form' ] },
children: [
{
path: '/form/base-form',
name: 'BaseForm',
component: () => import('@/views/form/BasicForm'),
meta: { title: '基础表单', keepAlive: true, permission: [ 'form' ] }
},
{
path: '/form/step-form',
name: 'StepForm',
component: () => import('@/views/form/stepForm/StepForm'),
meta: { title: '分步表单', keepAlive: true, permission: [ 'form' ] }
},
{
path: '/form/advanced-form',
name: 'AdvanceForm',
component: () => import('@/views/form/advancedForm/AdvancedForm'),
meta: { title: '高级表单', keepAlive: true, permission: [ 'form' ] }
}
]
},
// permissions
{
path: '/permissions',
@ -86,14 +41,14 @@ export const asyncRouterMap = [
name: 'users',
hideChildrenInMenu: true, // 强制显示 MenuItem 而不是 SubMenu
component: () => import('@/views/permissions/users/users'),
meta: { title: '用户管理', keepAlive: true, permission: [ 'permission' ] }
meta: { title: '用户管理', keepAlive: true, permission: [ 'user' ] }
},
{
path: '/permissions/roles',
name: 'roles',
hideChildrenInMenu: true, // 强制显示 MenuItem 而不是 SubMenu
component: () => import('@/views/permissions/roles/roles'),
meta: { title: '角色管理', keepAlive: true, permission: [ 'permission' ] }
meta: { title: '角色管理', keepAlive: true, permission: [ 'role' ] }
},
{
path: '/permissions/rules',
@ -116,268 +71,26 @@ export const asyncRouterMap = [
name: 'database',
hideChildrenInMenu: true, // 强制显示 MenuItem 而不是 SubMenu
component: () => import('@/views/system/database/index'),
meta: { title: '数据字典', keepAlive: true, system: [ 'system' ] }
meta: { title: '数据字典', keepAlive: true, system: [ 'database' ] }
},
{
path: '/system/log',
name: 'log',
meta: { title: '日志管理', keepAlive: true, permission: [ 'permission' ] },
meta: { title: '日志管理', keepAlive: true, permission: [ 'log' ] },
children: [
{
path: '/system/log/login',
name: 'loginLog',
hideChildrenInMenu: true, // 强制显示 MenuItem 而不是 SubMenu
component: () => import('@/views/system/log/login'),
meta: { title: '登录日志', keepAlive: true, system: [ 'system' ] }
meta: { title: '登录日志', keepAlive: true, system: [ 'loginLog/index' ] }
},
{
path: '/system/log/operate',
name: 'operateLog',
hideChildrenInMenu: true, // 强制显示 MenuItem 而不是 SubMenu
component: () => import('@/views/system/log/operate'),
meta: { title: '操作日志', keepAlive: true, system: [ 'system' ] }
}
]
}
]
},
// list
{
path: '/list',
name: 'list',
component: PageView,
redirect: '/list/table-list',
meta: { title: '列表页', icon: 'table', permission: [ 'table' ] },
children: [
{
path: '/list/basic-list',
name: 'BasicList',
component: () => import('@/views/list/StandardList'),
meta: { title: '标准列表', keepAlive: true, permission: [ 'table' ] }
},
{
path: '/list/card',
name: 'CardList',
component: () => import('@/views/list/CardList'),
meta: { title: '卡片列表', keepAlive: true, permission: [ 'table' ] }
},
{
path: '/list/search',
name: 'SearchList',
component: () => import('@/views/list/search/SearchLayout'),
redirect: '/list/search/article',
meta: { title: '搜索列表', keepAlive: true, permission: [ 'table' ] },
children: [
{
path: '/list/search/article',
name: 'SearchArticles',
component: () => import('../views/list/search/Article'),
meta: { title: '搜索列表(文章)', permission: [ 'table' ] }
},
{
path: '/list/search/project',
name: 'SearchProjects',
component: () => import('../views/list/search/Projects'),
meta: { title: '搜索列表(项目)', permission: [ 'table' ] }
},
{
path: '/list/search/application',
name: 'SearchApplications',
component: () => import('../views/list/search/Applications'),
meta: { title: '搜索列表(应用)', permission: [ 'table' ] }
}
]
}
]
},
// profile
{
path: '/profile',
name: 'profile',
component: RouteView,
redirect: '/profile/basic',
meta: { title: '详情页', icon: 'profile', permission: [ 'profile' ] },
children: [
{
path: '/profile/basic',
name: 'ProfileBasic',
component: () => import('@/views/profile/basic/Index'),
meta: { title: '基础详情页', permission: [ 'profile' ] }
},
{
path: '/profile/advanced',
name: 'ProfileAdvanced',
component: () => import('@/views/profile/advanced/Advanced'),
meta: { title: '高级详情页', permission: [ 'profile' ] }
}
]
},
// result
{
path: '/result',
name: 'result',
component: PageView,
redirect: '/result/success',
meta: { title: '结果页', icon: 'check-circle-o', permission: [ 'result' ] },
children: [
{
path: '/result/success',
name: 'ResultSuccess',
component: () => import(/* webpackChunkName: "result" */ '@/views/result/Success'),
meta: { title: '成功', keepAlive: false, hiddenHeaderContent: true, permission: [ 'result' ] }
},
{
path: '/result/fail',
name: 'ResultFail',
component: () => import(/* webpackChunkName: "result" */ '@/views/result/Error'),
meta: { title: '失败', keepAlive: false, hiddenHeaderContent: true, permission: [ 'result' ] }
}
]
},
// Exception
{
path: '/exception',
name: 'exception',
component: RouteView,
redirect: '/exception/403',
meta: { title: '异常页', icon: 'warning', permission: [ 'exception' ] },
children: [
{
path: '/exception/403',
name: 'Exception403',
component: () => import(/* webpackChunkName: "fail" */ '@/views/exception/403'),
meta: { title: '403', permission: [ 'exception' ] }
},
{
path: '/exception/404',
name: 'Exception404',
component: () => import(/* webpackChunkName: "fail" */ '@/views/exception/404'),
meta: { title: '404', permission: [ 'exception' ] }
},
{
path: '/exception/500',
name: 'Exception500',
component: () => import(/* webpackChunkName: "fail" */ '@/views/exception/500'),
meta: { title: '500', permission: [ 'exception' ] }
}
]
},
// account
{
path: '/account',
component: RouteView,
redirect: '/account/center',
name: 'account',
meta: { title: '个人页', icon: 'user', keepAlive: true, permission: [ 'user' ] },
children: [
{
path: '/account/center',
name: 'center',
component: () => import('@/views/account/center/Index'),
meta: { title: '个人中心', keepAlive: true, permission: [ 'user' ] }
},
{
path: '/account/settings',
name: 'settings',
component: () => import('@/views/account/settings/Index'),
meta: { title: '个人设置', hideHeader: true, permission: [ 'user' ] },
redirect: '/account/settings/base',
hideChildrenInMenu: true,
children: [
{
path: '/account/settings/base',
name: 'BaseSettings',
component: () => import('@/views/account/settings/BaseSetting'),
meta: { title: '基本设置', permission: [ 'user' ] }
},
{
path: '/account/settings/security',
name: 'SecuritySettings',
component: () => import('@/views/account/settings/Security'),
meta: { title: '安全设置', keepAlive: true, permission: [ 'user' ] }
},
{
path: '/account/settings/custom',
name: 'CustomSettings',
component: () => import('@/views/account/settings/Custom'),
meta: { title: '个性化设置', keepAlive: true, permission: [ 'user' ] }
},
{
path: '/account/settings/binding',
name: 'BindingSettings',
component: () => import('@/views/account/settings/Binding'),
meta: { title: '账户绑定', keepAlive: true, permission: [ 'user' ] }
},
{
path: '/account/settings/notification',
name: 'NotificationSettings',
component: () => import('@/views/account/settings/Notification'),
meta: { title: '新消息通知', keepAlive: true, permission: [ 'user' ] }
}
]
}
]
},
// other
{
path: '/other',
name: 'otherPage',
component: PageView,
meta: { title: '其他组件', icon: 'slack', permission: [ 'dashboard' ] },
redirect: '/other/icon-selector',
children: [
{
path: '/other/icon-selector',
name: 'TestIconSelect',
component: () => import('@/views/other/IconSelectorView'),
meta: { title: 'IconSelector', icon: 'tool', keepAlive: true, permission: [ 'dashboard' ] }
},
{
path: '/other/list',
component: RouteView,
meta: { title: '业务布局', icon: 'layout', permission: [ 'support' ] },
redirect: '/other/list/tree-list',
children: [
{
path: '/other/list/tree-list',
name: 'TreeList',
component: () => import('@/views/other/TreeList'),
meta: { title: '树目录表格', keepAlive: true }
},
{
path: '/other/list/edit-table',
name: 'EditList',
component: () => import('@/views/other/TableInnerEditList'),
meta: { title: '内联编辑表格', keepAlive: true }
},
{
path: '/other/list/user-list',
name: 'UserList',
component: () => import('@/views/other/UserList'),
meta: { title: '用户列表', keepAlive: true }
},
{
path: '/other/list/role-list',
name: 'RoleList',
component: () => import('@/views/other/RoleList'),
meta: { title: '角色列表', keepAlive: true }
},
{
path: '/other/list/system-role',
name: 'SystemRole',
component: () => import('@/views/role/RoleList'),
meta: { title: '角色列表2', keepAlive: true }
},
{
path: '/other/list/permission-list',
name: 'PermissionList',
component: () => import('@/views/other/PermissionList'),
meta: { title: '权限列表', keepAlive: true }
meta: { title: '操作日志', keepAlive: true, system: [ 'operateLog/index' ] }
}
]
}

View File

@ -70,7 +70,7 @@ import SideMenu from '@/components/Menu/SideMenu'
import GlobalHeader from '@/components/GlobalHeader'
import GlobalFooter from '@/components/GlobalFooter'
import SettingDrawer from '@/components/SettingDrawer'
import { asyncRouterMap } from '@/config/router.config.js'
// import { asyncRouterMap } from '@/config/router.config.js'
export default {
name: 'BasicLayout',
@ -110,8 +110,8 @@ export default {
}
},
created () {
this.menus = asyncRouterMap.find((item) => item.path === '/').children
// this.menus = this.mainMenu.find(item => item.path === '/').children
// this.menus = asyncRouterMap.find((item) => item.path === '/').children
this.menus = this.mainMenu.find(item => item.path === '/').children
this.collapsed = !this.sidebarOpened
},
mounted () {

View File

@ -14,7 +14,7 @@ import { VueAxios } from './utils/request'
import bootstrap from './core/bootstrap'
import './core/lazy_use'
// import './permission' // permission control
import './permission' // permission control
import './utils/filter' // global filter
import './components/global.less'

View File

@ -26,8 +26,8 @@ router.beforeEach((to, from, next) => {
store
.dispatch('GetInfo')
.then(res => {
const roles = res.result && res.result.role
store.dispatch('GenerateRoutes', { roles }).then(() => {
const permissions = res.data && res.data.permissions
store.dispatch('GenerateRoutes', { permissions }).then(() => {
// 根据roles权限生成可访问的路由表
// 动态添加可访问路由表
router.addRoutes(store.getters.addRouters)

View File

@ -1,27 +1,18 @@
import Vue from 'vue'
import Router from 'vue-router'
// import { constantRouterMap } from '@/config/router.config'
import { constantRouterMap, asyncRouterMap } from '@/config/router.config'
import { constantRouterMap } from '@/config/router.config'
// hack router push callback
/** const originalPush = Router.prototype.push
const originalPush = Router.prototype.push
Router.prototype.push = function push (location, onResolve, onReject) {
if (onResolve || onReject) return originalPush.call(this, location, onResolve, onReject)
return originalPush.call(this, location).catch(err => err)
} */
}
Vue.use(Router)
/** export default new Router({
mode: 'history',
base: process.env.BASE_URL,
scrollBehavior: () => ({ y: 0 }),
routes: constantRouterMap
}) */
export default new Router({
mode: 'history',
base: process.env.BASE_URL,
scrollBehavior: () => ({ y: 0 }),
routes: constantRouterMap.concat(asyncRouterMap)
routes: constantRouterMap
})

View File

@ -9,6 +9,7 @@ const getters = {
roles: state => state.user.roles,
userInfo: state => state.user.info,
addRouters: state => state.permission.addRouters,
routers: state => state.permission.routers,
multiTab: state => state.app.multiTab,
lang: state => state.i18n.lang
}

View File

@ -11,8 +11,10 @@ function hasPermission (permission, route) {
if (route.meta && route.meta.permission) {
let flag = false
for (let i = 0, len = permission.length; i < len; i++) {
flag = route.meta.permission.includes(permission[i])
flag = route.meta.permission.includes(permission[i].route)
if (flag) {
route.meta.icon = permission[i].icon
route.meta.title = permission[i].title
return true
}
}
@ -37,12 +39,17 @@ function hasRole(roles, route) {
}
}
function filterAsyncRouter (routerMap, roles) {
/**
*
* @param routerMap
* @param permissions
* @returns {Int32Array | * | Uint32Array | any[] | Int8Array | Float64Array | BigUint64Array | Uint8Array | Int16Array | BigInt64Array | Float32Array | Uint8ClampedArray | Uint16Array}
*/
function filterAsyncRouter (routerMap, permissions) {
const accessedRouters = routerMap.filter(route => {
console.log(roles)
if (hasPermission(roles.permissions, route)) {
if (hasPermission(permissions, route)) {
if (route.children && route.children.length) {
route.children = filterAsyncRouter(route.children, roles)
route.children = filterAsyncRouter(route.children, permissions)
}
return true
}
@ -65,8 +72,8 @@ const permission = {
actions: {
GenerateRoutes ({ commit }, data) {
return new Promise(resolve => {
const { roles } = data
const accessedRouters = filterAsyncRouter(asyncRouterMap, roles)
const { permissions } = data
const accessedRouters = filterAsyncRouter(asyncRouterMap, permissions)
commit('SET_ROUTERS', accessedRouters)
resolve()
})

View File

@ -51,25 +51,25 @@ const user = {
GetInfo ({ commit }) {
return new Promise((resolve, reject) => {
getInfo().then(response => {
const result = response.result
if (result.role && result.role.permissions.length > 0) {
const role = result.role
role.permissions = result.role.permissions
const result = response.data
if (result.roles.length > 0) {
const roles = result.roles
// const permissions = result.permissions
/** role.permissions = result.role.permissions
role.permissions.map(per => {
if (per.actionEntitySet != null && per.actionEntitySet.length > 0) {
const action = per.actionEntitySet.map(action => { return action.action })
per.actionList = action
}
})
role.permissionList = role.permissions.map(permission => { return permission.permissionId })
commit('SET_ROLES', result.role)
role.permissionList = role.permissions.map(permission => { return permission.permissionId }) */
commit('SET_ROLES', roles)
commit('SET_INFO', result)
} else {
reject(new Error('getInfo: roles must be a non-null array !'))
}
commit('SET_NAME', { name: result.name, welcome: welcome() })
commit('SET_NAME', { name: result.username, welcome: welcome() })
commit('SET_AVATAR', result.avatar)
resolve(response)

View File

@ -15,7 +15,25 @@
:labelCol="labelCol"
:wrapperCol="wrapperCol"
>
<a-input v-decorator="['permission_name', {rules: [{required: true, min: 2, message: '请输入至少3个字符'}]}]" />
<a-input allowClear v-decorator="['permission_name', {rules: [{required: true, min: 2, message: '请输入至少3个字符'}]}]" />
</a-form-item>
<a-form-item
label="菜单图标"
type="text"
:labelCol="labelCol"
:wrapperCol="wrapperCol"
>
<a-select
showSearch
placeholder="选择图标"
optionFilterProp="children"
style="width: 320px"
v-decorator="['icon']"
>
<a-select-option v-for="(icon, key) in icons" :key="`${key}-${icon}`" :value="icon">
{{ icon }} <a-icon :type="icon" :style="{ fontSize: '16px' }" />
</a-select-option>
</a-select>
</a-form-item>
<a-form-item
label="菜单路由"
@ -23,15 +41,16 @@
:labelCol="labelCol"
:wrapperCol="wrapperCol"
>
<a-input v-decorator="['route', {rules: [{required: true, min: 2, message: '请输入至少3个字符'}]}]" />
<a-input allowClear v-decorator="['route', {rules: [{required: true, min: 2, message: '请输入至少3个字符'}]}]" />
</a-form-item>
<a-form-item
label="菜单标识"
type="text"
:labelCol="labelCol"
:wrapperCol="wrapperCol"
:filterOption="filterOption"
>
<a-input v-decorator="['permission_mark',{rules: [{required: true, min: 2, message: '请输入至少3个字符'}]}]" />
<a-input allowClear v-decorator="['permission_mark',{rules: [{required: true, min: 2, message: '请输入至少3个字符'}]}]" />
</a-form-item>
<a-form-item
:label-col="labelCol"
@ -39,17 +58,17 @@
label="请求方法"
>
<a-select v-decorator="['method',{initialValue:methodValue},{rules: [{required: true}]}]">
<a-select-option value="GET">
GET
<a-select-option value="get">
get
</a-select-option>
<a-select-option value="POST">
POST
<a-select-option value="post">
post
</a-select-option>
<a-select-option value="PUT">
PUT
<a-select-option value="put">
put
</a-select-option>
<a-select-option value="DELETE">
DELETE
<a-select-option value="delete">
delete
</a-select-option>
</a-select>
</a-form-item>
@ -78,6 +97,7 @@
<script>
import { store, update } from '@/api/permission'
import pick from 'lodash.pick'
import icons from './icons'
export default {
data () {
@ -98,7 +118,8 @@ export default {
methodValue: 'GET',
typeValue: '2',
form: this.$form.createForm(this),
sort: 1
sort: 1,
icons
}
},
methods: {
@ -111,7 +132,7 @@ export default {
this.title = '编辑菜单'
const { form: { setFieldsValue } } = this
this.id = record.id
setFieldsValue(pick(record, ['permission_name', 'route', 'permission_mark', 'method', 'type', 'sort']))
setFieldsValue(pick(record, ['permission_name', 'route', 'permission_mark', 'method', 'type', 'sort', 'icon']))
this.methodValue = record.method
this.typeValue = record.type
this.sort = record.sort
@ -124,10 +145,10 @@ export default {
},
handleSubmit () {
const { form: { validateFields } } = this
this.confirmLoading = true
if (this.id) {
validateFields((errors, values) => {
if (!errors) {
this.confirmLoading = true
update(this.id, values).then((res) => {
this.refresh(res.message)
}).catch(err => this.failed(err))
@ -136,6 +157,7 @@ export default {
} else {
validateFields((errors, values) => {
if (!errors) {
this.confirmLoading = true
if (this.parent_id > 0) {
values['parent_id'] = this.parent_id
}
@ -163,6 +185,11 @@ export default {
this.sort = 1
this.form.resetFields()
},
filterOption (input, option) {
return (
option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
)
},
refresh (message) {
this.$notification['success']({
message: message,

View File

@ -0,0 +1,11 @@
/**
* 增加新的图标时请遵循以下数据结构
* Adding new icon please follow the data structure below
*/
export default
[
'lock', 'unlock', 'bars', 'book', 'calendar', 'cloud', 'cloud-download', 'code', 'copy', 'credit-card', 'delete', 'desktop', 'download', 'ellipsis', 'file', 'file-text', 'file-unknown', 'file-pdf', 'file-word', 'file-excel', 'file-jpg', 'file-ppt', 'file-markdown', 'file-add', 'folder', 'folder-open',
'folder-add', 'hdd', 'frown', 'meh', 'smile', 'inbox', 'laptop', 'appstore', 'link', 'mail', 'mobile', 'notification', 'paper-clip', 'picture', 'poweroff', 'reload', 'search', 'setting', 'share-alt', 'shopping-cart', 'tablet', 'tag', 'tags', 'to-top', 'upload', 'user', 'video-camera', 'home',
'loading', 'loading-3-quarters', 'cloud-upload', 'star', 'heart', 'environment', 'eye', 'camera', 'save', 'team', 'solution', 'phone', 'filter', 'exception', 'export', 'customer-service', 'qrcode', 'scan', 'like', 'dislike', 'message', 'pay-circle', 'calculator', 'pushpin', 'bulb', 'select',
'switcher', 'rocket', 'bell', 'disconnect', 'database', 'compass', 'barcode', 'hourglass', 'key', 'flag', 'layout', 'printer', 'sound', 'usb', 'skin', 'tool', 'sync', 'wifi', 'car', 'schedule', 'user-add', 'user-delete', 'usergroup-add', 'usergroup-delete', 'man', 'woman', 'shop', 'gift', 'idcard', 'medicine-box', 'red-envelope', 'coffee', 'copyright', 'trademark', 'safety', 'wallet', 'bank', 'trophy', 'contacts', 'global', 'shake', 'api', 'fork', 'dashboard', 'table', 'profile', 'alert', 'audit', 'branches', 'build', 'border', 'crown', 'experiment', 'fire', 'money-collect', 'property-safety', 'read', 'reconciliation', 'rest', 'security-scan', 'insurance', 'interation', 'safety-certificate', 'project', 'thunderbolt', 'block', 'cluster', 'deployment-unit', 'dollar', 'euro', 'pound', 'file-done', 'file-exclamation', 'file-protect', 'file-search', 'file-sync', 'gateway', 'gold', 'robot', 'shopping'
]