| | |
| | | <span class="selected-total">已选权限 {{ selectedRoleIds.length }} 个</span> |
| | | </div> |
| | | <div class="permission-toolbar"> |
| | | <el-checkbox v-model="checkAll" @change="toggleAll">全选</el-checkbox> |
| | | <span class="permission-tip">菜单和按钮权限均可勾选,保存后切换角色会自动反显。</span> |
| | | <el-radio-group v-model="permissionScope" size="small" @change="handleScopeChange"> |
| | | <el-radio-button label="all">全部</el-radio-button> |
| | | <el-radio-button label="assigned">已设置</el-radio-button> |
| | | </el-radio-group> |
| | | <el-checkbox v-if="permissionScope === 'all'" v-model="checkAll" @change="toggleAll">全选</el-checkbox> |
| | | <span class="permission-tip">{{ permissionTip }}</span> |
| | | </div> |
| | | <div v-loading="loading" class="permission-tree"> |
| | | <el-tree |
| | | ref="permissionTree" |
| | | :data="menus" |
| | | :data="displayMenus" |
| | | node-key="id" |
| | | show-checkbox |
| | | default-expand-all |
| | | empty-text="该角色尚未设置权限" |
| | | :render-content="renderContent" |
| | | :props="{ label: 'name', children: 'children' }" |
| | | @check="syncCheckAllState" |
| | |
| | | loading: false, |
| | | saving: false, |
| | | checkAll: false, |
| | | permissionScope: 'all', |
| | | selectedRoleIds: [] |
| | | } |
| | | }, |
| | |
| | | }, |
| | | allMenuIds() { |
| | | return this.flatMenus.map(item => String(item.id)) |
| | | }, |
| | | displayMenus() { |
| | | if (this.permissionScope === 'all') return this.menus |
| | | const assigned = new Set(this.selectedRoleIds.map(String)) |
| | | const filterAssigned = nodes => (nodes || []).reduce((result, node) => { |
| | | const children = filterAssigned(node.children) |
| | | if (assigned.has(String(node.id)) || children.length) { |
| | | result.push({ ...node, children }) |
| | | } |
| | | return result |
| | | }, []) |
| | | return filterAssigned(this.menus) |
| | | }, |
| | | permissionTip() { |
| | | return this.permissionScope === 'all' |
| | | ? '菜单和按钮权限均可勾选,保存后切换角色会自动反显。' |
| | | : '仅显示当前角色已设置的权限及其父级节点。' |
| | | } |
| | | }, |
| | | watch: { |
| | |
| | | if (!this.role || !this.role.id) return |
| | | this.loading = true |
| | | this.checkAll = false |
| | | this.permissionScope = 'all' |
| | | this.selectedRoleIds = [] |
| | | Promise.all([ |
| | | api.get('/system/menu/tree'), |
| | |
| | | this.syncCheckAllState() |
| | | }) |
| | | }).finally(() => { this.loading = false }) |
| | | |
| | | }, |
| | | handleScopeChange() { |
| | | this.selectedRoleIds = this.checkedMenuIds() |
| | | this.$nextTick(() => { |
| | | if (!this.$refs.permissionTree) return |
| | | this.$refs.permissionTree.setCheckedKeys(this.displayCheckedKeys(this.selectedRoleIds)) |
| | | this.syncCheckAllState() |
| | | }) |
| | | }, |
| | | renderContent(h, { data }) { |
| | | const label = data.menuType === 2 ? data.name + ' [按钮 ' + (data.permissions || '') + ']' : data.name |
| | |
| | | return [...new Set([...(tree.getCheckedKeys(false) || []), ...(tree.getHalfCheckedKeys() || [])].map(String))] |
| | | }, |
| | | syncCheckAllState() { |
| | | this.checkAll = this.checkedMenuIds().length === this.allMenuIds.length |
| | | const checked = this.checkedMenuIds() |
| | | this.selectedRoleIds = checked |
| | | this.checkAll = checked.length === this.allMenuIds.length |
| | | }, |
| | | toggleAll() { |
| | | if (!this.$refs.permissionTree) return |