Explorar o código

考勤规则部门下拉只展示当前登录机构及其子部门

lihaiting hai 6 días
pai
achega
64e7b45cc6
Modificáronse 1 ficheiros con 76 adicións e 0 borrados
  1. 76 0
      src/views/attendance/components/RuleMethodPanel.vue

+ 76 - 0
src/views/attendance/components/RuleMethodPanel.vue

@@ -365,6 +365,29 @@ export default {
         }
         // 登录缓存为空时兜底走全量组织树,避免下拉无选项
       }
+      /*
+       * DEPT(部门):只列「当前登录用户所属机构」下的部门(含各级子部门),
+       * 不再把其它机构的部门列出来。
+       * 需要 parentId 做层级下钻,而父组件传下来的 orgOptions 只有 { value, label, type },
+       * 因此这里直接读扁平组织列表(listOrganizations 带 parentId,且有 1 分钟共享缓存)。
+       */
+      if (type === 'DEPT') {
+        const { list: scoped, nameById } = await this.loadDepartmentsUnderCurrentOrg();
+        if (scoped.length) {
+          /* 编辑旧单据时,已选部门若不在「当前机构下」的列表里,补一条用于回显,
+             否则 el-select 找不到选项会退化成直接显示原始 id。 */
+          const selected = (this.selectedScopeIds || []).map((id) => normalizeOptionId(id));
+          const missing = selected.filter(
+            (id) => id && !scoped.some((item) => String(item.id) === id),
+          );
+          return missing.length
+            ? scoped.concat(
+                missing.map((id) => ({ id, name: nameById[id] || id })),
+              )
+            : scoped;
+        }
+        // 拿不到层级关系(parentId 缺失)时,退回下面「全量 type=30」的兜底逻辑
+      }
       let list = [];
       if (Array.isArray(this.orgOptions) && this.orgOptions.length) {
         list = this.orgOptions.map((item) => ({
@@ -393,6 +416,59 @@ export default {
       // ORG:机构,展示全部组织单元
       return list;
     },
+    /**
+     * 「当前登录用户所属机构」下的所有部门(含各级子部门)
+     * 机构取登录缓存 loginChangeGroupVOList(getOrgOptions),
+     * 部门按扁平组织列表的 parentId 逐级下钻,只收集 type=30 的节点;
+     * 机构自身、以及其它机构的部门都不返回。
+     */
+    async loadDepartmentsUnderCurrentOrg() {
+      const raw = await listOrganizations();
+      const rows = Array.isArray(raw) ? raw : raw?.list || raw?.records || raw?.rows || [];
+      const nodes = rows
+        .filter((item) => item && item.id != null && item.id !== '')
+        .map((item) => ({
+          id: normalizeOptionId(item.id),
+          name: item.name || '未命名部门',
+          parentId:
+            item.parentId != null && item.parentId !== ''
+              ? normalizeOptionId(item.parentId)
+              : '',
+          type: item.type,
+        }));
+      const orgIds = getOrgOptions().map((item) => normalizeOptionId(item.id));
+      if (!orgIds.length || !nodes.length) return { list: [], nameById: {} };
+
+      /* 全量部门名称索引:仅用于「已选值不在当前机构下」时的回显兜底 */
+      const nameById = nodes.reduce((map, node) => {
+        if (String(node.type) === '30') map[node.id] = node.name;
+        return map;
+      }, {});
+
+      /* 只按 parentId 建索引:没有 parentId 的节点无法判断归属,直接不参与下钻 */
+      const childrenOf = new Map();
+      nodes.forEach((node) => {
+        if (!node.parentId) return;
+        if (!childrenOf.has(node.parentId)) childrenOf.set(node.parentId, []);
+        childrenOf.get(node.parentId).push(node);
+      });
+
+      const result = [];
+      const visited = new Set();
+      const walk = (parentId) => {
+        (childrenOf.get(parentId) || []).forEach((node) => {
+          if (visited.has(node.id)) return;
+          visited.add(node.id);
+          /* 机构本身不作为部门选项;命中部门(type=30)后仍继续下钻子部门 */
+          if (String(node.type) === '30') {
+            result.push({ id: node.id, name: node.name });
+          }
+          walk(node.id);
+        });
+      };
+      orgIds.forEach((id) => walk(id));
+      return { list: result, nameById };
+    },
     /** 工厂区域列表(type=1 工厂),组织树无工厂节点时的兜底数据源 */
     async loadFactoryAreaOptions() {
       const data = await getFactoryAreaPage({ pageNum: 1, size: 999, type: 1 });