From 4c117d87a531a91aba06c87e0efd47dd1f8a3c20 Mon Sep 17 00:00:00 2001 From: b2894lxlx <517289602@qq.com> Date: Tue, 27 Oct 2026 04:05:02 +0800 Subject: [PATCH] =?UTF-8?q?:sparkles:=20=E8=A7=92=E8=89=B2=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E6=9D=83=E9=99=90=E9=85=8D=E7=BD=AE=E5=B9=B6=E7=A7=BB?= =?UTF-8?q?=E9=99=A4=E7=94=A8=E6=88=B7=E4=BE=A7=E6=95=B0=E6=8D=AE=E6=9D=83?= =?UTF-8?q?=E9=99=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 角色权限弹窗支持按菜单批量设置数据范围;用户管理去掉组织/客商权限配置;角色别名改为角色标识。 Co-authored-by: Cursor --- src/api/system/roleDataScope.js | 19 +++ src/option/system/user.js | 23 --- src/views/authority/role.vue | 290 +++++++++++++++++++++----------- src/views/system/user.vue | 43 ----- 4 files changed, 209 insertions(+), 166 deletions(-) create mode 100644 src/api/system/roleDataScope.js diff --git a/src/api/system/roleDataScope.js b/src/api/system/roleDataScope.js new file mode 100644 index 0000000..5d0e4f1 --- /dev/null +++ b/src/api/system/roleDataScope.js @@ -0,0 +1,19 @@ +import request from '@/axios'; + +export const getRoleMenuDataScopeTree = roleId => { + return request({ + url: '/blade-system/role-menu-data-scope/tree', + method: 'get', + params: { + roleId, + }, + }); +}; + +export const submitRoleMenuDataScope = data => { + return request({ + url: '/blade-system/role-menu-data-scope/submit', + method: 'post', + data, + }); +}; diff --git a/src/option/system/user.js b/src/option/system/user.js index cd0a0ee..b450ba5 100644 --- a/src/option/system/user.js +++ b/src/option/system/user.js @@ -315,29 +315,6 @@ export const userOption = safe => { { label: '承运商', value: 2 }, ], }, - { - label: '数据权限范围', - prop: 'dataScopeRange', - type: 'radio', - span: 24, - value: 1, - dicData: [ - { label: '仅所属组织', value: 1 }, - { label: '全部组织', value: 2 }, - { label: '自定义', value: 3 }, - ], - }, - { - label: '数据层级范围', - prop: 'dataLevelRange', - type: 'radio', - span: 24, - value: 1, - dicData: [ - { label: '包含下级', value: 1 }, - { label: '仅本级', value: 2 }, - ], - }, { label: '备注', prop: 'remark', diff --git a/src/views/authority/role.vue b/src/views/authority/role.vue index e24252c..f17267c 100644 --- a/src/views/authority/role.vue +++ b/src/views/authority/role.vue @@ -50,7 +50,7 @@ title="角色权限配置" append-to-body v-model="box" - width="345px" + width="960px" @close="handleDialogClose" > @@ -100,41 +100,26 @@ align="middle" style="margin-bottom: 12px; background: #f5f7fa; padding: 6px 10px; border-radius: 4px" > - - - - - - - - 全选 - 反选 - + 勾选多个菜单后点击「设置」,可批量配置数据权限;设置后菜单旁展示当前范围 + 设置 + @@ -188,6 +173,45 @@ + + + + + + + + + 所在部门及下级 + 全部组织 + 本人创建 + 自定义组织 + + + + + + + + @@ -196,37 +220,44 @@ import { add, getList, getRole, - getRoleAlias, getRoleTreeById, grant, grantTree, remove, update, } from '@/api/system/role'; +import { getRoleMenuDataScopeTree, submitRoleMenuDataScope } from '@/api/system/roleDataScope'; +import { getDeptTree } from '@/api/system/dept'; import { mapGetters } from 'vuex'; import website from '@/config/website'; -import { validatenull } from '@/utils/validate'; export default { data() { return { form: {}, box: false, + dataScopeSettingBox: false, props: { label: 'title', value: 'key', }, menuGrantList: [], - dataScopeGrantList: [], apiScopeGrantList: [], apiGrantList: [], menuTreeObj: [], - dataScopeTreeObj: [], apiScopeTreeObj: [], menuLinked: false, - dataScopeLinked: false, apiScopeLinked: false, currentRoleIds: [], + currentRoleName: '', + roleDataScopeMenuTree: [], + roleDataScopeMap: {}, + deptTree: [], + dataScopeSetting: { + roleName: '', + scopeType: 2, + menuIds: [], + }, selectionList: [], query: {}, loading: true, @@ -309,32 +340,19 @@ export default { ], }, { - label: '角色别名', - labelTip: '用于权限校验与标注的属性,可手动录入也可点击现有别名快速录入', + label: '角色标识', + labelTip: '用于权限校验与标注的属性', prop: 'roleAlias', search: true, span: 24, rules: [ { required: true, - message: '请输入角色别名', + message: '请输入角色标识', trigger: 'blur', }, ], }, - { - label: '现有别名', - labelTip: '当前系统已存在的角色别名,点击可快速录入', - prop: 'currentAlias', - type: 'radio', - dicData: [], - props: { - label: 'roleName', - value: 'roleAlias', - }, - hide: true, - span: 24, - }, { label: '角色排序', prop: 'sort', @@ -378,14 +396,6 @@ export default { return ids; }, }, - watch: { - 'form.currentAlias'() { - const alias = this.form.currentAlias; - if (!validatenull(alias)) { - this.form.roleAlias = alias; - } - }, - }, methods: { initData(roleId) { getRoleTreeById(roleId).then(res => { @@ -452,9 +462,9 @@ export default { }, submit() { const menuList = this.$refs.treeMenu.getCheckedKeys(); - const dataScopeList = this.$refs.treeDataScope.getCheckedKeys(); const apiScopeList = this.$refs.treeApiScope.getCheckedKeys(); - grant(this.currentRoleIds, menuList, dataScopeList, apiScopeList).then(() => { + // 数据权限已改为角色菜单配置;传 null 跳过原生 dataScope 更新,避免误清历史配置 + grant(this.currentRoleIds, menuList, null, apiScopeList).then(() => { this.box = false; this.$message({ type: 'success', @@ -465,6 +475,84 @@ export default { this.onLoad(this.page); }); }, + getMenuScopeLabel(menuId) { + const scope = this.roleDataScopeMap[String(menuId)]; + return scope ? scope.scopeTypeName : ''; + }, + loadRoleDataScopeTree(roleId) { + return getRoleMenuDataScopeTree(roleId).then(res => { + const data = res.data.data || {}; + this.currentRoleName = data.roleName || ''; + this.roleDataScopeMenuTree = data.menuTree || []; + const scopeMap = {}; + (data.scopes || []).forEach(item => { + scopeMap[String(item.menuId)] = item; + }); + this.roleDataScopeMap = scopeMap; + }); + }, + openDataScopeSetting() { + const tree = this.$refs.treeRoleDataScope; + if (!tree) { + return; + } + const menuIds = tree.getCheckedKeys(); + if (!menuIds || menuIds.length === 0) { + this.$message.warning('请先勾选要设置的菜单'); + return; + } + this.dataScopeSetting = { + roleName: this.currentRoleName, + scopeType: 2, + menuIds, + }; + const loadDept = + this.deptTree && this.deptTree.length + ? Promise.resolve() + : getDeptTree(this.userInfo.tenantId).then(res => { + this.deptTree = res.data.data || []; + }); + loadDept.then(() => { + this.dataScopeSettingBox = true; + this.$nextTick(() => { + if (this.$refs.treeCustomDept) { + this.$refs.treeCustomDept.setCheckedKeys([]); + } + }); + }); + }, + submitDataScopeSetting() { + const roleId = this.currentRoleIds && this.currentRoleIds[0]; + if (!roleId) { + this.$message.warning('角色信息异常,请重新打开权限配置'); + return; + } + const scopeType = Number(this.dataScopeSetting.scopeType || 2); + let deptIds = []; + if (scopeType === 4) { + deptIds = this.$refs.treeCustomDept ? this.$refs.treeCustomDept.getCheckedKeys() : []; + if (!deptIds.length) { + this.$message.warning('自定义组织时请勾选组织'); + return; + } + } + submitRoleMenuDataScope({ + roleId, + menuIds: this.dataScopeSetting.menuIds, + scopeType, + deptIds, + }).then(() => { + this.$message.success('数据权限设置成功'); + this.dataScopeSettingBox = false; + this.loadRoleDataScopeTree(roleId).then(() => { + this.$nextTick(() => { + if (this.$refs.treeRoleDataScope) { + this.$refs.treeRoleDataScope.setCheckedKeys([]); + } + }); + }); + }); + }, rowSave(row, done, loading) { add(this.withTenantId(row)).then( () => { @@ -547,10 +635,6 @@ export default { this.form.parentId = ''; } } - getRoleAlias().then(res => { - const column = this.findColumn(this.option.column, 'currentAlias'); - column.dicData = res.data.data; - }); done(); }, handleRole() { @@ -563,58 +647,52 @@ export default { return; } this.menuTreeObj = []; - this.dataScopeTreeObj = []; this.apiScopeTreeObj = []; - // 保存当前要配置权限的角色ID this.currentRoleIds = this.idsArray; - grantTree().then(res => { - this.menuGrantList = res.data.data.menu; - this.dataScopeGrantList = res.data.data.dataScope; - this.apiScopeGrantList = res.data.data.apiScope; - getRole(this.ids).then(res => { - this.menuTreeObj = res.data.data.menu; - this.dataScopeTreeObj = res.data.data.dataScope; - this.apiScopeTreeObj = res.data.data.apiScope; - this.box = true; - this.$nextTick(() => { - this.applyCheckedKeys('treeMenu', this.menuTreeObj); - this.applyCheckedKeys('treeDataScope', this.dataScopeTreeObj); - this.applyCheckedKeys('treeApiScope', this.apiScopeTreeObj); - }); + this.currentRoleName = (this.selectionList[0] && this.selectionList[0].roleName) || ''; + const roleId = this.currentRoleIds[0]; + Promise.all([grantTree(), getRole(this.ids), this.loadRoleDataScopeTree(roleId)]).then(results => { + const grantRes = results[0]; + const roleRes = results[1]; + this.menuGrantList = grantRes.data.data.menu; + this.apiScopeGrantList = grantRes.data.data.apiScope; + this.menuTreeObj = roleRes.data.data.menu; + this.apiScopeTreeObj = roleRes.data.data.apiScope; + this.box = true; + this.$nextTick(() => { + this.applyCheckedKeys('treeMenu', this.menuTreeObj); + this.applyCheckedKeys('treeApiScope', this.apiScopeTreeObj); }); }); }, handleRowRole(row) { this.menuTreeObj = []; - this.dataScopeTreeObj = []; this.apiScopeTreeObj = []; - // 保存当前要配置权限的角色ID(单个行操作) this.currentRoleIds = [row.id]; - grantTree().then(res => { - this.menuGrantList = res.data.data.menu; - this.dataScopeGrantList = res.data.data.dataScope; - this.apiScopeGrantList = res.data.data.apiScope; - getRole(row.id).then(res => { - this.menuTreeObj = res.data.data.menu; - this.dataScopeTreeObj = res.data.data.dataScope; - this.apiScopeTreeObj = res.data.data.apiScope; - this.box = true; - this.$nextTick(() => { - this.applyCheckedKeys('treeMenu', this.menuTreeObj); - this.applyCheckedKeys('treeDataScope', this.dataScopeTreeObj); - this.applyCheckedKeys('treeApiScope', this.apiScopeTreeObj); - }); + this.currentRoleName = row.roleName || ''; + Promise.all([grantTree(), getRole(row.id), this.loadRoleDataScopeTree(row.id)]).then(results => { + const grantRes = results[0]; + const roleRes = results[1]; + this.menuGrantList = grantRes.data.data.menu; + this.apiScopeGrantList = grantRes.data.data.apiScope; + this.menuTreeObj = roleRes.data.data.menu; + this.apiScopeTreeObj = roleRes.data.data.apiScope; + this.box = true; + this.$nextTick(() => { + this.applyCheckedKeys('treeMenu', this.menuTreeObj); + this.applyCheckedKeys('treeApiScope', this.apiScopeTreeObj); }); }); }, handleDialogClose() { - // 对话框关闭时清空选择状态和权限树数据 this.menuTreeObj = []; - this.dataScopeTreeObj = []; this.apiScopeTreeObj = []; this.menuLinked = false; - this.dataScopeLinked = false; this.apiScopeLinked = false; + this.roleDataScopeMenuTree = []; + this.roleDataScopeMap = {}; + this.currentRoleName = ''; + this.dataScopeSettingBox = false; this.selectionClear(); }, handleDelete() { @@ -659,3 +737,15 @@ export default { }, }; + + diff --git a/src/views/system/user.vue b/src/views/system/user.vue index ae2f53a..20fcb3b 100644 --- a/src/views/system/user.vue +++ b/src/views/system/user.vue @@ -175,8 +175,6 @@ - 仅所属组织全部组织自定义 - 包含下级仅本级 - - - - -
包含新增的客商
- -