Ver código fonte

pms 设备分类BOM设置物料数量 保养工单列表根据保养项最近保养时间排序

zhangcl 1 mês atrás
pai
commit
313aa6f572

+ 5 - 0
src/api/pms/iotmainworkorder/index.ts

@@ -31,6 +31,11 @@ export const IotMainWorkOrderApi = {
     return await request.get({ url: `/pms/iot-main-work-order/page`, params })
   },
 
+  // 获得保养工单分页 按照保养项的最近保养排序
+  sortedMainWorkOrderPage: async (params: any) => {
+    return await request.get({ url: `/pms/iot-main-work-order/sortedMainWorkOrderPage`, params })
+  },
+
   // 以设备为维度统计所有保养明细中最近的保养数据
   deviceMainDistances: async (params: any) => {
     return await request.get({ url: `/pms/iot-main-work-order/deviceMainDistances`, params })

+ 74 - 22
src/views/pms/bom/MaterialList.vue

@@ -42,20 +42,6 @@
             class="!w-200px"
           />
         </el-form-item>
-        <!--
-        <el-form-item :label="t('workOrderMaterial.materialGroup')" prop="materialGroupId" style="margin-left: 5px">
-          <el-tree-select
-            filterable
-            v-model="queryParams.materialGroupId"
-            :data="materialGroupList"
-            :props="defaultProps"
-            check-strictly
-            node-key="id"
-            :placeholder="t('workOrderMaterial.groupHolder')"
-            class="!w-220px"
-            clearable
-          />
-        </el-form-item> -->
         <el-form-item>
           <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" />
             {{ t('workOrderMaterial.search') }}</el-button>
@@ -105,9 +91,19 @@
         </el-table-column>
         <el-table-column :label="t('workOrderMaterial.materialName')" align="center" prop="name" />
         <el-table-column :label="t('workOrderMaterial.materialCode')" align="center" prop="code" />
-        <!-- <el-table-column :label="t('deviceForm.model')" align="center" prop="model" /> -->
         <el-table-column :label="t('workOrderMaterial.unit')" align="center" prop="unit" />
-        <!-- <el-table-column :label="t('form.remark')" align="center" prop="remark" show-overflow-tooltip /> -->
+        <el-table-column :label="t('route.quantity')" align="center" prop="quantity">
+          <template #default="scope">
+            <el-input
+              type="number"
+              :controls="false"
+              v-model="scope.row.quantity"
+              @click.stop=""
+              @focus="handleInputFocus(scope.row)"
+              @blur="(event) => handleQuantityBlur(event, scope.row)"
+            />
+          </template>
+        </el-table-column>
         <el-table-column
           :label="t('deviceList.createTime')"
           align="center"
@@ -148,7 +144,7 @@ const emit = defineEmits<{
 const dialogVisible = ref(false) // 弹窗的是否展示
 const loading = ref(true) // 列表的加载中
 const queryFormRef = ref() // 搜索的表单
-const list = ref<DictDataVO[]>([]) // 列表的数据
+const list = ref<MaterialApi.MaterialVO[]>([]) // 列表的数据
 const total = ref(0) // 列表的总页数
 const selectedRows = ref<MaterialApi.MaterialVO[]>([]); // 多选数据(存储所有选中行的数组)
 const tableRef = ref();
@@ -168,17 +164,24 @@ const queryParams = reactive({
 
 const selectedRow = ref(null);
 
+// 更新选中物料数量的方法
+const updateSelectedRowQuantity = (row: MaterialApi.MaterialVO) => {
+  const selectedItem = selectedRows.value.find(item => item.id === row.id);
+  if (selectedItem) {
+    selectedItem.quantity = row.quantity;
+  }
+};
+
+
 // 处理单选逻辑
 const selectRow = (row) => {
-  // selectedRow.value = selectedRow.value?.id === row.id ? null : row;
-  // emit('choose', row)
   const index = selectedRows.value.findIndex(item => item.id === row.id);
   if (index > -1) {
     selectedRows.value.splice(index, 1); // 取消选中
+    row.quantity = undefined;
   } else {
-    selectedRows.value.push(row); // 选中
+    selectedRows.value.push({ ...row }); // 选中
   }
-  // dialogVisible.value = false
 };
 
 // 点击整行选中
@@ -203,6 +206,14 @@ const getList = async () => {
     const data = await MaterialApi.getMaterialPage(queryParams)
     list.value = data.list
     total.value = data.total
+
+    // 同步selectedRows中的数量到当前页数据
+    list.value.forEach(row => {
+      const selectedItem = selectedRows.value.find(item => item.id === row.id);
+      if (selectedItem && selectedItem.quantity !== undefined) {
+        row.quantity = selectedItem.quantity;
+      }
+    });
   } finally {
     loading.value = false
   }
@@ -228,12 +239,52 @@ const removeTag = (material: MaterialApi.MaterialVO) => {
   if (rowInTable) {
     const rowIndex = list.value.indexOf(rowInTable);
     // 这里可以添加逻辑强制更新行状态(如果需要)
+    rowInTable.quantity = undefined;
   }
 };
 
+// 处理 消耗数量 quantity 输入框失焦事件
+const handleQuantityBlur = (event: Event, row: any) => {
+  const inputValue = (event.target as HTMLInputElement).value;
+  let num = parseFloat(inputValue);
+  // 处理无效值
+  if (isNaN(num)) {
+    row.quantity = 0;
+    return;
+  }
+  // 处理小于等于0的情况
+  if (num <= 0) {
+    row.quantity = 0;
+    return;
+  }
+  // 保留两位小数
+  row.quantity = parseFloat(num.toFixed(2));
+  // 实时更新selectedRows
+  updateSelectedRowQuantity(row);
+};
+
+// 处理输入框焦点事件(自动选中当前行)
+const handleInputFocus = (row: MaterialApi.MaterialVO) => {
+  const getRowUniqueKey = (row) => {
+    return `${row.code}_${row.name}`
+  }
+  const currentKey = getRowUniqueKey(row)
+  // 如果未选中则添加到选中列表
+  const exists = selectedRows.value.some(item => getRowUniqueKey(item) === currentKey)
+  if (!exists) {
+    selectedRows.value.push(row)
+  }
+}
 
 // 确认选择
 const handleConfirm = () => {
+  // 同步当前页所有选中行的最新数量
+  list.value.forEach(row => {
+    if (selectedRows.value.some(item => item.id === row.id)) {
+      updateSelectedRowQuantity(row);
+    }
+  });
+
   if (selectedRows.value.length === 0) {
     ElMessage.warning('请至少选择一个物料')
     return
@@ -243,7 +294,8 @@ const handleConfirm = () => {
     // 确保返回必要字段
     code: row.code,
     name: row.name,
-    unit: row.unit
+    unit: row.unit,
+    quantity: row.quantity,
   })))
   dialogVisible.value = false;
   handleClose()

+ 26 - 10
src/views/pms/bom/MaterialListDrawer.vue

@@ -24,19 +24,19 @@
           </div>
         </div>
 
-        <el-table :data="materials" style="width: 100%">
-          <el-table-column prop="name" label="物料名称" width="180" />
-          <el-table-column prop="code" label="物料编码" width="180" />
-          <!-- <el-table-column prop="model" label="规格型号" width="180" /> -->
-          <el-table-column prop="unit" label="单位" width="180" />
+        <el-table :data="materials" style="width: 100%" fit :row-style="{ height: '48px' }">
+          <el-table-column prop="name" label="物料名称" min-width="150" show-overflow-tooltip/>
+          <el-table-column prop="code" label="物料编码" min-width="80" />
+          <el-table-column prop="quantity" label="数量" min-width="60" align="center"/>
+          <el-table-column prop="unit" label="单位" min-width="60" align="center"/>
           <el-table-column
             label="创建时间"
             align="center"
             prop="createTime"
-            width="180"
+            min-width="110"
             :formatter="dateFormatter"
           />
-          <el-table-column label="操作" align="right">
+          <el-table-column label="操作" align="right" width="100" fixed="right">
             <template #default="scope">
               <el-button
                 size="small"
@@ -78,7 +78,7 @@ const queryParams = reactive({
   pageNo: 1,
   pageSize: 10,
   createTime: [],
-  bomId: '',
+  bomNodeId: '',
   name: '',
   code: ''
 })
@@ -114,12 +114,13 @@ watch(() => props.nodeId, async (newVal) => {
 
 // 加载指定bom节点下的物料数据
 const loadMaterials = async (nodeId) => {
-  queryParams.bomId = nodeId
+  queryParams.bomNodeId = nodeId
   queryParams.pageNo = 1
   try {
     loading.value = true
     // API调用
-    const data = await PmsMaterialApi.listByBomId(queryParams)
+    // const data = await PmsMaterialApi.listByBomId(queryParams)
+    const data = await CommonBomMaterialApi.getCommonBomMaterialPage(queryParams)
     materials.value = data.list
     total.value = data.total
   } catch (error) {
@@ -164,6 +165,21 @@ defineExpose({ openDrawer, closeDrawer, loadMaterials }) // 暴露方法给父
 </script>
 
 <style lang="scss" scoped>
+
+/* 添加表格样式优化 */
+.el-table {
+  :deep(.cell) {
+    white-space: nowrap;  /* 防止单元格内容换行 */
+  }
+
+  /* 表头样式 */
+  :deep(th.el-table__cell) {
+    background-color: #f5f7fa;
+    font-weight: bold;
+    color: #606266;
+  }
+}
+
 .info-header {
   display: flex;
   align-items: center;

+ 1 - 0
src/views/pms/bom/index.vue

@@ -298,6 +298,7 @@ const chooseMaterial = async(selectedMaterials) => {
       materialId: material.id,
       name: material.name,
       code: material.code,
+      quantity: material.quantity
     }))
 
     // 调用批量添加接口

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

@@ -113,7 +113,7 @@
           </template>
         </el-table-column>
         <el-table-column :label="t('main.mileage')" key="mileageRule" align="center"
-                         :width="columnWidths.mileageRule" v-if="hasMileageRuleInCurrentPage">
+                         :width="columnWidths.mileageRule" v-if="false">
           <template #default="scope">
             <el-switch
               v-model="scope.row.mileageRule"
@@ -124,7 +124,7 @@
           </template>
         </el-table-column>
         <el-table-column :label="t('main.runTime')" key="runningTimeRule" align="center"
-                         :width="columnWidths.runningTimeRule" v-if="hasTimeRuleInCurrentPage">
+                         :width="columnWidths.runningTimeRule" v-if="false">
           <template #default="scope">
             <el-switch
               v-model="scope.row.runningTimeRule"
@@ -135,7 +135,7 @@
           </template>
         </el-table-column>
         <el-table-column :label="t('main.date')" key="naturalDateRule" align="center"
-                         :width="columnWidths.naturalDateRule" v-if="hasDateRuleInCurrentPage">
+                         :width="columnWidths.naturalDateRule" v-if="false">
           <template #default="scope">
             <el-switch
               v-model="scope.row.naturalDateRule"
@@ -640,6 +640,7 @@ import {erpPriceTableColumnFormatter} from "@/utils";
 import dayjs from 'dayjs'
 import MaterialListDrawer from "@/views/pms/iotmainworkorder/SelectedMaterialDrawer.vue";
 import WorkOrderMaterial from "@/views/pms/iotmainworkorder/WorkOrderMaterial.vue";
+import DeviceBomMaterials from "@/views/pms/iotmainworkorder/DeviceBomMaterials.vue";
 import { IotDevicePersonApi, IotDevicePersonVO } from '@/api/pms/iotdeviceperson'
 import {DICT_TYPE, getIntDictOptions} from "@/utils/dict";
 // 引入图标

+ 1 - 1
src/views/pms/iotmainworkorder/index.vue

@@ -190,7 +190,7 @@ const exportLoading = ref(false) // 导出的加载中
 const getList = async () => {
   loading.value = true
   try {
-    const data = await IotMainWorkOrderApi.getIotMainWorkOrderPage(queryParams)
+    const data = await IotMainWorkOrderApi.sortedMainWorkOrderPage(queryParams)
     list.value = data.list
     total.value = data.total
   } finally {