Ver Fonte

fix: 前端判断归一

tanzx há 6 dias atrás
pai
commit
78506c7437

+ 38 - 4
src/views/position/positionManagement/components/PositionEditDialog.vue

@@ -855,6 +855,26 @@ export default {
       if (!this.form) return;
       this.form.type = this.resolveTypeValue(this.form.type);
     },
+    /**
+     * 所属部门归一(dept_id 为 NOT NULL 的历史列,界面已无该表单项)。
+     * 历史数据里这列存的是「机构 id」,也有部分脏数据指向已删除组织;
+     * 这里只把「既不是现存部门、也不是任何机构 id」的野值回落到当前法人,正常值原样保留。
+     */
+    normalizeDeptId() {
+      if (!this.form) return;
+      const deptKey = String(this.form.deptId ?? "").trim();
+      if (!deptKey) {
+        this.form.deptId = this.form.legalId ?? null;
+        return;
+      }
+      const inDept = this.departments.some(
+        (item) => String(item.id) === deptKey,
+      );
+      const inOrg = this.legalEntities.some(
+        (item) => String(item.id) === deptKey,
+      );
+      if (!inDept && !inOrg) this.form.deptId = this.form.legalId ?? null;
+    },
     // 岗位序列的启用层级:直接从 sequenceList 的 children 取,不调接口(按序列名称)
     // 返回元数据数组 [{ label, id, levelGrade }],label 即层级文本(C1/P1…)
     fetchEnabledLevels(seqName) {
@@ -1083,6 +1103,8 @@ export default {
         await this.applyActiveLevel(presetLevel);
       }
       this.normalizeFormType();
+      // 所属部门历史脏值归一(必须早于校验,否则野值会锁死保存)
+      this.normalizeDeptId();
       // 推荐培训选项依赖所属机构(机构 id = 接口 deptId),机构确定后再拉
       await this.loadTrainingOptions();
     },
@@ -1532,13 +1554,25 @@ export default {
       const duplicate = this.positionList.some(
         (item) =>
           item.positionCode === this.form.positionCode &&
-          item.id !== this.form.id,
+          String(item.id) !== String(this.form.id),
       );
+      /* 所属部门:界面已下线该字段,历史数据这一列存的是「机构 id」(dept_id NOT NULL)。
+         departments 由 index.vue 构建时主动剔除了机构节点,所以机构 id 在 departments 里必然找不到,
+         原逻辑会把「合法历史数据」判成非法并锁死保存。此处把机构节点本身也视为合法归属,
+         只有既不是部门、也不是任何机构 id 的野值才拦截。 */
+      const deptKey = String(this.form.deptId ?? "").trim();
       const department = this.departments.find(
-        (item) => String(item.id) === String(this.form.deptId),
+        (item) => String(item.id) === deptKey,
       );
-      if (this.form.deptId != null &&
-    (!department || String(department.legalId) !== String(this.form.legalId))) {
+      const isOrgNode =
+        deptKey !== "" &&
+        (deptKey === String(this.form.legalId ?? "").trim() ||
+          this.legalEntities.some((item) => String(item.id) === deptKey));
+      const deptNotInLegal =
+        Boolean(department) &&
+        String(department.legalId ?? "").trim() !==
+          String(this.form.legalId ?? "").trim();
+      if (deptKey && !isOrgNode && (!department || deptNotInLegal)) {
         errors.push({
           message: "所属部门必须存在且属于当前法人",
           module: "basic",

+ 5 - 1
src/views/position/positionManagement/components/PositionHistoryDialog.vue

@@ -292,7 +292,11 @@ export default {
       return impacts.slice(0, 4);
     },
     departmentName(id) {
-      return this.departments.find((item) => item.id === id)?.name || "";
+      // 主键序列化后可能是字符串,部门 id 可能是数字,统一转字符串比较(否则部门名恒为空)
+      return (
+        this.departments.find((item) => String(item.id) === String(id))?.name ||
+        ""
+      );
     },
     formatMonth(month) {
       const parts = month.split("-");

+ 12 - 4
src/views/position/positionManagement/index.vue

@@ -1150,7 +1150,7 @@ export default {
     },
     viewHistoryPosition(positionId) {
       const position = this.localPositions.find(
-        (item) => item.id === positionId,
+        (item) => String(item.id) === String(positionId),
       );
       if (position) this.selectPosition(position);
     },
@@ -1180,12 +1180,19 @@ export default {
       return `${(int >> 16) & 255}, ${(int >> 8) & 255}, ${int & 255}`;
     },
     deptName(id) {
-      return this.departments.find((item) => item.id === id)?.name || "-";
+      // id 序列化后可能为字符串(BaseVO 主键走 ToStringSerializer),部门 id 可能为数字,统一转字符串比较
+      return (
+        this.departments.find((item) => String(item.id) === String(id))?.name ||
+        "-"
+      );
     },
     legalName(id) {
       const org = this.orgMap[String(id)];
       if (org && org.name) return org.name;
-      return this.legalEntities.find((item) => item.id === id)?.name || "-";
+      return (
+        this.legalEntities.find((item) => String(item.id) === String(id))
+          ?.name || "-"
+      );
     },
     typeName(value) {
       if (value === null || value === undefined || value === "") return "-";
@@ -1295,7 +1302,8 @@ export default {
       return (
         org?.groupCode ||
         org?.code ||
-        this.legalEntities.find((item) => item.id === id)?.code ||
+        this.legalEntities.find((item) => String(item.id) === String(id))
+          ?.code ||
         "ZY"
       );
     },

+ 1 - 1
src/views/position/positionSequence/index.vue

@@ -759,7 +759,7 @@ export default {
         const duplicate = this.sequences.some(
           (item) =>
             item.name.trim().toLowerCase() === name.toLowerCase() &&
-            item.id !== this.form.id,
+            String(item.id) !== String(this.form.id),
         );
         if (duplicate) {
           this.$message.warning("岗位序列名称已存在,请更换后重试");