From d0c73496379d8a57462ed93c523301f6badc9af6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BA=84=E9=94=90=E6=B3=A2?= <10549902+zhuangruibo@user.noreply.gitee.com> Date: Sun, 17 May 2026 20:08:40 +0800 Subject: [PATCH] =?UTF-8?q?=E6=89=A7=E6=B3=95=E7=AB=AF-=E8=AE=A1=E5=88=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../zfjd-refactoring-v1/015-索引优化.sql | 1 + .../common/util/DataFilterUtil.java | 91 +++- .../controller/BureauUnitController.java | 4 + .../enforcement/AppEnfLoginController.java | 39 +- .../src/api/enforcement/plan.js | 22 + .../router/enforcement-app/enf-main-router.js | 18 + .../src/store/Common.js | 42 +- .../src/views/enforcement/login.vue | 22 +- .../views/enforcement/my/enforcementMy.vue | 3 +- .../enforcement/my/plan/cp_plan_edit.vue | 437 ++++++++++++++++++ .../enforcement/my/plan/cp_plan_list.vue | 134 ++++++ .../enforcement/my/plan/cp_plan_mine.vue | 320 +++++++++++++ .../enforcement/my/plan/cp_plan_other.vue | 21 + 13 files changed, 1112 insertions(+), 42 deletions(-) create mode 100644 script/sql/zfjd-refactoring-v1/015-索引优化.sql create mode 100644 zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/controller/BureauUnitController.java create mode 100644 zdxt-web-client/zdxt-efcode-enforcement-app/src/views/enforcement/my/plan/cp_plan_edit.vue create mode 100644 zdxt-web-client/zdxt-efcode-enforcement-app/src/views/enforcement/my/plan/cp_plan_list.vue create mode 100644 zdxt-web-client/zdxt-efcode-enforcement-app/src/views/enforcement/my/plan/cp_plan_mine.vue create mode 100644 zdxt-web-client/zdxt-efcode-enforcement-app/src/views/enforcement/my/plan/cp_plan_other.vue diff --git a/script/sql/zfjd-refactoring-v1/015-索引优化.sql b/script/sql/zfjd-refactoring-v1/015-索引优化.sql new file mode 100644 index 00000000..703930b5 --- /dev/null +++ b/script/sql/zfjd-refactoring-v1/015-索引优化.sql @@ -0,0 +1 @@ +CREATE INDEX idx_qymc_tyshxydm ON sszt_jbxx110497_new(QYMC, TYSHXYDM); diff --git a/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/common/util/DataFilterUtil.java b/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/common/util/DataFilterUtil.java index 62fbe808..b0a8bd43 100644 --- a/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/common/util/DataFilterUtil.java +++ b/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/common/util/DataFilterUtil.java @@ -342,13 +342,24 @@ public class DataFilterUtil { * @throws IllegalStateException 当 unitTypeCode=99 或递归查找失败时抛出 */ public static String getUserOrganId(Long userId) { + SrzDeptVo organDept = getUserOrganDept(userId); + return organDept != null ? organDept.getOrganizationid() : null; + } + + /** + * 查询指定用户所在的认证机构(unitTypeCode=10)对应的 SrzDeptVo 对象。 + * + * @param userId 用户ID + * @return 认证机构对应的 SrzDeptVo;如果用户不存在或未找到则返回 null + */ + public static SrzDeptVo getUserOrganDept(Long userId) { String deptId = getUserDeptId(userId); if (deptId == null) { return null; } SrzDeptMapper srzDeptMapper = SpringUtils.getBean(SrzDeptMapper.class); - return findOrganIdByDeptId(srzDeptMapper, deptId, 0); + return findOrganDeptByDeptId(srzDeptMapper, deptId, 0); } /** @@ -357,9 +368,9 @@ public class DataFilterUtil { * @param srzDeptMapper Mapper * @param organizationId 当前机构ID * @param depth 递归深度(防歿循环) - * @return unitTypeCode=10 的 organizationId + * @return unitTypeCode=10 的 SrzDeptVo 对象 */ - private static String findOrganIdByDeptId(SrzDeptMapper srzDeptMapper, String organizationId, int depth) { + private static SrzDeptVo findOrganDeptByDeptId(SrzDeptMapper srzDeptMapper, String organizationId, int depth) { if (StrUtil.isBlank(organizationId)) { return null; } @@ -380,11 +391,11 @@ public class DataFilterUtil { "用户所在机构(organizationId=" + organizationId + ")的 unitTypeCode=99,不合法的机构类型"); } if ("10".equals(unitTypeCode)) { - return srzDept.getOrganizationid(); + return srzDept; } if ("11".equals(unitTypeCode)) { // 递归查找父级 - return findOrganIdByDeptId(srzDeptMapper, srzDept.getParentid(), depth + 1); + return findOrganDeptByDeptId(srzDeptMapper, srzDept.getParentid(), depth + 1); } // 其他未知的 unitTypeCode,返回 null @@ -392,21 +403,31 @@ public class DataFilterUtil { } public static String getUserDeptId(Long userId) { + SysDeptVo userSysDept = getUserSysDept(userId); + if (userSysDept == null || userSysDept.getDeptId() == null) { + return null; + } + return String.valueOf(userSysDept.getDeptId()); + } + + /** + * 根据 userId 查询用户的 UserDTO 对象。 + * + * @param userId 用户ID + * @return UserDTO 对象;如果用户不存在则返回 null + */ + public static SysDeptVo getUserSysDept(Long userId) { if (userId == null) { return null; } - // 1. 通过 userId 获取用户的 deptId UserService userService = SpringUtils.getBean(UserService.class); List users = userService.selectListByIds(Collections.singletonList(userId)); if (CollUtil.isEmpty(users)) { return null; } - UserDTO user = users.get(0); - if (user.getDeptId() == null) { - return null; - } - String deptId = String.valueOf(user.getDeptId()); - return deptId; + SysDeptVo userSysDept = new SysDeptVo(); + userSysDept.setDeptId(String.valueOf(users.get(0).getDeptId())); + return userSysDept; } // ======================== 用户执法单位查询方法 ======================== @@ -428,6 +449,28 @@ public class DataFilterUtil { * @throws IllegalStateException 当某层匹配到多条 vir_show_at_business='是' 的记录,或多条匹配但无法确定唯一执法单位时抛出 */ public static String getUserBureauDeptId(Long userId) { + SysDeptVo dept = getUserBureauDept(userId); + return dept != null ? dept.getDeptId() : null; + } + + /** + * 查询指定用户所在的执法单位的 SysDeptVo 对象。 + *

+ * 逻辑: + *

    + *
  1. 通过 userId 查询用户的 dept_id
  2. + *
  3. 用 dept_id 查找 efcode_virtual_unit(按 sys_dept_id 匹配)
  4. + *
  5. 若存在匹配记录,优先返回 vir_show_at_business='是' 的记录对应的 SysDeptVo; + * 若无 business 记录且只有一条匹配也直接返回
  6. + *
  7. 若不存在匹配记录,通过 sys_dept 查找父节点,再用父节点 dept_id 重复上述查找
  8. + *
  9. 递归向上最多查 4 层父节点
  10. + *
+ * + * @param userId 用户ID + * @return 用户所在执法单位的 SysDeptVo;如果用户不存在、未分配部门或向上 4 层仍未找到则返回 null + * @throws IllegalStateException 当某层匹配到多条 vir_show_at_business='是' 的记录,或多条匹配但无法确定唯一执法单位时抛出 + */ + public static SysDeptVo getUserBureauDept(Long userId) { if (userId == null) { return null; } @@ -458,22 +501,24 @@ public class DataFilterUtil { .filter(v -> "是".equals(v.getVirShowAtBusiness())) .collect(Collectors.toList()); + String foundDeptId = null; if (businessUnits.size() == 1) { - return businessUnits.get(0).getSysDeptId(); - } - if (businessUnits.size() > 1) { + foundDeptId = businessUnits.get(0).getSysDeptId(); + } else if (businessUnits.size() > 1) { throw new IllegalStateException( "用户(userId=" + userId + ")的部门(deptId=" + currentDeptId + ")在虚拟单位表中匹配到多条 vir_show_at_business='是' 的记录,无法确定唯一执法单位"); + } else if (allMatched.size() == 1) { + // 没有 business 记录,如果只有一条匹配则返回 + foundDeptId = allMatched.get(0).getSysDeptId(); + } else { + // 多条匹配但无 business 标记,无法确定唯一执法单位 + throw new IllegalStateException( + "用户(userId=" + userId + ")的部门(deptId=" + currentDeptId + + ")在虚拟单位表中匹配到多条记录且无 vir_show_at_business='是',无法确定唯一执法单位"); } - // 没有 business 记录,如果只有一条匹配则返回 - if (allMatched.size() == 1) { - return allMatched.get(0).getSysDeptId(); - } - // 多条匹配但无 business 标记,无法确定唯一执法单位 - throw new IllegalStateException( - "用户(userId=" + userId + ")的部门(deptId=" + currentDeptId - + ")在虚拟单位表中匹配到多条记录且无 vir_show_at_business='是',无法确定唯一执法单位"); + + return sysDeptService.selectDeptById(foundDeptId); } // 不存在匹配记录,通过 sys_dept 查找父节点 diff --git a/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/controller/BureauUnitController.java b/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/controller/BureauUnitController.java new file mode 100644 index 00000000..9bf23583 --- /dev/null +++ b/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/controller/BureauUnitController.java @@ -0,0 +1,4 @@ +package com.zdxt.enforcementcode.controller; + +public class BureauUnitController { +} diff --git a/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/controller/app/enforcement/AppEnfLoginController.java b/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/controller/app/enforcement/AppEnfLoginController.java index 70e556ff..1cd4dcdd 100644 --- a/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/controller/app/enforcement/AppEnfLoginController.java +++ b/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/controller/app/enforcement/AppEnfLoginController.java @@ -1,7 +1,9 @@ package com.zdxt.enforcementcode.controller.app.enforcement; import cn.dev33.satoken.annotation.SaIgnore; +import com.zdxt.enforcementcode.common.util.DataFilterUtil; import com.zdxt.enforcementcode.controller.app.LoginController; +import com.zdxt.enforcementcode.domain.vo.SrzDeptVo; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.dromara.common.core.domain.R; @@ -75,18 +77,30 @@ public class AppEnfLoginController extends LoginController { } // 7. 查询部门信息 - String deptName = ""; - if (user.getDeptId() != null && !user.getDeptId().isBlank()) { - SysDeptVo dept = sysDeptService.selectDeptById(user.getDeptId()); - if (dept != null) { - deptName = dept.getDeptName(); - } - } + SrzDeptVo srzOrgan = DataFilterUtil.getUserOrganDept(user.getUserId()); + SysDeptVo sysDept = DataFilterUtil.getUserSysDept(user.getUserId()); + SysDeptVo bureauDept = DataFilterUtil.getUserBureauDept(user.getUserId()); // 7. 构建LoginUser并生成SaToken String token = doSaTokenLogin(user.getUserId(), user.getUserName(), user.getNickName(), user.getDeptId(), "enforcement_user", "enforcement_app", "enforcement"); + + // 验证关键组织信息不能为空 + if (srzOrgan == null) { + return R.fail("该用户未关联认证机构,无法登录执法端"); + } + if (sysDept == null) { + return R.fail("该用户未关联部门,无法登录执法端"); + } + if (bureauDept == null) { + return R.fail("该用户未关联执法单位,无法登录执法端"); + } + + if (!sysDept.getDeptId().equals(user.getDeptId())){ + return R.fail("部门ID查找错误!"); + } + // 8. 构造返回数据 Map data = new HashMap<>(); data.put("token", token); @@ -95,8 +109,15 @@ public class AppEnfLoginController extends LoginController { data.put("loginName", user.getLoginName()); data.put("nickName", user.getNickName()); data.put("phonenumber", user.getPhonenumber() != null ? user.getPhonenumber() : ""); - data.put("deptId", user.getDeptId() != null ? user.getDeptId() : ""); - data.put("deptName", deptName); + + data.put("deptId", user.getDeptId()); + data.put("deptName", sysDept.getDeptName()); + + data.put("organId", srzOrgan.getOrganizationid()); + data.put("organName", srzOrgan.getName()); + + data.put("bureauUnitId", bureauDept.getDeptId()); + data.put("bureauUnitName", bureauDept.getDeptId()); return R.ok(data); } diff --git a/zdxt-web-client/zdxt-efcode-enforcement-app/src/api/enforcement/plan.js b/zdxt-web-client/zdxt-efcode-enforcement-app/src/api/enforcement/plan.js index e69de29b..ac2327fc 100644 --- a/zdxt-web-client/zdxt-efcode-enforcement-app/src/api/enforcement/plan.js +++ b/zdxt-web-client/zdxt-efcode-enforcement-app/src/api/enforcement/plan.js @@ -0,0 +1,22 @@ +import { _get, _post, _put, _delete } from "../../http/index"; + +// region 计划管理接口 + +const planBaseUrl = "/app-enf/cpPlan"; + +// 计划列表(分页) +export const getPlanList = (params, success, error) => _get(planBaseUrl + "/list", params, success, error); + +// 计划详情 +export const getPlanDetail = (id, success, error) => _get(planBaseUrl + "/" + id, {}, success, error); + +// 新增计划 +export const addPlan = (params, success, error) => _post(planBaseUrl, params, success, error); + +// 编辑计划 +export const editPlan = (params, success, error) => _put(planBaseUrl, params, success, error); + +// 删除计划 +export const deletePlan = (ids, success, error) => _delete(planBaseUrl + "/" + ids, {}, success, error); + +// endregion diff --git a/zdxt-web-client/zdxt-efcode-enforcement-app/src/router/enforcement-app/enf-main-router.js b/zdxt-web-client/zdxt-efcode-enforcement-app/src/router/enforcement-app/enf-main-router.js index 306b5ea5..d51120dc 100644 --- a/zdxt-web-client/zdxt-efcode-enforcement-app/src/router/enforcement-app/enf-main-router.js +++ b/zdxt-web-client/zdxt-efcode-enforcement-app/src/router/enforcement-app/enf-main-router.js @@ -63,6 +63,24 @@ const routes = [ isKeepAlive: true, }, }, + // 执法端-计划列表 + { + path: "/enforcement/plan", + name: "cpPlanList", + component: () => import("@/views/enforcement/my/plan/cp_plan_list.vue"), + meta: { + isKeepAlive: false, + }, + }, + // 执法端-计划编辑(新增/编辑) + { + path: "/enforcement/plan/edit", + name: "cpPlanEdit", + component: () => import("@/views/enforcement/my/plan/cp_plan_edit.vue"), + meta: { + isKeepAlive: false, + }, + }, ]; export {routes}; diff --git a/zdxt-web-client/zdxt-efcode-enforcement-app/src/store/Common.js b/zdxt-web-client/zdxt-efcode-enforcement-app/src/store/Common.js index 8690975f..cf635341 100644 --- a/zdxt-web-client/zdxt-efcode-enforcement-app/src/store/Common.js +++ b/zdxt-web-client/zdxt-efcode-enforcement-app/src/store/Common.js @@ -12,8 +12,18 @@ export default defineStore('useCommon', { enterpriseId:"", //当前登录用户ID userId:"", - //执法主体 - orgId:"", + //部门ID + deptId:"", + //部门名称 + deptName:"", + //认证机构ID + organId:"", + //认证机构名称 + organName:"", + //执法单位ID + bureauUnitId:"", + //执法单位名称 + bureauUnitName:"", // token token: "", //当前登录用户的手机号 @@ -53,9 +63,29 @@ export default defineStore('useCommon', { SET_USER_ID(data){ this.userId = data; }, - //设置执法主体ID - SET_ORG_ID(data){ - this.orgId = data; + //设置部门ID + SET_DEPT_ID(data){ + this.deptId = data; + }, + //设置部门名称 + SET_DEPT_NAME(data){ + this.deptName = data; + }, + //设置认证机构ID + SET_ORGAN_ID(data){ + this.organId = data; + }, + //设置认证机构名称 + SET_ORGAN_NAME(data){ + this.organName = data; + }, + //设置执法单位ID + SET_BUREAU_UNIT_ID(data){ + this.bureauUnitId = data; + }, + //设置执法单位名称 + SET_BUREAU_UNIT_NAME(data){ + this.bureauUnitName = data; }, //设置用户token SET_TOKEN(data){ @@ -115,6 +145,6 @@ export default defineStore('useCommon', { }, persist: { storage: sessionStorage, - pick: ['token', 'userId', 'enterpriseNumber', 'enterpriseName', 'enterpriseId', 'phonenumber', 'orgId', 'hasLaw'], + pick: ['token', 'userId', 'enterpriseNumber', 'enterpriseName', 'enterpriseId', 'phonenumber', 'deptId', 'deptName', 'organId', 'organName', 'bureauUnitId', 'bureauUnitName', 'hasLaw'], }, }); diff --git a/zdxt-web-client/zdxt-efcode-enforcement-app/src/views/enforcement/login.vue b/zdxt-web-client/zdxt-efcode-enforcement-app/src/views/enforcement/login.vue index cf2799aa..ade35062 100644 --- a/zdxt-web-client/zdxt-efcode-enforcement-app/src/views/enforcement/login.vue +++ b/zdxt-web-client/zdxt-efcode-enforcement-app/src/views/enforcement/login.vue @@ -73,11 +73,29 @@ const encryptedKey = Encrypt(secretKey); enforcementLogin({"secretName": secretName, "secretKey": encryptedKey}, response => { if (response.code === 200) { + // 验证关键组织信息 + if (!response.data.deptId) { + showFailToast("该用户未关联部门,无法登录"); + return; + } + if (!response.data.organId) { + showFailToast("该用户未关联认证机构,无法登录"); + return; + } + if (!response.data.bureauUnitId) { + showFailToast("该用户未关联执法单位,无法登录"); + return; + } // 执法端登录成功 → 赋值用户基本信息 - useCommon.SET_USER_PHONENUMBER(response.data.phonenumber.toString()); + useCommon.SET_USER_PHONENUMBER(response.data.phonenumber || ""); useCommon.SET_USER_ID(response.data.userId); useCommon.SET_TOKEN(response.data.token); - useCommon.SET_ORG_ID(response.data.deptId || ""); + useCommon.SET_DEPT_ID(response.data.deptId); + useCommon.SET_DEPT_NAME(response.data.deptName || ""); + useCommon.SET_ORGAN_ID(response.data.organId); + useCommon.SET_ORGAN_NAME(response.data.organName || ""); + useCommon.SET_BUREAU_UNIT_ID(response.data.bureauUnitId); + useCommon.SET_BUREAU_UNIT_NAME(response.data.bureauUnitName || ""); console.log("enforcement login success", useCommon.userId); router.push({name: "enforcementHome"}); } else { diff --git a/zdxt-web-client/zdxt-efcode-enforcement-app/src/views/enforcement/my/enforcementMy.vue b/zdxt-web-client/zdxt-efcode-enforcement-app/src/views/enforcement/my/enforcementMy.vue index 67f47e81..cc665352 100644 --- a/zdxt-web-client/zdxt-efcode-enforcement-app/src/views/enforcement/my/enforcementMy.vue +++ b/zdxt-web-client/zdxt-efcode-enforcement-app/src/views/enforcement/my/enforcementMy.vue @@ -128,8 +128,7 @@ const onMenuClick = (item) => { }); break; case 'plan': - // TODO: 对接执法计划列表页 - showToast('执法计划功能开发中'); + router.push({ path: '/enforcement/plan' }); break; case 'setting': // TODO: 对接设置页 diff --git a/zdxt-web-client/zdxt-efcode-enforcement-app/src/views/enforcement/my/plan/cp_plan_edit.vue b/zdxt-web-client/zdxt-efcode-enforcement-app/src/views/enforcement/my/plan/cp_plan_edit.vue new file mode 100644 index 00000000..7fbb3cd3 --- /dev/null +++ b/zdxt-web-client/zdxt-efcode-enforcement-app/src/views/enforcement/my/plan/cp_plan_edit.vue @@ -0,0 +1,437 @@ + + + + + diff --git a/zdxt-web-client/zdxt-efcode-enforcement-app/src/views/enforcement/my/plan/cp_plan_list.vue b/zdxt-web-client/zdxt-efcode-enforcement-app/src/views/enforcement/my/plan/cp_plan_list.vue new file mode 100644 index 00000000..c93852ab --- /dev/null +++ b/zdxt-web-client/zdxt-efcode-enforcement-app/src/views/enforcement/my/plan/cp_plan_list.vue @@ -0,0 +1,134 @@ + + + + + diff --git a/zdxt-web-client/zdxt-efcode-enforcement-app/src/views/enforcement/my/plan/cp_plan_mine.vue b/zdxt-web-client/zdxt-efcode-enforcement-app/src/views/enforcement/my/plan/cp_plan_mine.vue new file mode 100644 index 00000000..1ea16ab3 --- /dev/null +++ b/zdxt-web-client/zdxt-efcode-enforcement-app/src/views/enforcement/my/plan/cp_plan_mine.vue @@ -0,0 +1,320 @@ + + + + + diff --git a/zdxt-web-client/zdxt-efcode-enforcement-app/src/views/enforcement/my/plan/cp_plan_other.vue b/zdxt-web-client/zdxt-efcode-enforcement-app/src/views/enforcement/my/plan/cp_plan_other.vue new file mode 100644 index 00000000..af5dd691 --- /dev/null +++ b/zdxt-web-client/zdxt-efcode-enforcement-app/src/views/enforcement/my/plan/cp_plan_other.vue @@ -0,0 +1,21 @@ + + + + +