Forráskód Böngészése

feat: 新增部门选择模式及字段类型过滤

- 支持 `dept` 模式,允许在表格中选择部门
- 根据当前模式(`person` 或 `dept`)动态过滤可选的字段类型
- 重构右键菜单的模式切换逻辑,并支持获取部门映射用于打印
- 导入 `deptSelect` 组件及 `listOrganizations` 接口
yusheng 1 hete
szülő
commit
5a81acbb85

+ 31 - 14
src/views/rulesManagement/releaseRules/components/experimentationProcessNew.vue

@@ -95,7 +95,11 @@
               @change="editInputChange"
             ></el-input>
           </el-form-item>
-          <el-form-item label="字段类型:" prop="fieldType" v-if="domObj.mode=='person'">
+          <el-form-item
+            label="字段类型:"
+            prop="fieldType"
+            v-if="['person', 'dept'].includes(domObj.mode)"
+          >
             <el-select
               v-model="domObj.fieldType"
               placeholder="请选择"
@@ -103,7 +107,7 @@
               clearable
             >
               <el-option
-                v-for="opt in fieldTypeOptions"
+                v-for="opt in filteredFieldTypeOptions()"
                 :key="opt.value"
                 :label="opt.label"
                 :value="opt.value"
@@ -293,7 +297,14 @@
         type: Boolean
       }
     },
-    computed: {},
+    computed: {
+      filteredFieldTypeOptions() {
+        return (val) => {
+          const mode = val || this.domObj?.mode || 'text';
+          return this.allFieldTypeOptions[mode] || [];
+        };
+      }
+    },
     data() {
       return {
         list: [],
@@ -302,13 +313,16 @@
         templateDivRef: '',
         domObj: { units: {} },
         idList: [],
-        fieldTypeOptions: [
-          { label: '作业负责人', value: 'work_leader' },
-          { label: '监护人', value: 'guardian' },
-          { label: '作业人', value: 'worker' },
-          { label: '安全交底人', value: 'safety_briefer' },
-          { label: '接受交底人', value: 'safety_receiver' }
-        ],
+        allFieldTypeOptions: {
+          person: [
+            { label: '作业负责人', value: 'work_leader' },
+            { label: '监护人', value: 'guardian' },
+            { label: '作业人', value: 'worker' },
+            { label: '安全交底人', value: 'safety_briefer' },
+            { label: '接受交底人', value: 'safety_receiver' }
+          ],
+          dept: [{ label: '申请单位', value: 'apply_dept' }]
+        },
         opSelectOptions: ['+', '-', '*', '/', '%', '(', ')'],
         equationUnit: {
           equation: [],
@@ -402,7 +416,7 @@
             this.$message.warning(
               '该字段类型在当前表格中已被使用,请选择其他类型'
             );
-            this.domObj.fieldType =  '';
+            this.domObj.fieldType = '';
           } else {
             // 唯一,允许修改
             this.domObj.id = val;
@@ -553,9 +567,12 @@
         if (!this.edit) return;
         this.templateDivRef = templateDivRef;
         // 根据 id 匹配类型(若 id 为预设值则回显,否则置空)
-        const found = this.fieldTypeOptions.find(
-          (opt) => opt.value === domObj.id
-        );
+
+        const found = this.filteredFieldTypeOptions(domObj.mode).find((opt) => {
+          console.log(opt);
+          return opt.value === domObj.id;
+        });
+        console.log(found, 'found');
         domObj.fieldType = found ? found.value : '';
         // 确保 domObj 有 textAlign 默认值(若没有则设置)
         if (!domObj.textAlign) domObj.textAlign = 'center';

+ 124 - 57
src/views/rulesManagement/releaseRules/components/templateDiv/customTableNew.vue

@@ -94,6 +94,26 @@
                     ></i>
                   </div>
                 </template>
+                <!-- ========== 🆕 部门选择模式 ========== -->
+                <template v-else-if="cell.mode === 'dept'">
+                  <div
+                    style="width: 100%; position: relative; min-height: 30px"
+                  >
+                    <deptSelect
+                      v-model="cell.value"
+                      :disabled="!edit"
+                      :isBindPlan="readonly || cell.readonly === 2"
+                      @change="onDeptChange(rowIndex, colIndex)"
+                      style="width: 95%"
+                      placeholder="请选择部门"
+                    />
+                    <i
+                      v-if="edit"
+                      class="el-icon-edit person-edit-icon"
+                      @click.stop="openPersonConfig(cell, rowIndex, colIndex)"
+                    ></i>
+                  </div>
+                </template>
 
                 <!-- ========== 文本模式 ========== -->
                 <template v-else>
@@ -127,13 +147,13 @@
 
 <script>
   import { generateRandomString } from '@/utils/util';
-  // 🆕 导入人员选择组件
   import personSelect from '@/components/CommomSelect/person-select.vue';
-  // 🆕 导入人员列表接口
+  import deptSelect from '@/components/CommomSelect/dept-select.vue'; // 🆕 导入部门选择组件
   import { getUserPage } from '@/api/system/organization';
+  import { listOrganizations } from '@/api/system/organization'; // 🆕 导入部门列表接口
   export default {
     // 🆕 注册人员选择组件
-    components: { personSelect },
+    components: { personSelect, deptSelect },
     props: {
       id: { type: String, default: '' },
       edit: { type: Boolean, default: true },
@@ -239,6 +259,27 @@
       }
     },
     methods: {
+      getTransitions(key) {
+        return [
+          { target: 'text', label: '转为文本模式', method: 'disableDeptMode' },
+          {
+            target: 'checkbox',
+            label: '转为复选框模式',
+            method: 'enableCheckboxMode'
+          },
+          {
+            target: 'person',
+            label: '转为人员选择模式',
+            method: 'enablePersonMode'
+          },
+          {
+            target: 'dept',
+            label: '转为部门选择模式',
+            method: 'enableDeptMode'
+          }
+        ].filter((item) => item.target !== key);
+      },
+
       // ========== 工具 ==========
       getCellStyle(cell) {
         let width = parseFloat(cell.style?.width || cell.width || 100);
@@ -549,28 +590,30 @@
         this.currentRowIndex = rowIndex;
         this.currentColumnIndex = colIndex;
 
+        // 移除旧菜单和监听
         const existingMenu = document.querySelector('.custom-context-menu');
         if (existingMenu) existingMenu.remove();
-
         if (this.menuCloseHandler) {
           document.removeEventListener('click', this.menuCloseHandler);
           this.menuCloseHandler = null;
         }
 
+        // 创建菜单容器
         const menu = document.createElement('div');
         menu.className = 'custom-context-menu';
         menu.style.cssText = `
-      position: fixed;
-      left: ${event.clientX}px;
-      top: ${event.clientY}px;
-      background: white;
-      border: 1px solid #ccc;
-      box-shadow: 2px 2px 8px rgba(0,0,0,0.2);
-      z-index: 10000;
-      padding: 5px 0;
-      min-width: 120px;
-    `;
-
+    position: fixed;
+    left: ${event.clientX}px;
+    top: ${event.clientY}px;
+    background: white;
+    border: 1px solid #ccc;
+    box-shadow: 2px 2px 8px rgba(0,0,0,0.2);
+    z-index: 10000;
+    padding: 5px 0;
+    min-width: 120px;
+  `;
+
+        // 菜单项添加函数
         const addItem = (text, onClick, isSeparator = false) => {
           if (isSeparator) {
             const hr = document.createElement('hr');
@@ -595,6 +638,7 @@
           menu.appendChild(item);
         };
 
+        // 关闭菜单的全局监听
         this.menuCloseHandler = (e) => {
           if (!menu.contains(e.target)) {
             menu.remove();
@@ -603,59 +647,31 @@
           }
         };
 
-        // ===== 根据行号区分菜单项 =====
+        // ---- 行操作菜单 ----
         if (rowIndex === 0) {
-          // 表头行:插入/删除列
           addItem('插入列', () => this.addColumn(colIndex));
           addItem('删除列', () => this.removeColumn(colIndex));
-          addItem('', null, true); // 分隔线
+          addItem('', null, true);
         } else {
-          // 普通行:插入/删除行
           addItem('插入行', () => this.addRow(rowIndex));
           addItem('删除行', () => this.removeRow(rowIndex));
           addItem('', null, true);
         }
 
-        // ===== 模式切换(所有行通用) =====
+        // ---- 模式切换
         const cell = this.tableData[rowIndex][colIndex];
-        if (!cell) {
-          document.body.appendChild(menu);
-          setTimeout(
-            () => document.addEventListener('click', this.menuCloseHandler),
-            0
-          );
-          return;
-        }
-
-        // 根据当前模式显示可用切换项
-        if (cell.mode === 'text' || !cell.mode) {
-          addItem('转为复选框模式', () =>
-            this.enableCheckboxMode(rowIndex, colIndex)
-          );
-          addItem('转为人员选择模式', () =>
-            this.enablePersonMode(rowIndex, colIndex)
-          );
-        } else if (cell.mode === 'checkbox') {
-          addItem('转为文本模式', () =>
-            this.disableCheckboxMode(rowIndex, colIndex)
-          );
-          addItem('转为人员选择模式', () =>
-            this.enablePersonMode(rowIndex, colIndex)
-          );
-        } else if (cell.mode === 'person') {
-          addItem('转为文本模式', () =>
-            this.disablePersonMode(rowIndex, colIndex)
-          );
-          addItem('转为复选框模式', () =>
-            this.enableCheckboxMode(rowIndex, colIndex)
-          );
-        }
-
-        // 当为复选框模式时,额外显示“添加复选框”
-        if (cell.mode === 'checkbox') {
-          addItem('添加复选框', () => this.addCheckbox(rowIndex, colIndex));
+        if (cell) {
+          const currentMode = cell.mode || 'text';
+          this.getTransitions(currentMode).forEach(({ label, method }) => {
+            addItem(label, () => this[method](rowIndex, colIndex));
+          });
+          // 复选框模式额外选项
+          if (currentMode === 'checkbox') {
+            addItem('添加复选框', () => this.addCheckbox(rowIndex, colIndex));
+          }
         }
 
+        // 渲染菜单
         document.body.appendChild(menu);
         setTimeout(() => {
           document.addEventListener('click', this.menuCloseHandler);
@@ -713,6 +729,20 @@
 
       onCheckboxLabelInput() {},
 
+      enableDeptMode(rowIndex, colIndex) {
+        const cell = this.tableData[rowIndex][colIndex];
+        if (!cell) return;
+        this.$set(cell, 'mode', 'dept');
+        this.$forceUpdate();
+      },
+
+      disableDeptMode(rowIndex, colIndex) {
+        const cell = this.tableData[rowIndex][colIndex];
+        if (!cell) return;
+        this.$set(cell, 'mode', 'text');
+        this.$forceUpdate();
+      },
+      onDeptChange() {},
       // ========== 🆕 人员选择 ==========
       enablePersonMode(rowIndex, colIndex) {
         const cell = this.tableData[rowIndex][colIndex];
@@ -862,6 +892,34 @@
           valueObj: { tableData }
         });
       },
+
+      async fetchDeptMap() {
+        if (this.deptMapLoaded) return;
+        try {
+          const res = await listOrganizations({ pageNum: 1, size: -1 });
+          // 递归展平树形数据
+          const flatten = (nodes) => {
+            let result = [];
+            nodes.forEach((node) => {
+              result.push({ id: node.id, name: node.name });
+              if (node.children && node.children.length) {
+                result = result.concat(flatten(node.children));
+              }
+            });
+            return result;
+          };
+          const flatList = flatten(res || []);
+          const map = {};
+          flatList.forEach((dept) => {
+            map[dept.id] = dept.name || '未知部门';
+          });
+          this.deptMap = map;
+          this.deptMapLoaded = true;
+        } catch (error) {
+          console.warn('获取部门列表失败,打印时将显示ID', error);
+        }
+      },
+
       // ========== 🆕 获取用户映射(供打印使用) ==========
       async fetchUserMap() {
         if (this.userMapLoaded) return;
@@ -884,7 +942,7 @@
       async printTable() {
         // 1. 先获取用户映射(如果未加载)
         await this.fetchUserMap();
-
+        await this.fetchDeptMap(); // 🆕 加载部门映射
         const tableEl = this.$el.querySelector('.custom-table');
         if (!tableEl) return;
 
@@ -941,6 +999,15 @@
               div.style.cssText = 'text-align:center;padding:4px;';
               td.innerHTML = '';
               td.appendChild(div);
+            } else if (cell.mode === 'dept') {
+              // 🆕
+              const deptId = cell.value;
+              const deptName = this.deptMap[deptId] || deptId || '';
+              const div = document.createElement('div');
+              div.textContent = deptName;
+              div.style.cssText = 'text-align:center;padding:4px;';
+              td.innerHTML = '';
+              td.appendChild(div);
             }
           }
         }