Преглед изворни кода

pms 数据权限等功能优化

zhangcl пре 2 месеци
родитељ
комит
a5aaed384a

+ 3 - 0
src/api/pms/iotmaintenancebom/index.ts

@@ -13,6 +13,9 @@ export interface IotMaintenanceBomVO {
   runningTimeRule: number   // 保养规则-运行时间(0启用 1停用)
   lastRunningTime: number // 上次保养运行时长(小时)
   nextRunningTime: number // 下次保养运行时长(小时)
+  timePeriod: number // 时间周期(小时)
+  kilometerCycle: number // 公里数周期(千米)
+  naturalDatePeriod: number // 自然日周期(天)
   timePeriodLead: number  // 运行时长周期提前量 H
   lastRunningKilometers: number // 上次保养运行公里数(千米)
   nextRunningKilometers: number // 下次保养运行公里数(千米)

+ 2 - 1
src/locales/en.ts

@@ -625,7 +625,8 @@ export default {
     dept:'Department',
     rp:'ResponsiblePerson',
     operation:'Operation',
-    adjustmentRecords:'AdjustmentRecords'
+    adjustmentRecords:'AdjustmentRecords',
+    filterDevicePlaceholder: "Filter DeviceCode or DeviceName"
   },
   configPerson:{
     deviceList:'DeviceList',

+ 1 - 0
src/locales/zh-CN.ts

@@ -620,6 +620,7 @@ export default {
     rp:'责任人',
     operation:'操作',
     adjustmentRecords:'调整记录',
+    filterDevicePlaceholder: "输入设备编码或名称过滤"
   },
   configPerson:{
     deviceList:'设备列表',

+ 37 - 1
src/views/pms/device/allotlog/ConfigDeviceAllot.vue

@@ -18,10 +18,21 @@
               @node-click="handleDeptDeviceTreeNodeClick"
             />
           </div>
+
+          <!-- 设备搜索框 -->
+          <div class="filter-input">
+            <el-input
+              v-model="deviceFilterText"
+              :placeholder="t('devicePerson.filterDevicePlaceholder')"
+              clearable
+              prefix-icon="Search"
+            />
+          </div>
+
           <el-scrollbar height="500px">
             <el-checkbox-group v-model="selectedDevices">
               <div
-                v-for="device in simpleDevices"
+                v-for="device in filteredDevices"
                 :key="device.id"
                 class="checkbox-item"
               >
@@ -240,6 +251,22 @@ const validateDeptSelection = (deptId: number) => {
   return true
 }
 
+// 设备过滤文本
+const deviceFilterText = ref('')
+
+// 计算属性:过滤设备列表
+const filteredDevices = computed(() => {
+  const searchText = deviceFilterText.value.toLowerCase().trim()
+  if (!searchText) return simpleDevices.value
+
+  return simpleDevices.value.filter(device => {
+    return (
+      (device.deviceCode || '').toLowerCase().includes(searchText) ||
+      (device.deviceName || '').toLowerCase().includes(searchText)
+    )
+  })
+})
+
 const removeTempRelation = (deviceId: number) => {
   tempRelationsMap.value.delete(deviceId)
   selectedDevices.value = selectedDevices.value.filter(id => id !== deviceId)
@@ -392,4 +419,13 @@ h3 {
   min-height: 400px;/* 统一最小高度 */
 }
 
+.filter-input {
+  margin-bottom: 15px;
+}
+
+.no-data {
+  padding: 20px;
+  text-align: center;
+  color: #999;
+}
 </style>

+ 38 - 2
src/views/pms/device/personlog/ConfigDevicePerson.vue

@@ -18,10 +18,20 @@
               @node-click="handleDeptDeviceTreeNodeClick"
             />
           </div>
+          <!-- 设备搜索框 -->
+          <div class="filter-input">
+            <el-input
+              v-model="deviceFilterText"
+              :placeholder="t('devicePerson.filterDevicePlaceholder')"
+              clearable
+              prefix-icon="Search"
+            />
+          </div>
+
           <el-scrollbar height="400px">
             <el-checkbox-group v-model="selectedDevices">
               <div
-                v-for="device in simpleDevices"
+                v-for="device in filteredDevices"
                 :key="device.id"
                 class="radio-item"
               >
@@ -52,7 +62,7 @@
             />
           </div>
 
-          <el-scrollbar height="400px">
+          <el-scrollbar height="450px">
             <el-checkbox-group v-model="selectedUsers" @change="handleUserSelectionChange">
               <div
                 v-for="user in simpleUsers"
@@ -268,6 +278,22 @@ const getUserList = async () => {
   }
 }
 
+// 设备过滤文本
+const deviceFilterText = ref('')
+
+// 计算属性:过滤设备列表
+const filteredDevices = computed(() => {
+  const searchText = deviceFilterText.value.toLowerCase().trim()
+  if (!searchText) return simpleDevices.value
+
+  return simpleDevices.value.filter(device => {
+    return (
+      (device.deviceCode || '').toLowerCase().includes(searchText) ||
+      (device.deviceName || '').toLowerCase().includes(searchText)
+    )
+  })
+})
+
 // 新增输入处理方法
 const handleReasonInput = (value: string) => {
   formData.value.reason = value
@@ -430,4 +456,14 @@ h3 {
   margin-left: 3px;
   vertical-align: middle;
 }
+
+.filter-input {
+  margin-bottom: 15px;
+}
+
+.no-data {
+  padding: 20px;
+  text-align: center;
+  color: #999;
+}
 </style>

+ 37 - 1
src/views/pms/device/statuslog/ConfigDeviceStatus.vue

@@ -18,10 +18,21 @@
               @node-click="handleDeptDeviceTreeNodeClick"
             />
           </div>
+
+          <!-- 设备搜索框 -->
+          <div class="filter-input">
+            <el-input
+              v-model="deviceFilterText"
+              :placeholder="t('devicePerson.filterDevicePlaceholder')"
+              clearable
+              prefix-icon="Search"
+            />
+          </div>
+
           <el-scrollbar height="400px">
             <el-checkbox-group v-model="selectedDevices"  @change="handleDeviceChange">
               <div
-                v-for="device in simpleDevices"
+                v-for="device in filteredDevices"
                 :key="device.id"
                 class="checkbox-item"
               >
@@ -273,6 +284,22 @@ const isMultiDevice = (row: any) => {
   return selectedDevices.value.includes(row.deviceId) && selectedDevices.value.length > 1
 }
 
+// 设备过滤文本
+const deviceFilterText = ref('')
+
+// 计算属性:过滤设备列表
+const filteredDevices = computed(() => {
+  const searchText = deviceFilterText.value.toLowerCase().trim()
+  if (!searchText) return simpleDevices.value
+
+  return simpleDevices.value.filter(device => {
+    return (
+      (device.deviceCode || '').toLowerCase().includes(searchText) ||
+      (device.deviceName || '').toLowerCase().includes(searchText)
+    )
+  })
+})
+
 // 修改删除方法
 const removeTempRelation = (deviceId: number) => {
   // 从暂存列表删除
@@ -420,4 +447,13 @@ h3 {
   vertical-align: middle;
 }
 
+.filter-input {
+  margin-bottom: 15px;
+}
+
+.no-data {
+  padding: 20px;
+  text-align: center;
+  color: #999;
+}
 </style>

+ 48 - 5
src/views/pms/iotmainworkorder/DeviceAlarmBomList.vue

@@ -14,6 +14,7 @@
         <el-table-column label="累计运行时间(H)" align="center" prop="totalRunTime" />
         <el-table-column label="累计运行公里数(KM)" align="center" prop="totalMileage" />
         <el-table-column label="保养项" align="center" prop="name" />
+        <!--
         <el-table-column label="运行里程" align="center" prop="mileageRule" >
           <template #default="scope">
             <el-switch
@@ -43,18 +44,18 @@
               :disabled="true"
             />
           </template>
-        </el-table-column>
+        </el-table-column> -->
 
         <template v-if="showTimeColumns">
-          <el-table-column label="上次保养运行时(H)" align="center" prop="lastRunningTime" />
+          <el-table-column label="上次保养运行时(H)" align="center" prop="lastRunningTime" />
           <el-table-column label="运行时间周期(H)" align="center" prop="nextRunningTime" />
-          <el-table-column label="运行时间周期-提前量(H)" align="center" prop="timePeriodLead" />
+          <el-table-column label="距离下次保养运行时长(H)" align="center" prop="timePeriod" />
         </template>
 
         <template v-if="showMileageColumns">
           <el-table-column label="上次保养里程数(KM)" align="center" prop="lastRunningKilometers" />
           <el-table-column label="运行里程周期(KM)" align="center" prop="nextRunningKilometers" />
-          <el-table-column label="运行里程周期-提前量(KM)" align="center" prop="kiloCycleLead" />
+          <el-table-column label="距离下次保养公里数(KM)" align="center" prop="kilometerCycle" />
         </template>
 
         <template v-if="showNaturalDateColumns">
@@ -72,7 +73,7 @@
             </template>
           </el-table-column>
           <el-table-column label="自然日周期(D)" align="center" prop="nextNaturalDate" />
-          <el-table-column label="自然日-提前量(D)" align="center" prop="naturalDatePeriodLead" />
+          <el-table-column label="下次保养自然日期" align="center" prop="naturalDatePeriod" />
         </template>
       </el-table>
       <!-- 分页
@@ -158,6 +159,12 @@ const getWorkOrderList = async () => {
         // 处理空值情况
         item.lastNaturalDate = ''
       }
+      // 计算下次保养运行时长 H
+      item.timePeriod = calculateTimePeriod(item);
+      // 计算下次保养公里数 KM
+      item.kilometerCycle = calculateKiloPeriod(item);
+      // 计算下次保养日期
+      item.naturalDatePeriod = calculateNextNaturalDate(item)
     })
     list.value = data
     total.value = data.total
@@ -179,6 +186,12 @@ const getPlanList = async () => {
         // 处理空值情况
         item.lastNaturalDate = ''
       }
+      // 计算下次保养运行时长 H
+      item.timePeriod = calculateTimePeriod(item);
+      // 计算下次保养公里数 KM
+      item.kilometerCycle = calculateKiloPeriod(item);
+      // 计算下次保养日期
+      item.naturalDatePeriod = calculateNextNaturalDate(item)
     })
     list.value = data
     total.value = data.total
@@ -197,6 +210,36 @@ const handleClose = () => {
   emit('close')
 }
 
+// 计算 距离下次保养运行时长 H
+const calculateTimePeriod = (item: IotMaintenanceBomVO) => {
+  if (item.runningTimeRule === 0) {
+    const next = Number(item.nextRunningTime) || 0;
+    const totalRun = Number(item.totalRunTime) || 0;
+    const lastRun = Number(item.lastRunningTime) || 0;
+    return next - (totalRun - lastRun);
+  }
+  return item.timePeriod; // 保持原始值
+};
+
+// 计算 距离下次保养公里数 KM
+const calculateKiloPeriod = (item: IotMaintenanceBomVO) => {
+  if (item.mileageRule === 0) {
+    const next = Number(item.nextRunningKilometers) || 0;
+    const totalRun = Number(item.totalMileage) || 0;
+    const lastRun = Number(item.lastRunningKilometers) || 0;
+    return next - (totalRun - lastRun);
+  }
+  return item.kilometerCycle; // 保持原始值
+};
+
+// 计算下次保养日期
+const calculateNextNaturalDate = (item: IotMaintenanceBomVO): string => {
+  if (item.naturalDateRule !== 0 || !item.lastNaturalDate || !item.nextNaturalDate) {
+    return '-'
+  }
+  return dayjs(item.lastNaturalDate).add(item.nextNaturalDate, 'day').format('YYYY-MM-DD')
+}
+
 // 新增计算属性:控制时间相关列的显示
 const showTimeColumns = computed(() => {
   return list.value.some(item => item.runningTimeRule === 0);

+ 43 - 3
src/views/pms/iotmainworkorder/IotMainWorkOrder.vue

@@ -343,6 +343,21 @@
             style="width: 60%"
           />
         </el-form-item>
+        <el-form-item
+          label="推迟原因"
+          prop="delayReason"
+          v-if="configDialog.current?.mileageRule === 0 ||
+              configDialog.current?.runningTimeRule === 0 ||
+              configDialog.current?.naturalDateRule === 0"
+        >
+          <el-input
+            v-model="configDialog.form.delayReason"
+            type="textarea"
+            :rows="2"
+            placeholder="请填写推迟原因"
+            style="width: 60%"
+          />
+        </el-form-item>
       </div>
 
       <div class="form-group" v-if="configDialog.current?.mileageRule === 0">
@@ -549,7 +564,9 @@ const configDialog = reactive({
     // 提前量
     kiloCycleLead: 0,
     timePeriodLead: 0,
-    naturalDatePeriodLead: 0
+    naturalDatePeriodLead: 0,
+    // 推迟原因
+    delayReason: ''
   }
 })
 
@@ -581,7 +598,9 @@ const openConfigDialog = (row: IotMainWorkOrderBomVO) => {
     // 提前量
     kiloCycleLead: row.kiloCycleLead || 0,
     timePeriodLead: row.timePeriodLead || 0,
-    naturalDatePeriodLead: row.naturalDatePeriodLead || 0
+    naturalDatePeriodLead: row.naturalDatePeriodLead || 0,
+    // 推迟原因
+    delayReason: row.delayReason || ''
   }
   configDialog.visible = true
 }
@@ -824,6 +843,20 @@ const submitForm = async () => {
   }
 }
 
+const validateDelayReason = (rule: any, value: any, callback: any) => {
+  const form = configDialog.form
+  const hasDelay =
+    (form.delayKilometers > 0) ||
+    (form.delayDuration > 0) ||
+    (form.delayNaturalDate > 0)
+
+  if (hasDelay && (!value || value.trim() === '')) {
+    callback(new Error('请填写推迟原因'))
+  } else {
+    callback()
+  }
+}
+
 // 新增表单校验规则
 const configFormRules = reactive({
   nextRunningKilometers: [{
@@ -855,7 +888,11 @@ const configFormRules = reactive({
     required: true,
     message: '提前量必须填写',
     trigger: 'blur'
-  }]
+  }],
+  // 新增推迟原因验证规则
+  delayReason: [
+    { validator: validateDelayReason, trigger: ['blur', 'change'] }
+  ]
 })
 
 /** 校验表格数据 */
@@ -930,6 +967,9 @@ const resetForm = () => {
   }
   formRef.value?.resetFields()
 }
+
+
+
 onMounted(async () => {
   materialList.value = []
   const deptId = useUserStore().getUser.deptId

+ 21 - 2
src/views/pms/iotmainworkorder/IotMainWorkOrderDetail.vue

@@ -350,6 +350,21 @@
             :disabled="true"
           />
         </el-form-item>
+        <el-form-item
+          label="推迟原因"
+          prop="delayReason"
+          v-if="configDialog.current?.mileageRule === 0 ||
+              configDialog.current?.runningTimeRule === 0 ||
+              configDialog.current?.naturalDateRule === 0"
+        >
+          <el-input
+            v-model="configDialog.form.delayReason"
+            type="textarea"
+            :rows="2"
+            :disabled = true
+            style="width: 60%"
+          />
+        </el-form-item>
       </div>
 
       <div class="form-group" v-if="configDialog.current?.mileageRule === 0">
@@ -555,7 +570,9 @@ const configDialog = reactive({
     // 提前量
     kiloCycleLead: 0,
     timePeriodLead: 0,
-    naturalDatePeriodLead: 0
+    naturalDatePeriodLead: 0,
+    // 推迟原因
+    delayReason: ''
   }
 })
 
@@ -587,7 +604,9 @@ const openConfigDialog = (row: IotMainWorkOrderBomVO) => {
     // 提前量
     kiloCycleLead: row.kiloCycleLead || 0,
     timePeriodLead: row.timePeriodLead || 0,
-    naturalDatePeriodLead: row.naturalDatePeriodLead || 0
+    naturalDatePeriodLead: row.naturalDatePeriodLead || 0,
+    // 推迟原因
+    delayReason: row.delayReason || ''
   }
   configDialog.visible = true
 }