Преглед на файлове

pms 保养计划 上次保养日期

zhangcl преди 2 месеца
родител
ревизия
23822ff3a0

+ 2 - 0
src/api/pms/iotmainworkorderbom/index.ts

@@ -8,6 +8,8 @@ export interface IotMainWorkOrderBomVO {
   workOrderId: number // 保养工单id
   deviceCategoryId: number // 所属设备分类
   deviceId: number // 设备id
+  deviceCode: string  // 设备编码
+  deviceName: string  // 设备名称
   rule: string // 保养规则(量程 运行时间 自然日期) 可多选
   mileageRule: number // 保养规则-里程(0启用 1停用)
   naturalDateRule: number // 保养规则-自然日期(0启用 1停用)

+ 56 - 34
src/views/pms/iotmainworkorder/IotMainWorkOrder.vue

@@ -897,59 +897,81 @@ const configFormRules = reactive({
 
 /** 校验表格数据 */
 const validateTableData = (): boolean => {
-  let isValid = true
-  const errorMessages: string[] = []
-  let shouldBreak = false;
-  const materialRequiredErrors: string[] = []  // 物料必填错误
+  let isValid = true;
+  const errorMessages: string[] = []; // 通用错误集合
+  const materialRequiredErrors: string[] = []; // 物料缺失专用错误集合
 
+  // 1. 基础校验:工单明细是否存在
   if (list.value.length === 0) {
-    errorMessages.push('工单明细不存在')
-    isValid = false
-    // 直接返回无需后续校验
-    message.error('工单明细不存在')
-    return isValid
+    message.error('工单明细不存在');
+    return false;
   }
 
-  // 新增物料必填校验(仅在非委外模式下检查)
-  if (formData.value.outsourcingFlag !== 1) { // 非委外模式
+  // 2. 校验设备状态
+  list.value.forEach((row, index) => {
+    const rowNumber = index + 1;
+    if (row.deviceCode === null || row.deviceName === null) {
+      errorMessages.push(`第${rowNumber}行设备状态错误`);
+      isValid = false;
+    }
+  });
+
+  // 3. 校验物料必填(仅在非委外模式下)
+  if (formData.value.outsourcingFlag !== 1) {
     list.value.forEach((row, index) => {
-      const rowNumber = index + 1
-      const deviceIdentifier = `${row.deviceCode}-${row.name}`
+      const rowNumber = index + 1;
+      const deviceIdentifier = `${row.deviceCode}-${row.name}`;
 
       // 检查是否设置了推迟保养
       const hasDelay =
         (row.delayKilometers || 0) > 0 ||
         (row.delayNaturalDate || 0) > 0 ||
-        (row.delayDuration || 0) > 0
+        (row.delayDuration || 0) > 0;
 
       // 未设置推迟保养且未选择物料
       if (!hasDelay && getMaterialCount(row.bomNodeId) === 0) {
-        materialRequiredErrors.push(`第${rowNumber}行【${deviceIdentifier}】必须选择物料`)
-        isValid = false
+        materialRequiredErrors.push(`第${rowNumber}行【${deviceIdentifier}】未添加物料`);
+        isValid = false;
       }
-    })
+    });
   }
 
-  list.value.forEach((row, index) => {
-    if (shouldBreak) return;
-    const rowNumber = index + 1 // 用户可见的行号从1开始
-    // const deviceIdentifier = `${row.deviceCode}-${row.name}` // 设备标识
-    if(row.deviceCode === null || row.deviceName === null){
-      errorMessages.push('设备状态错误')
-      isValid = false
+  // 4. 智能错误提示
+  if (!isValid) {
+    // 构建错误消息HTML
+    let errorHtml = '';
+
+    // 添加通用错误
+    if (errorMessages.length > 0) {
+      errorHtml += errorMessages.join('<br>');
+    }
+
+    // 添加物料错误(带智能截断)
+    if (materialRequiredErrors.length > 0) {
+      if (errorHtml) errorHtml += '<br>'; // 添加换行分隔
+
+      if (materialRequiredErrors.length > 3) {
+        errorHtml += materialRequiredErrors.slice(0, 3).join('<br>');
+        errorHtml += `<br>...等共 ${materialRequiredErrors.length} 个保养项未添加物料`;
+      } else {
+        errorHtml += materialRequiredErrors.join('<br>');
+      }
     }
-  })
-  if (errorMessages.length > 0) {
-    message.error('设备状态错误')
-  }
-  // 合并错误信息
-  if (materialRequiredErrors.length > 0) {
-    message.error(materialRequiredErrors.join('\n'))
-  }
-  return isValid
-}
 
+    // 添加标题
+    const title = "<span style='font-weight:bold;color:#f56c6c'></span>";
+    errorHtml = title + errorHtml;
+
+    // 显示带格式的错误消息
+    message.error({
+      message: errorHtml,
+      dangerouslyUseHTMLString: true,
+      duration: 8000  // 延长显示时间
+    });
+  }
 
+  return isValid;
+};
 
 /** 重置表单 */
 const resetForm = () => {

+ 48 - 1
src/views/pms/iotmainworkorder/IotMainWorkOrderAdd.vue

@@ -726,7 +726,7 @@ const saveConfig = () => {
     // 强制校验逻辑
     if (configDialog.current.naturalDateRule === 0) {
       if (!configDialog.form.lastNaturalDate) {
-        message.error('必须选择自然日期')
+        message.error('必须选择 上次保养自然日期')
         return
       }
 
@@ -836,6 +836,11 @@ const submitForm = async () => {
   // 校验表格数据
   const isValid = validateTableData()
   if (!isValid) return
+
+  // 新增:校验物料选择
+  const hasMaterial = validateMaterialSelection();
+  if (!hasMaterial) return;
+
   // 提交请求
   formLoading.value = true
   try {
@@ -904,6 +909,48 @@ const validateTableData = (): boolean => {
   return isValid
 }
 
+/** 检查每个保养项是否都有物料 */
+const validateMaterialSelection = (): boolean => {
+  let isValid = true;
+  const errorMessages: string[] = [];
+
+  // 遍历所有保养项
+  list.value.forEach(item => {
+    const hasMaterial = materialList.value.some(
+      material => material.bomNodeId === item.bomNodeId
+    );
+
+    if (!hasMaterial) {
+      isValid = false;
+      errorMessages.push(
+        `设备 ${item.deviceCode}-${item.deviceName} 的保养项【${item.name}】未添加物料`
+      );
+    }
+  });
+
+  // 显示错误信息
+  if (!isValid) {
+    let displayMessage;
+
+    if (errorMessages.length > 3) {
+      // 超过3条错误时显示前3条+总结
+      const firstThree = errorMessages.slice(0, 3);
+      displayMessage = firstThree.join('<br/>') +
+        `<br/>...等共 ${errorMessages.length} 个保养项未添加物料`;
+    } else {
+      // 3条及以内直接显示全部
+      displayMessage = errorMessages.join('<br/>');
+    }
+
+    message.error({
+      message: displayMessage,
+      dangerouslyUseHTMLString: true
+    });
+  }
+
+  return isValid;
+};
+
 /** 重置表单 */
 const resetForm = () => {
   formData.value = {

+ 17 - 4
src/views/pms/maintenance/IotMaintenancePlan.vue

@@ -160,6 +160,7 @@
     v-model="configDialog.visible"
     :title="`设备 ${configDialog.current?.deviceCode+'-'+configDialog.current?.name} 保养配置`"
     width="600px"
+    :close-on-click-modal="false"
   >
     <!-- 使用header插槽自定义标题 -->
     <template #header>
@@ -432,7 +433,10 @@ const openConfigDialog = (row: IotMaintenanceBomVO) => {
   configDialog.form = {
     lastRunningKilometers: row.lastRunningKilometers || 0,
     lastRunningTime: row.lastRunningTime || 0,
-    lastNaturalDate: initialDate,
+    // 时间戳 -> Date对象(用于日期选择器)
+    lastNaturalDate: row.lastNaturalDate
+      ? dayjs(row.lastNaturalDate).format('YYYY-MM-DD')
+      : null,
     // 保养规则 周期值
     nextRunningKilometers: row.nextRunningKilometers || 0,
     nextRunningTime: row.nextRunningTime || 0,
@@ -495,7 +499,8 @@ const saveConfig = () => {
     // 更新当前行的数据
     Object.assign(configDialog.current, {
       ...configDialog.form,
-      lastNaturalDate: finalDate
+      // Date对象 -> 时间戳
+      lastNaturalDate: finalDate,
     })
     configDialog.visible = false
   })
@@ -629,9 +634,17 @@ const submitForm = async () => {
   // 提交请求
   formLoading.value = true
   try {
+    // 转换日期格式
+    const convertedList = list.value.map(item => ({
+      ...item,
+      lastNaturalDate: typeof item.lastNaturalDate === 'number'
+        ? item.lastNaturalDate
+        : (item.lastNaturalDate ? dayjs(item.lastNaturalDate).valueOf() : null)
+    }));
+
     const data = {
       mainPlan: formData.value,
-      mainPlanBom: list.value
+      mainPlanBom: convertedList
     }
     if (formType.value === 'create') {
       await IotMaintenancePlanApi.createIotMaintenancePlan(data)
@@ -811,7 +824,7 @@ onMounted(async () => {
       list.value = data.map(item => ({
         ...item,
         // 这里可以添加必要的字段转换(如果有日期等需要格式化的字段)
-        lastNaturalDate: item.lastNaturalDate ? dayjs(item.lastNaturalDate).format('YYYY-MM-DD') : null
+        lastNaturalDate: item.lastNaturalDate
       }))
       // 同时查询所有设备的责任人
       // await getDevicePersons();