Browse Source

pms 瑞都日报 任务 多个工作量 添加 与 回显

zhangcl 2 weeks ago
parent
commit
3f134f541f
1 changed files with 269 additions and 46 deletions
  1. 269 46
      src/views/pms/iotprojecttask/IotProjectTaskForm.vue

+ 269 - 46
src/views/pms/iotprojecttask/IotProjectTaskForm.vue

@@ -236,25 +236,35 @@
       <el-row>
         <el-col :span="8">
           <el-form-item label="设计工作量" prop="workloadDesign">
-            <el-input
-              v-model="currentTask.workloadDesign"
-              placeholder="请输入设计工作量"
-              :disabled="currentTask.platformWell === '1'"
-              class="workload-input-with-button"
+            <el-tooltip
+              :disabled="!workloadDesignError"
+              :content="workloadDesignError"
+              placement="top"
+              effect="light"
+              popper-class="workload-design-tooltip"
+              :show-after="0"
             >
-              <template #append>
-                <el-tooltip content="添加多个设计工作量" placement="top">
-                  <el-button
-                    class="workload-add-btn"
-                    @click="openWorkloadDialog"
-                    :disabled="!currentTask.workloadUnit || currentTask.platformWell === '1'"
-                  >
-                    <!-- <el-icon><Plus /></el-icon> -->
-                    <span class="btn-text">+</span>
-                  </el-button>
-                </el-tooltip>
-              </template>
-            </el-input>
+              <el-input
+                v-model="currentTask.workloadDesign"
+                placeholder="请输入设计工作量"
+                :disabled="currentTask.platformWell === '1'"
+                class="workload-input-with-button"
+                :class="{ 'error-input': workloadDesignError }"
+                @blur="validateWorkloadDesign"
+              >
+                <template #append>
+                  <el-tooltip content="添加多个设计工作量" placement="top">
+                    <el-button
+                      class="workload-add-btn"
+                      @click="openWorkloadDialog"
+                      :disabled="getWorkloadAddBtnDisabled"
+                    >
+                      <span class="btn-text">+</span>
+                    </el-button>
+                  </el-tooltip>
+                </template>
+              </el-input>
+            </el-tooltip>
           </el-form-item>
         </el-col>
         <el-col :span="8">
@@ -265,6 +275,7 @@
                 :key="dict.value"
                 :label="dict.label"
                 :value="dict.value"
+                :disabled="getFormSelectedWorkloadUnits().includes(dict.value) && dict.value !== currentTask.workloadUnit"
               />
             </el-select>
           </el-form-item>
@@ -761,11 +772,17 @@ const platformWellDetailsBackup = ref([]);
 // 存储井号到工作量列表的映射(key: wellName, value: Array<{workloadUnit, workloadDesign}>)
 const workloadMap = ref(new Map());
 
+// 工作量数据备份
+const workloadBackup = ref<Map<string, any[]>>(new Map());
+
 // 工作量维护相关变量
 const workloadDialogVisible = ref(false);
 const workloadList = ref<any[]>([]);
 const hasInitialWorkload = ref(false);
 
+// 设计工作量错误信息
+const workloadDesignError = ref('');
+
 /** 项目信息 表单 */
 defineOptions({ name: 'IotProjectTaskInfo' })
 
@@ -933,6 +950,8 @@ const getDeviceNames = (deviceIds: number[]) => {
   });
 }; */
 
+
+
 const initDynamicAttrsToCurrentTask = () => {
   dynamicAttrs.value.forEach(attr => {
     if (!currentTask.value.hasOwnProperty(attr.identifier)) {
@@ -979,7 +998,34 @@ const taskFormRules = computed(() => {
     wellType: [{ required: true, message: '井型不能为空', trigger: 'change' }],
     location: [{ required: true, message: '施工地点不能为空', trigger: 'blur' }],
     technique: [{ required: true, message: '施工工艺不能为空', trigger: 'change' }],
-    workloadDesign: [{ required: currentTask.value.platformWell !== '1', message: '设计工作量不能为空', trigger: 'blur' }],
+    workloadDesign: [
+      {
+        required: currentTask.value.platformWell !== '1',
+        message: '设计工作量不能为空',
+        trigger: 'blur'
+      },
+      {
+        validator: (rule, value, callback) => {
+          if (currentTask.value.platformWell === '1') {
+            callback();
+            return;
+          }
+
+          if (value === '' || value === null || value === undefined) {
+            callback(new Error('设计工作量不能为空'));
+            return;
+          }
+
+          const numValue = Number(value);
+          if (isNaN(numValue) || numValue < 0) {
+            callback(new Error('请填写大于0的数字'));
+          } else {
+            callback();
+          }
+        },
+        trigger: 'blur'
+      }
+    ],
     workloadUnit: [{ required: currentTask.value.platformWell !== '1', message: '工作量单位不能为空', trigger: 'change' }],
     deptIds: [{ required: true, message: '施工队伍不能为空', trigger: 'change' }],
     deviceIds: [{ required: true, message: '施工设备不能为空', trigger: 'change' }],
@@ -1135,6 +1181,12 @@ const openDeviceDialogForForm = async () => {
 
 // 打开工作量维护对话框
 const openWorkloadDialog = () => {
+  // 前置校验:设计工作量不合法则直接返回
+  if (!validateWorkloadDesign()) {
+    ElMessage.error(workloadDesignError.value);
+    return;
+  }
+
   // 重置列表
   workloadList.value = [];
   hasInitialWorkload.value = false;
@@ -1150,8 +1202,13 @@ const openWorkloadDialog = () => {
     currentWellName = currentTask.value.wellName;
   }
 
+  if (!currentWellName) {
+    ElMessage.warning('请先填写井号');
+    return;
+  }
+
   // 从Map中回显当前井号的工作量数据
-  if (currentWellName && workloadMap.value.has(currentWellName)) {
+  if (workloadMap.value.has(currentWellName)) {
     // 深拷贝避免原数据被修改
     workloadList.value = JSON.parse(JSON.stringify(workloadMap.value.get(currentWellName)));
     hasInitialWorkload.value = workloadList.value.length > 0;
@@ -1205,21 +1262,32 @@ const confirmWorkloadSelection = () => {
   // 获取当前井号并存储到Map
   let currentWellName = '';
   if (currentTask.value.platformWell === '1') {
-    currentWellName = currentTask.value.wellName || (currentTask.value.platformWellDetails.length > 0 ? currentTask.value.platformWellDetails[0].wellName : '');
+    currentWellName = currentTask.value.wellName || (currentTask.value.platformWellDetails.length > 0
+      ? currentTask.value.platformWellDetails[0].wellName : '');
   } else {
     currentWellName = currentTask.value.wellName;
   }
   // 深拷贝存储,避免后续修改影响Map数据
   if (currentWellName) {
     workloadMap.value.set(currentWellName, JSON.parse(JSON.stringify(workloadList.value)));
+
+    // 同步更新表单中的workloadUnit为第一项的值(确保一致性)
+    if (workloadList.value.length > 0) {
+      const firstItem = workloadList.value[0];
+      // 只有当当前值不同时才更新,避免触发watch循环
+      if (currentTask.value.workloadUnit !== firstItem.workloadUnit) {
+        currentTask.value.workloadUnit = firstItem.workloadUnit;
+      }
+      currentTask.value.workloadDesign = firstItem.workloadDesign;
+    }
   }
 
   // 如果有数据,设置第一个项到表单中(保持原有逻辑)
-  if (workloadList.value.length > 0) {
+  /* if (workloadList.value.length > 0) {
     const firstItem = workloadList.value[0];
     currentTask.value.workloadUnit = firstItem.workloadUnit;
     currentTask.value.workloadDesign = firstItem.workloadDesign;
-  }
+  } */
 
   // 这里可以根据需要将整个workloadList存储到currentTask中
   // 例如:currentTask.value.workloadDesignList = [...workloadList.value];
@@ -1448,8 +1516,13 @@ const resetTaskForm = () => {
   };
 
   // 清理当前井号对应的Map数据
-  if (oldWellName && workloadMap.value.has(oldWellName)) {
-    workloadMap.value.delete(oldWellName);
+  if (oldWellName) {
+    if (workloadMap.value.has(oldWellName)) {
+      workloadMap.value.delete(oldWellName);
+    }
+    if (workloadBackup.value.has(oldWellName)) {
+      workloadBackup.value.delete(oldWellName);
+    }
   }
 
   // 重新初始化动态属性
@@ -1895,6 +1968,12 @@ const submitForm = async () => {
   // 施工区域的数据字典类型
   currentTask.value.dictType = currentDictLabel.value;
 
+  // 先校验设计工作量
+  if (currentTask.value.platformWell !== '1' && !validateWorkloadDesign()) {
+    ElMessage.error('请完善设计工作量信息');
+    return;
+  }
+
   // 先同步当前任务表单数据到表格
   if (!syncCurrentTaskToTable()) {
     return;
@@ -1976,6 +2055,14 @@ const isMainPlatformWellDetail = (index: number) => {
 const handlePlatformWellChange = (value) => {
   if (value === '1') {
 
+    // 切换到平台井模式前,备份当前井号的工作量数据
+    if (currentTask.value.wellName) {
+      const currentWorkload = workloadMap.value.get(currentTask.value.wellName);
+      if (currentWorkload) {
+        workloadBackup.value.set(currentTask.value.wellName, [...currentWorkload]);
+      }
+    }
+
     // 检查是否是从非平台井切换过来,且当前任务有井号信息
     const hasWellName = currentTask.value.wellName && currentTask.value.wellName.trim() !== '';
     const hasWorkloadDesign = currentTask.value.workloadDesign;
@@ -1990,10 +2077,6 @@ const handlePlatformWellChange = (value) => {
 
       // 清空现有详情,添加主记录
       currentTask.value.platformWellDetails = [mainDetail];
-
-      // 清空主任务的井号和设计工作量(因为现在在平台井详情中管理)
-      // currentTask.value.wellName = '';
-      // currentTask.value.workloadDesign = '';
     } else {
       // 恢复之前保存的数据或初始化
       if (platformWellDetailsBackup.value.length > 0) {
@@ -2005,40 +2088,60 @@ const handlePlatformWellChange = (value) => {
     }
     // 更新备份数据
     platformWellDetailsBackup.value = [...currentTask.value.platformWellDetails];
-
-    // 切换到平台井模式,恢复之前保存的数据
-    /* if (platformWellDetailsBackup.value.length > 0) {
-      // 恢复数据时进行排序
-      currentTask.value.platformWellDetails = [...platformWellDetailsBackup.value].sort((a, b) => {
-        if (a.taskId === currentTask.value.id) return -1;
-        if (b.taskId === currentTask.value.id) return 1;
-        return 0;
-      });
-    } else {
-      // 如果没有备份数据,初始化一行
-      addPlatformWellDetail();
-    } */
   } else {
     // 关闭平台井时,清理所有平台井详情对应的Map数据
-    currentTask.value.platformWellDetails.forEach(detail => {
+    /* currentTask.value.platformWellDetails.forEach(detail => {
       if (detail.wellName && workloadMap.value.has(detail.wellName)) {
         workloadMap.value.delete(detail.wellName);
       }
-    });
+    }); */
 
-    // 切换到非平台井模式,保存当前数据到备份
-    platformWellDetailsBackup.value = [...currentTask.value.platformWellDetails];
     // 如果有平台井详情,将第一个详情的数据设置回主任务
     if (currentTask.value.platformWellDetails.length > 0) {
       const mainDetail = currentTask.value.platformWellDetails[0];
       currentTask.value.wellName = mainDetail.wellName || '';
       currentTask.value.workloadDesign = mainDetail.workloadDesign || '';
+
+      // 恢复工作量数据
+      if (mainDetail.wellName && workloadBackup.value.has(mainDetail.wellName)) {
+        const backupWorkload = workloadBackup.value.get(mainDetail.wellName);
+        if (backupWorkload && backupWorkload.length > 0) {
+          workloadMap.value.set(mainDetail.wellName, [...backupWorkload]);
+
+          // 恢复表单中的工作量单位(取第一项)
+          currentTask.value.workloadUnit = backupWorkload[0].workloadUnit;
+          currentTask.value.workloadDesign = backupWorkload[0].workloadDesign;
+        }
+      }
     }
+
+    // 切换到非平台井模式,保存当前数据到备份
+    platformWellDetailsBackup.value = [...currentTask.value.platformWellDetails];
     // 切换到非平台井模式,清空详情列表
     currentTask.value.platformWellDetails = [];
   }
 };
 
+// 获取表单中已选的工作量单位(来自workloadMap)
+const getFormSelectedWorkloadUnits = () => {
+  // 兼容普通井/平台井的井号获取逻辑(与工作量弹窗逻辑一致)
+  let currentWellName = '';
+  if (currentTask.value.platformWell === '1') {
+    // 平台井:取主井号(优先当前任务wellName,其次取平台井详情第一个)
+    currentWellName = currentTask.value.wellName || (currentTask.value.platformWellDetails.length > 0
+      ? currentTask.value.platformWellDetails[0].wellName : '');
+  } else {
+    // 普通井:直接取当前任务井号
+    currentWellName = currentTask.value.wellName;
+  }
+
+  // 从Map中获取当前井号的工作量列表,提取已选单位
+  const workloadList = workloadMap.value.get(currentWellName) || [];
+  return workloadList
+    .map(item => item.workloadUnit)
+    .filter(unit => unit && unit.trim() !== ''); // 过滤空值
+};
+
 // 添加平台井详情行
 const addPlatformWellDetail = () => {
   const newDetail = {
@@ -2236,6 +2339,90 @@ const loadTechnologyOptions = async (deptId: number) => {
   }
 }
 
+// 工作量加号按钮禁用状态(计算属性)
+const getWorkloadAddBtnDisabled = computed(() => {
+  // 禁用条件:无工作量单位 || 平台井模式 || 设计工作量校验失败
+  return !currentTask.value.workloadUnit ||
+    currentTask.value.platformWell === '1' ||
+    !!workloadDesignError.value;
+});
+
+// 监听平台井状态变化,清空错误信息
+watch(() => currentTask.value.platformWell, () => {
+  workloadDesignError.value = '';
+});
+
+// 监听工作量单位变化,同步更新到 workloadMap
+watch(() => currentTask.value.workloadUnit, (newWorkloadUnit, oldWorkloadUnit) => {
+  if (!newWorkloadUnit || newWorkloadUnit === oldWorkloadUnit) return;
+
+  // 获取当前井号(兼容普通井/平台井)
+  let currentWellName = '';
+  if (currentTask.value.platformWell === '1') {
+    currentWellName = currentTask.value.wellName || (currentTask.value.platformWellDetails.length > 0
+      ? currentTask.value.platformWellDetails[0].wellName : '');
+  } else {
+    currentWellName = currentTask.value.wellName;
+  }
+
+  if (!currentWellName) return;
+
+  // 如果workloadMap中存在当前井号的工作量数据,更新第一项的workloadUnit
+  if (workloadMap.value.has(currentWellName)) {
+    const workloadList = workloadMap.value.get(currentWellName);
+    if (workloadList && workloadList.length > 0) {
+      // 更新第一项的workloadUnit
+      workloadList[0].workloadUnit = newWorkloadUnit;
+      // 重新设置到Map中(虽然引用相同,但为了确保响应性)
+      workloadMap.value.set(currentWellName, [...workloadList]);
+    } else {
+      // 如果列表为空但有设计工作量,创建新项
+      if (currentTask.value.workloadDesign) {
+        workloadMap.value.set(currentWellName, [{
+          workloadUnit: newWorkloadUnit,
+          workloadDesign: currentTask.value.workloadDesign
+        }]);
+      }
+    }
+  } else if (currentTask.value.workloadDesign) {
+    // 如果Map中不存在但有设计工作量,创建新条目
+    workloadMap.value.set(currentWellName, [{
+      workloadUnit: newWorkloadUnit,
+      workloadDesign: currentTask.value.workloadDesign
+    }]);
+  }
+}, { deep: true });
+
+// 校验设计工作量
+const validateWorkloadDesign = () => {
+  workloadDesignError.value = '';
+
+  if (currentTask.value.platformWell === '1') {
+    return true;
+  }
+
+  const value = currentTask.value.workloadDesign;
+  if (value === '' || value === null || value === undefined) {
+    workloadDesignError.value = '设计工作量不能为空';
+    return false;
+  }
+
+  const numValue = Number(value);
+  if (isNaN(numValue) || numValue < 0) {
+    workloadDesignError.value = '请填写大于0的数字';
+    return false;
+  }
+
+  return true;
+};
+
+// 监听设计工作量变化
+watch(() => currentTask.value.workloadDesign, () => {
+  if (workloadDesignError.value) {
+    validateWorkloadDesign();
+  }
+});
+
 // 监听当前任务的变化,设置默认展开的keys
 watch(() => currentTask.value.deptIds, (newVal) => {
   if (newVal && newVal.length > 0) {
@@ -2502,4 +2689,40 @@ onMounted(async () => {
   cursor: not-allowed;
 }
 
+/* 设计工作量错误输入框样式 */
+:deep(.error-input .el-input__inner) {
+  border-color: #f56c6c !important;
+  background-color: #fef0f0 !important;
+  box-shadow: 0 0 0 1px rgba(245, 108, 108, 0.4) !important;
+}
+
+:deep(.error-input .el-input__inner:hover) {
+  border-color: #f56c6c !important;
+  background-color: #fef0f0 !important;
+}
+
+:deep(.error-input .el-input__inner:focus) {
+  border-color: #f56c6c !important;
+  background-color: #fef0f0 !important;
+  box-shadow: 0 0 0 1px rgba(245, 108, 108, 0.2) !important;
+}
+
+/* 设计工作量tooltip样式 */
+:deep(.workload-design-tooltip) {
+  background: #fef0f0 !important;
+  border: 1px solid #fbc4c4 !important;
+  color: #f56c6c !important;
+  max-width: 300px;
+  font-size: 12px;
+  padding: 8px 12px;
+}
+
+/* 隐藏 Tooltip 箭头 */
+:deep(.workload-design-tooltip .el-tooltip__arrow),
+:deep(.workload-design-tooltip .el-tooltip__arrow::before) {
+  display: none !important;
+  width: 0 !important;
+  height: 0 !important;
+}
+
 </style>