diff --git a/script/sql/zfjd-refactoring-v1/014-初始化角色.sql b/script/sql/zfjd-refactoring-v1/014-初始化角色.sql
index a141018b..ae918a2c 100644
--- a/script/sql/zfjd-refactoring-v1/014-初始化角色.sql
+++ b/script/sql/zfjd-refactoring-v1/014-初始化角色.sql
@@ -1,3 +1,14 @@
+-- 清空一期没有无效的角色
+delete sys_role where role_id not in (177
+194
+206
+209
+211
+212
+213
+214
+215);
+
INSERT INTO sys_role (role_id, tenant_id, role_name, role_key, role_sort, data_scope, menu_check_strictly, dept_check_strictly, status, del_flag, create_dept, create_by, create_time, update_by, update_time, remark, tenant_code, user_id, dept_id, sass_id, role_code, is_role_sys)
VALUES (1000, '000000', '查看全部业务数据角色', 'ViewAllDataRole', 1, '1', 1, 1, '0', '0', null, 0, '2025-01-10 15:08:12', 0, '2025-01-10 15:10:18', 'roleKey不可修改', null, '1', null, null, null, '1');
INSERT INTO sys_role (role_id, tenant_id, role_name, role_key, role_sort, data_scope, menu_check_strictly, dept_check_strictly, status, del_flag, create_dept, create_by, create_time, update_by, update_time, remark, tenant_code, user_id, dept_id, sass_id, role_code, is_role_sys)
diff --git a/zdxt-modules/zdxt-enforcement-code-common/src/main/java/com/zdxt/enforcementcode/service/IEfcodeVirtualUnitService.java b/zdxt-modules/zdxt-enforcement-code-common/src/main/java/com/zdxt/enforcementcode/service/IEfcodeVirtualUnitService.java
index 4e180438..b7a8e810 100644
--- a/zdxt-modules/zdxt-enforcement-code-common/src/main/java/com/zdxt/enforcementcode/service/IEfcodeVirtualUnitService.java
+++ b/zdxt-modules/zdxt-enforcement-code-common/src/main/java/com/zdxt/enforcementcode/service/IEfcodeVirtualUnitService.java
@@ -2,6 +2,7 @@ package com.zdxt.enforcementcode.service;
import com.zdxt.enforcementcode.domain.vo.EfcodeVirtualUnitVo;
import com.zdxt.enforcementcode.domain.vo.UnitUserVo;
+import com.zdxt.enforcementcode.domain.vo.VirtualUnitDeptTreeVo;
import com.zdxt.enforcementcode.domain.bo.EfcodeVirtualUnitBo;
import com.zdxt.enforcementcode.domain.bo.UnitUserBo;
import org.dromara.common.mybatis.core.page.TableDataInfo;
@@ -140,4 +141,15 @@ public interface IEfcodeVirtualUnitService {
* @param userIds 用户ID数组
*/
void deleteUsers(Long[] userIds);
+
+ /**
+ * 构建角色数据权限使用的虚拟单位部门树
+ *
+ * 树节点ID使用 vir_id 展示层级,节点携带 sysDeptId;
+ * checkedKeys 为角色已保存的 sys_dept_id 反查得到的 vir_id 列表。
+ *
+ * @param roleId 角色ID
+ * @return 虚拟单位部门树选择数据
+ */
+ VirtualUnitDeptTreeVo buildRoleDeptTree(Long roleId);
}
diff --git a/zdxt-modules/zdxt-enforcement-code-common/src/main/java/com/zdxt/enforcementcode/service/impl/EfcodeVirtualUnitServiceImpl.java b/zdxt-modules/zdxt-enforcement-code-common/src/main/java/com/zdxt/enforcementcode/service/impl/EfcodeVirtualUnitServiceImpl.java
index 6957ec8b..1781c39b 100644
--- a/zdxt-modules/zdxt-enforcement-code-common/src/main/java/com/zdxt/enforcementcode/service/impl/EfcodeVirtualUnitServiceImpl.java
+++ b/zdxt-modules/zdxt-enforcement-code-common/src/main/java/com/zdxt/enforcementcode/service/impl/EfcodeVirtualUnitServiceImpl.java
@@ -11,6 +11,9 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import cn.hutool.crypto.digest.DigestUtil;
+import cn.hutool.core.lang.tree.Tree;
+import cn.hutool.core.lang.tree.TreeUtil;
+import cn.hutool.core.lang.tree.TreeNodeConfig;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@@ -18,6 +21,7 @@ import com.zdxt.enforcementcode.domain.bo.EfcodeVirtualUnitBo;
import com.zdxt.enforcementcode.domain.bo.UnitUserBo;
import com.zdxt.enforcementcode.domain.vo.EfcodeVirtualUnitVo;
import com.zdxt.enforcementcode.domain.vo.UnitUserVo;
+import com.zdxt.enforcementcode.domain.vo.VirtualUnitDeptTreeVo;
import com.zdxt.enforcementcode.domain.EfcodeVirtualUnit;
import com.zdxt.enforcementcode.mapper.EfcodeVirtualUnitMapper;
import com.zdxt.enforcementcode.service.IEfcodeVirtualUnitService;
@@ -25,6 +29,7 @@ import org.dromara.system.domain.SysDept;
import org.dromara.system.domain.SysUser;
import org.dromara.system.mapper.SysDeptMapper;
import org.dromara.system.mapper.SysUserMapper;
+import org.dromara.system.service.ISysDeptService;
import com.zdxt.enforcementcode.domain.vo.SrzDeptVo;
import com.baomidou.mybatisplus.core.metadata.IPage;
@@ -46,6 +51,7 @@ public class EfcodeVirtualUnitServiceImpl implements IEfcodeVirtualUnitService {
private final SysDeptMapper sysDeptMapper;
private final SrzDeptMapper srzDeptMapper;
private final SysUserMapper sysUserMapper;
+ private final ISysDeptService sysDeptService;
/**
* 查询虚拟单位树
@@ -376,4 +382,57 @@ public class EfcodeVirtualUnitServiceImpl implements IEfcodeVirtualUnitService {
}
sysUserMapper.deleteByIds(List.of(userIds));
}
+
+ /**
+ * 构建角色数据权限使用的虚拟单位部门树
+ *
+ * 树节点ID使用 vir_id 展示层级,节点携带 sysDeptId;
+ * checkedKeys 为角色已保存的 sys_dept_id 反查得到的 vir_id 列表。
+ */
+ @Override
+ public VirtualUnitDeptTreeVo buildRoleDeptTree(Long roleId) {
+ List allUnits = queryTreeList();
+
+ // 收集全部 virId,并构建 sysDeptId -> virId 映射(用于反查勾选项)
+ Set allVirIds = new HashSet<>();
+ Map sysDeptIdToVirId = new HashMap<>();
+ for (EfcodeVirtualUnitVo u : allUnits) {
+ allVirIds.add(u.getVirId());
+ if (StringUtils.isNotBlank(u.getSysDeptId())) {
+ sysDeptIdToVirId.putIfAbsent(u.getSysDeptId(), u.getVirId());
+ }
+ }
+
+ // 计算根 parentId 集合:parentId 为空或不在所有 virId 中的节点视为根
+ Set rootParentIds = new LinkedHashSet<>();
+ for (EfcodeVirtualUnitVo u : allUnits) {
+ String pid = u.getVirParentId();
+ if (StringUtils.isBlank(pid) || !allVirIds.contains(pid)) {
+ rootParentIds.add(StringUtils.isBlank(pid) ? "0" : pid);
+ }
+ }
+
+ // 构建树:节点id=virId,label=virName,携带 sysDeptId
+ TreeNodeConfig config = new TreeNodeConfig().setNameKey("label");
+ List> depts = new ArrayList<>();
+ for (String rootPid : rootParentIds) {
+ depts.addAll(TreeUtil.build(allUnits, rootPid, config, (u, tree) -> {
+ tree.setId(u.getVirId());
+ tree.setParentId(StringUtils.isBlank(u.getVirParentId()) ? "0" : u.getVirParentId());
+ tree.setName(u.getVirName());
+ tree.setWeight(u.getCustOrderNum() != null ? u.getCustOrderNum() : u.getOrderNum());
+ tree.putExtra("sysDeptId", u.getSysDeptId());
+ }));
+ }
+
+ // checkedKeys:角色已保存的 sys_dept_id 反查为 vir_id
+ List deptSysIds = sysDeptService.selectDeptListByRoleId(roleId);
+ List checkedKeys = deptSysIds.stream()
+ .map(sysDeptIdToVirId::get)
+ .filter(Objects::nonNull)
+ .distinct()
+ .collect(Collectors.toList());
+
+ return new VirtualUnitDeptTreeVo(checkedKeys, depts);
+ }
}
diff --git a/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/controller/EfcodeVirtualUnitController.java b/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/controller/EfcodeVirtualUnitController.java
index d98bdba5..dd6621f4 100644
--- a/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/controller/EfcodeVirtualUnitController.java
+++ b/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/controller/EfcodeVirtualUnitController.java
@@ -19,6 +19,7 @@ import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.excel.utils.ExcelUtil;
import com.zdxt.enforcementcode.domain.vo.EfcodeVirtualUnitVo;
import com.zdxt.enforcementcode.domain.vo.UnitUserVo;
+import com.zdxt.enforcementcode.domain.vo.VirtualUnitDeptTreeVo;
import com.zdxt.enforcementcode.domain.bo.EfcodeVirtualUnitBo;
import com.zdxt.enforcementcode.domain.bo.UnitUserBo;
import com.zdxt.enforcementcode.service.IEfcodeVirtualUnitService;
@@ -66,6 +67,19 @@ public class EfcodeVirtualUnitController extends BaseController {
return R.ok(efcodeVirtualUnitService.queryBusinessTreeList());
}
+ /**
+ * 获取角色数据权限使用的虚拟单位部门树
+ *
+ * 树节点id使用 vir_id 展示层级,节点携带 sysDeptId;
+ * checkedKeys 为角色已保存的 sys_dept_id 反查得到的 vir_id 列表。
+ *
+ * @param roleId 角色ID
+ */
+ @GetMapping("/roleDeptTree/{roleId}")
+ public R roleDeptTree(@NotNull(message = "角色ID不能为空") @PathVariable Long roleId) {
+ return R.ok(efcodeVirtualUnitService.buildRoleDeptTree(roleId));
+ }
+
/**
* 根据虚拟单位分页查询关联人员列表
*
diff --git a/zdxt-web-client/zdxt-admin-plus-ui/src/api/system/role/index.ts b/zdxt-web-client/zdxt-admin-plus-ui/src/api/system/role/index.ts
index fb0fcabc..f65a9c21 100644
--- a/zdxt-web-client/zdxt-admin-plus-ui/src/api/system/role/index.ts
+++ b/zdxt-web-client/zdxt-admin-plus-ui/src/api/system/role/index.ts
@@ -146,10 +146,10 @@ export const authUserSelectAll = (data: any) => {
params: data
});
};
-// 根据角色ID查询部门树结构
+// 根据角色ID查询虚拟单位部门树结构(树节点id=vir_id,携带 sysDeptId;checkedKeys 为 vir_id)
export const deptTreeSelect = (roleId: string | number): AxiosPromise => {
return request({
- url: '/system/role/deptTree/' + roleId,
+ url: '/enforcementcode/virtualUnit/roleDeptTree/' + roleId,
method: 'get'
});
};
diff --git a/zdxt-web-client/zdxt-admin-plus-ui/src/api/system/role/types.ts b/zdxt-web-client/zdxt-admin-plus-ui/src/api/system/role/types.ts
index ffb1de6b..a1e67dc8 100644
--- a/zdxt-web-client/zdxt-admin-plus-ui/src/api/system/role/types.ts
+++ b/zdxt-web-client/zdxt-admin-plus-ui/src/api/system/role/types.ts
@@ -6,6 +6,8 @@ export interface DeptTreeOption {
label: string;
parentId: string;
weight: number;
+ /** 虚拟单位对应的部门ID,用于绑定角色-部门关系时保存 */
+ sysDeptId?: string;
children?: DeptTreeOption[];
}
diff --git a/zdxt-web-client/zdxt-admin-plus-ui/src/views/system/role/index-dept-separate.vue b/zdxt-web-client/zdxt-admin-plus-ui/src/views/system/role/index-dept-separate.vue
index e628a96d..ec0ff1df 100644
--- a/zdxt-web-client/zdxt-admin-plus-ui/src/views/system/role/index-dept-separate.vue
+++ b/zdxt-web-client/zdxt-admin-plus-ui/src/views/system/role/index-dept-separate.vue
@@ -176,7 +176,7 @@
-
+
diff --git a/zdxt-web-client/zdxt-admin-plus-ui/src/views/system/role/index.vue b/zdxt-web-client/zdxt-admin-plus-ui/src/views/system/role/index.vue
index 05487dd6..69f75e48 100644
--- a/zdxt-web-client/zdxt-admin-plus-ui/src/views/system/role/index.vue
+++ b/zdxt-web-client/zdxt-admin-plus-ui/src/views/system/role/index.vue
@@ -395,12 +395,33 @@ const getRoleMenuTreeselect = (roleId: string | number) => {
return res.data;
});
};
-/** 根据角色ID查询部门树结构 */
+/** 根据角色ID查询部门树结构(虚拟单位树:节点id=vir_id,携带 sysDeptId) */
const getRoleDeptTreeSelect = async (roleId: string | number) => {
const res = await deptTreeSelect(roleId);
deptOptions.value = res.data.depts;
+ // 构建 vir_id -> sys_dept_id 映射,供提交时绑定角色-部门关系使用
+ buildVirIdToSysDeptIdMap(res.data.depts);
return res.data;
};
+
+/** vir_id -> sys_dept_id 映射表 */
+const virIdToSysDeptId = new Map();
+
+/** 遍历虚拟单位树构建 vir_id -> sys_dept_id 映射 */
+const buildVirIdToSysDeptIdMap = (nodes: DeptTreeOption[]) => {
+ virIdToSysDeptId.clear();
+ const traverse = (list: DeptTreeOption[]) => {
+ for (const node of list) {
+ if (node.sysDeptId) {
+ virIdToSysDeptId.set(node.id, node.sysDeptId);
+ }
+ if (node.children?.length) {
+ traverse(node.children);
+ }
+ }
+ };
+ traverse(nodes || []);
+};
/** 树权限(展开/折叠)*/
const handleCheckedTreeExpand = (value: boolean, type: string) => {
if (type == 'menu') {
@@ -483,7 +504,11 @@ const handleDataScope = async (row: RoleVO) => {
/** 提交按钮(数据权限) */
const submitDataScope = async () => {
if (form.value.roleId) {
- form.value.deptIds = getDeptAllCheckedKeys();
+ // 勾选的树节点为 vir_id,绑定角色-部门关系时转换为 sys_dept_id 保存
+ const checkedVirIds = getDeptAllCheckedKeys() as Array;
+ form.value.deptIds = (checkedVirIds || [])
+ .map((virId) => virIdToSysDeptId.get(String(virId)))
+ .filter((sysDeptId): sysDeptId is string => !!sysDeptId);
await dataScope(form.value);
proxy?.$modal.msgSuccess('修改成功');
openDataScope.value = false;