Browse Source

数据权限过滤

dev-V1.0.1
庄锐波 6 months ago
parent
commit
ad08a8ed68
  1. 25
      doc/执法码数据权限过滤使用说明.md
  2. 35
      script/sql/zfjd-refactoring-v1/013-计划任务表设计.sql
  3. 75
      zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/common/util/DataFilterUtil.java

25
doc/执法码数据权限过滤使用说明.md

@ -244,13 +244,13 @@ public TableDataInfo<TestEnfDemoVo> directFilterPageList(TestEnfDemoBo bo, PageQ
|----------|--------|------|
| `getUserDeptId(userId)` | `String` | 获取用户的 dept_id(来源 sys_user 表) |
| `getUserOrganId(userId)` | `String` | 查询用户所属执法单位的 organizationId(来源 srz_dept 表,向上递归) |
| `getUserBureauDeptId(userId)` | `String` | 查询用户所在执法单位的 vir_id(来源 efcode_virtual_unit 表) |
| `getUserBureauDeptId(userId)` | `String` | 查询用户所在执法单位的 sys_dept_id(沿 sys_dept 父链向上递归查找 efcode_virtual_unit) |
#### 5.4.1 getUserDeptId
#### 5.4.1 getUserDeptId 获取用户所在的部门ID
通过 `UserService.selectListByIds()` 查询用户的 `dept_id` 并返回字符串。
#### 5.4.2 getUserOrganId
#### 5.4.2 getUserOrganId 获取用户所在的单位ID,有可能和部门ID相同
```
userId → getUserDeptId → deptId
@ -261,17 +261,22 @@ deptId → srz_dept.organizationId 匹配
(最大递归深度:4层)
```
#### 5.4.3 getUserBureauDeptId
#### 5.4.3 getUserBureauDeptId 获取用户所在的执法单位ID有可能和部门ID相同,单位ID相同
```
userId → getUserDeptId → deptId
deptId → efcode_virtual_unit.sys_dept_id 匹配
├─ 筛选 vir_show_at_business='是' 的记录
│ ├─ 恰好1条 → 返回 vir_id
循环(自身 + 最多4层父节点,共5层):
currentDeptId → efcode_virtual_unit.sys_dept_id 匹配
├─ 存在匹配记录
│ ├─ 筛选 vir_show_at_business='是' 的记录
│ │ ├─ 恰好1条 → 返回该记录的 sys_dept_id
│ │ └─ 多条 → 抛出异常
│ └─ 无 vir_show_at_business='是' 的记录
│ ├─ 总匹配只有1条 → 返回该记录的 sys_dept_id
│ └─ 多条 → 抛出异常
└─ 无 vir_show_at_business='是' 的记录
├─ 总匹配只有1条 → 返回 vir_id
└─ 多条 → 抛出异常
└─ 无匹配记录
└─ 通过 sys_dept 查找 parentId → currentDeptId = parentId → 继续下一层
到达根节点或超过4层仍未找到 → 返回 null
```
### 5.5 常量定义

35
script/sql/zfjd-refactoring-v1/013-计划任务表设计.sql

@ -1,7 +1,6 @@
DROP TABLE IF EXISTS `enforcement_law_check_plan`;
CREATE TABLE `enforcement_law_check_plan` (
CREATE TABLE `efcode_cp_plan`
(
`id` varchar(50) NOT NULL COMMENT '主键ID',
-- `plan_code` varchar(32) NOT NULL COMMENT '计划编号(唯一)',
`plan_type` tinyint NOT NULL COMMENT '计划类别 1=日常计划 2=专项计划',
`plan_date` varchar(16) NOT NULL COMMENT '计划执行日期(如 2025-05-08)',
`plan_time` tinyint NOT NULL COMMENT '执行时段 1=上午 2=下午 3=其他',
@ -14,7 +13,6 @@ CREATE TABLE `enforcement_law_check_plan` (
`is_public` tinyint NOT NULL DEFAULT 1 COMMENT '是否公开 1=是 0=否',
`is_union` tinyint NOT NULL DEFAULT 1 COMMENT '是否联合执法 1=是 0=否',
`union_dept` varchar(500) DEFAULT NULL COMMENT '联合执法单位(多个逗号分隔)',
-- `status` tinyint NOT NULL DEFAULT 1 COMMENT '状态 1=草稿 2=已提交 3=已执行 4=已作废',
`reserve_status` tinyint NOT NULL DEFAULT 0 COMMENT '预约状态 0=待预约 1=预约中 2=预约完成 3=停止预约',
`create_by` varchar(64) DEFAULT '' COMMENT '创建者',
`create_dept` varchar(64) DEFAULT NULL COMMENT '创建人部门',
@ -26,10 +24,35 @@ CREATE TABLE `enforcement_law_check_plan` (
PRIMARY KEY (`id`),
KEY `idx_dept_id` (`dept_id`),
KEY `idx_reserve_status` (`reserve_status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='行政执法检查计划表';
) comment '行政执法检查计划-计划表' row_format = DYNAMIC;
CREATE TABLE `efcode_cp_task`(
) comment '行政执法检查计划-计划参与人员表' row_format = DYNAMIC;
CREATE TABLE `efcode_cp_task`(
) comment '行政执法检查计划-任务表' row_format = DYNAMIC;
CREATE TABLE `efcode_cp_task`(
) comment '行政执法检查计划-预约表' row_format = DYNAMIC;
CREATE TABLE `efcode_cp_task`(
) comment '行政执法检查计划-预告表' row_format = DYNAMIC;
CREATE TABLE `efcode_cp_task`(
) comment '行政执法检查计划-预告交流表' row_format = DYNAMIC;
CREATE TABLE `efcode_cp_setting`(
) comment '行政执法检查计划-设置表' row_format = DYNAMIC;
DROP TABLE IF EXISTS `enforcement_law_notice`;
CREATE TABLE `enforcement_law_notice` (
CREATE TABLE `enforcement_law_notice`
(
`id` varchar(50) NOT NULL COMMENT '主键ID',
`plan_id` bigint DEFAULT NULL COMMENT '导入的计划ID(关联执法计划表)',
`enforce_date` varchar(16) NOT NULL COMMENT '执法日期',

75
zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/common/util/DataFilterUtil.java

@ -20,6 +20,8 @@ import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.system.domain.vo.SysDeptVo;
import org.dromara.system.service.ISysDeptService;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class DataFilterUtil {
@ -409,70 +411,81 @@ public class DataFilterUtil {
// ======================== 用户执法单位查询方法 ========================
/**
* 查询指定用户所在的执法单位的 vir_id。
* 查询指定用户所在的执法单位的 sys_dept_id。
* <p>
* 逻辑:
* <ol>
* <li>通过 userId 查询用户的 dept_id</li>
* <li>用 dept_id 匹配 efcode_virtual_unit.sys_dept_id</li>
* <li>优先返回 vir_show_at_business='是' 的记录的 vir_id</li>
* <li>如果 vir_show_at_business='是' 的有多条,抛出异常</li>
* <li>如果没有 vir_show_at_business='是' 的记录,且只有一条匹配 sys_dept_id 的记录,也直接返回</li>
* <li>用 dept_id 查找 efcode_virtual_unit(按 sys_dept_id 匹配)</li>
* <li>若存在匹配记录,优先返回 vir_show_at_business='是' 的记录的 sys_dept_id;
* 若无 business 记录且只有一条匹配也直接返回</li>
* <li>若不存在匹配记录,通过 sys_dept 查找父节点,再用父节点 dept_id 重复上述查找</li>
* <li>递归向上最多查 4 层父节点</li>
* </ol>
*
* @param userId 用户ID
* @return 用户所在执法单位的 vir_id;如果用户不存在或未分配部门则返回 null
* @throws IllegalStateException 当匹配到多条 vir_show_at_business='是' 的记录时抛出
* @return 用户所在执法单位的 sys_dept_id;如果用户不存在、未分配部门或向上 4 层仍未找到则返回 null
* @throws IllegalStateException 当某层匹配到多条 vir_show_at_business='是' 的记录,或多条匹配但无法确定唯一执法单位时抛出
*/
public static String getUserBureauDeptId(Long userId) {
if (userId == null) {
return null;
}
// 1. 通过 userId 获取用户的 deptId
UserService userService = SpringUtils.getBean(UserService.class);
List<UserDTO> users = userService.selectListByIds(Collections.singletonList(userId));
if (CollUtil.isEmpty(users)) {
return null;
}
UserDTO user = users.get(0);
if (user.getDeptId() == null) {
String deptId = getUserDeptId(userId);
if (StrUtil.isBlank(deptId)) {
return null;
}
String deptId = String.valueOf(user.getDeptId());
// 2. 通过 deptId 查询 efcode_virtual_unit 中所有匹配 sys_dept_id 的记录
// 2. 从当前 deptId 开始,向上查找 sys_dept 父链,最多查 5 层(自身 + 4 层父节点)
IEfcodeVirtualUnitService virtualUnitService = SpringUtils.getBean(IEfcodeVirtualUnitService.class);
ISysDeptService sysDeptService = SpringUtils.getBean(ISysDeptService.class);
String currentDeptId = deptId;
for (int i = 0; i < 5; i++) {
if (StrUtil.isBlank(currentDeptId)) {
break;
}
// 查询 efcode_virtual_unit 中所有匹配 sys_dept_id 的记录
EfcodeVirtualUnitBo bo = new EfcodeVirtualUnitBo();
bo.setSysDeptId(deptId);
bo.setSysDeptId(currentDeptId);
List<EfcodeVirtualUnitVo> allMatched = virtualUnitService.queryList(bo);
if (CollUtil.isEmpty(allMatched)) {
return null;
}
// 3. 筛选 vir_show_at_business='是' 的记录
if (CollUtil.isNotEmpty(allMatched)) {
// 筛选 vir_show_at_business='是' 的记录
List<EfcodeVirtualUnitVo> businessUnits = allMatched.stream()
.filter(v -> "是".equals(v.getVirShowAtBusiness()))
.collect(Collectors.toList());
if (businessUnits.size() == 1) {
// 恰好一条业务记录,直接返回
return businessUnits.get(0).getVirId();
return businessUnits.get(0).getSysDeptId();
}
if (businessUnits.size() > 1) {
// 多条业务记录,抛出异常
throw new IllegalStateException(
"用户(userId=" + userId + ")的部门(deptId=" + deptId
"用户(userId=" + userId + ")的部门(deptId=" + currentDeptId
+ ")在虚拟单位表中匹配到多条 vir_show_at_business='是' 的记录,无法确定唯一执法单位");
}
// 4. 没有 vir_show_at_business='是' 的记录,如果只有一条匹配记录则返回
// 没有 business 记录,如果只有一条匹配则返回
if (allMatched.size() == 1) {
return allMatched.get(0).getVirId();
return allMatched.get(0).getSysDeptId();
}
// 多条匹配但无法确定唯一执法单位
// 多条匹配但无 business 标记,无法确定唯一执法单位
throw new IllegalStateException(
"无法找到当前用户所在的执法单位!");
"用户(userId=" + userId + ")的部门(deptId=" + currentDeptId
+ ")在虚拟单位表中匹配到多条记录且无 vir_show_at_business='是',无法确定唯一执法单位");
}
// 不存在匹配记录,通过 sys_dept 查找父节点
SysDeptVo dept = sysDeptService.selectDeptById(currentDeptId);
if (dept == null || StrUtil.isBlank(dept.getParentId()) || "0".equals(dept.getParentId())) {
break;
}
currentDeptId = dept.getParentId();
}
// 向上查找 4 层仍未找到对应的虚拟单位
return null;
}
// ======================== 私有辅助方法 ========================

Loading…
Cancel
Save