lipenghui 3 mesi fa
parent
commit
5d6bebed44

+ 3 - 1
src/api/pms/device/index.ts

@@ -52,7 +52,9 @@ export const IotDeviceApi = {
   deviceAssociateBomList: async (params: any) => {
     return await request.get({ url: `/rq/iot-device/deviceAssociateBomList`, params })
   },
-
+  deviceAssociateBomListPage: async (params: any) => {
+    return await request.get({ url: `/rq/iot-device/deviceAssociateBomListPage`, params })
+  },
   // 查询设备台账详情
   getIotDevice: async (id: number) => {
     return await request.get({ url: `/rq/iot-device/get?id=` + id })

+ 85 - 46
src/views/pms/iotmainworkorder/WorkOrderMaterial.vue

@@ -1,5 +1,5 @@
 <template>
-  <Dialog v-model="dialogVisible" title="选择物料" style="width: 1100px; max-height: 800px">
+  <Dialog v-model="dialogVisible" title="选择物料" style="width: 1100px; min-height: 800px">
     <ContentWrap>
       <el-form
         class="-mb-15px"
@@ -27,7 +27,12 @@
         <el-form-item>
           <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
           <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
-          <el-button @click="handleConfirm" class="custom-green-button"><Icon icon="ep:check" class="mr-5px" /> 确认选择</el-button>
+          <el-button @click="handleConfirm" class="custom-green-button"
+            ><Icon icon="ep:check" class="mr-5px" /> 确认选择</el-button
+          >
+          <el-button @click="handleView" type="warning"
+            ><Icon icon="ep:plus" class="mr-5px" /> 新增物料</el-button
+          >
         </el-form-item>
       </el-form>
     </ContentWrap>
@@ -43,7 +48,7 @@
         <el-table-column width="60" label="选择">
           <template #default="{ row }">
             <el-checkbox
-              :model-value="selectedRows.some(item => item.materialCode === row.materialCode)"
+              :model-value="selectedRows.some((item) => item.materialCode === row.materialCode)"
               @click.stop="toggleRow(row)"
               class="no-label-radio"
             />
@@ -62,13 +67,16 @@
           prop="materialName"
           :show-overflow-tooltip="true"
         />
-        <el-table-column label="单位" align="center" prop="unit"  />
-        <el-table-column label="总库存数量" align="center" prop="totalInventoryQuantity"/>
-        <el-table-column label="消耗数量" align="center" prop="quantity" >
+        <el-table-column label="单位" align="center" prop="unit" />
+        <el-table-column label="总库存数量" align="center" prop="totalInventoryQuantity" />
+        <el-table-column label="来源" align="center" prop="materialSource" />
+        <el-table-column label="消耗数量" align="center" prop="quantity">
           <template #default="scope">
-            <el-input v-model="scope.row.quantity"
-                      @click.stop=""
-                      @focus="scope.$el.querySelector('input').focus()"/>
+            <el-input
+              v-model="scope.row.quantity"
+              @click.stop=""
+              @focus="scope.$el.querySelector('input').focus()"
+            />
           </template>
         </el-table-column>
       </el-table>
@@ -81,16 +89,21 @@
       />
     </ContentWrap>
   </Dialog>
+  <MaintainMaterialDrawer
+    ref="showDrawer"
+    :model-value="drawerVisible"
+    @update:model-value="(val) => (drawerVisible = val)"
+    @add="handleChildSubmit"
+  />
 </template>
 
 <script setup lang="ts">
-import * as MaintainMaterialApi from '@/api/pms/maintain/material'
-import * as WorkOrderBomMaterialApi from '@/api/pms/iotmainworkorderbommaterial'
 import { IotMaintainMaterialVO } from '@/api/pms/maintain/material'
-import { propTypes } from '@/utils/propTypes'
-import { defineExpose } from 'vue';
-import {IotDeviceVO} from "@/api/pms/device";
+import * as WorkOrderBomMaterialApi from '@/api/pms/iotmainworkorderbommaterial'
+import { defineExpose, ref } from 'vue'
+import MaintainMaterialDrawer from '@/views/pms/maintain/material/MaintainMaterialDrawer.vue'
 
+const message = useMessage() // 消息弹窗
 // const emit = defineEmits(['choose']) // 定义 success 事件,用于操作成功后的回调
 // 调整 emit 类型
 const emit = defineEmits<{
@@ -102,8 +115,8 @@ const loading = ref(true) // 列表的加载中
 const queryFormRef = ref() // 搜索的表单
 const list = ref<WorkOrderBomMaterialApi.IotMainWorkOrderBomMaterialVO[]>([]) // 列表的数据
 const total = ref(0) // 列表的总页数
-const tableRef = ref();
-const selectedRows = ref<WorkOrderBomMaterialApi.IotMainWorkOrderBomMaterialVO[]>([]); // 多选数据(存储所有选中行的数组)
+const tableRef = ref()
+const selectedRows = ref<WorkOrderBomMaterialApi.IotMainWorkOrderBomMaterialVO[]>([]) // 多选数据(存储所有选中行的数组)
 const queryParams = reactive({
   pageNo: 1,
   pageSize: 10,
@@ -112,25 +125,43 @@ const queryParams = reactive({
   name: '',
   code: ''
 })
-
-const selectedRow = ref(null)
-
-// 处理单选逻辑
-const selectRow = (row) => {
-  selectedRow.value = selectedRow.value?.id === row.id ? null : row
-  emit('choose', row)
-  dialogVisible.value = false
+const drawerVisible = ref<boolean>(false)
+const showDrawer = ref()
+const handleView = () => {
+  drawerVisible.value = true
+  showDrawer.value.openDrawer()
+}
+const addMateriall = ref(null)
+const handleChildSubmit = (formData) => {
+  const modified = removeOnesFromKeys(formData)
+  modified.materialName = modified.name;
+  modified.materialCode = modified.code;
+  modified.materialSource = '手动添加';
+  addMateriall.value = modified;
+  list.value.unshift(modified)
+  total.value = total.value+1
+  debugger
+}
+const removeOnesFromKeys = (obj: Record<string, any>) => {
+  return Object.keys(obj).reduce(
+    (acc, key) => {
+      const newKey = key.replace(/1/g, '') // 替换所有 1
+      acc[newKey] = obj[key]
+      return acc
+    },
+    {} as Record<string, any>
+  )
 }
-
 // 点击整行选中
 const handleRowClick = (row) => {
   toggleRow(row)
 }
 const open = async (deptId: number, bomNodeId: number) => {
   console.log('传递过来的数据:', deptId)
+  selectedRows.value = []
   dialogVisible.value = true
-  queryParams.deptId = deptId;
-  queryParams.bomNodeId = bomNodeId;
+  queryParams.deptId = deptId
+  queryParams.bomNodeId = bomNodeId
   await getList()
 }
 
@@ -155,36 +186,45 @@ const handleConfirm = () => {
     ElMessage.warning('请至少选择一个物料')
     return
   }
-  emit('choose', selectedRows.value.map(row => ({
-    ...row,
-    // 确保返回必要字段
-    id: row.id,
-    materialCode: row.materialCode,
-    materialName: row.materialName,
-    unitPrice: row.unitPrice,
-    unit: row.unit,
-    quantity: row.quantity,
-  })))
-  dialogVisible.value = false;
+  const filters = selectedRows.value.filter((item) => item.quantity === null||item.quantity === undefined)
+  debugger
+  if (filters.length > 0) {
+    message.error('消耗数量必填')
+    return
+  }
+  emit(
+    'choose',
+    selectedRows.value.map((row) => ({
+      ...row,
+      // 确保返回必要字段
+      id: row.id,
+      materialCode: row.materialCode,
+      materialName: row.materialName,
+      unitPrice: row.unitPrice,
+      unit: row.unit,
+      quantity: row.quantity
+    }))
+  )
+  dialogVisible.value = false
   handleClose()
-};
+}
 
 // 关闭时清空选择
 const handleClose = () => {
-  tableRef.value?.clearSelection();
+  tableRef.value?.clearSelection()
   selectedRows.value = []
   emit('close')
-};
+}
 
 // 多选 切换行选中状态
 const toggleRow = (row) => {
-  const index = selectedRows.value.findIndex(item => item.materialCode === row.materialCode);
+  const index = selectedRows.value.findIndex((item) => item.materialCode === row.materialCode)
   if (index > -1) {
-    selectedRows.value.splice(index, 1); // 取消选中
+    selectedRows.value.splice(index, 1) // 取消选中
   } else {
-    selectedRows.value.push(row); // 选中
+    selectedRows.value.push(row) // 选中
   }
-};
+}
 
 /** 搜索按钮操作 */
 const handleQuery = () => {
@@ -209,7 +249,6 @@ const resetQuery = () => {
   margin-right: 0;
 }
 
-
 /* 自定义淡绿色按钮 */
 :deep(.custom-green-button) {
   background-color: #e1f3d8;

+ 144 - 63
src/views/pms/maintain/IotMaintain.vue

@@ -13,7 +13,7 @@
           <el-col :span="8">
             <el-form-item label="设备" prop="deviceName">
               <el-select
-                :disabled="formType==='update'"
+                :disabled="formType === 'update'"
                 v-model="formData.deviceName"
                 :model-value="deviceLabel"
                 placeholder="请选择设备"
@@ -128,7 +128,7 @@
               />
             </el-form-item>
           </el-col>
-          <el-col :span="8" v-if="formData.type === 'out'" >
+          <el-col :span="8" v-if="formData.type === 'out'">
             <el-form-item label="委外相关附件" prop="outFile">
               <UploadFile v-model="formData.outFile" class="min-w-80px" />
             </el-form-item>
@@ -162,12 +162,16 @@
       <!-- 搜索工作栏 -->
       <el-form class="-mb-15px" ref="queryFormRef" :inline="true" label-width="68px">
         <el-form-item>
-          <el-button @click="openMaterialForm" type="primary"
-            ><Icon icon="ep:plus" class="mr-5px" /> 选择物料</el-button
+          <!--          <el-button @click="openMaterialForm" type="primary"-->
+          <!--            ><Icon icon="ep:plus" class="mr-5px" /> 选择物料</el-button>-->
+          <el-button @click="openMaintainForm" type="primary"
+            ><Icon icon="ep:plus" class="mr-5px" /> 选择维修项</el-button
           >
-          <el-button @click="handleView" type="warning"
-            ><Icon icon="ep:plus" class="mr-5px" /> 新增物料</el-button
+          <el-button @click="openMaintainItem" type="warning"
+            ><Icon icon="ep:plus" class="mr-5px" /> 新增维修项</el-button
           >
+          <!--          <el-button @click="handleViewNew" type="warning"-->
+          <!--            ><Icon icon="ep:plus" class="mr-5px" /> 新增物料</el-button>-->
         </el-form-item>
       </el-form>
     </ContentWrap>
@@ -175,26 +179,10 @@
     <!-- 列表 -->
     <ContentWrap>
       <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
-        <el-table-column label="物料编码" align="center" prop="code" />
-        <el-table-column label="物料名称" align="center" prop="name" />
-        <el-table-column label="单位" align="center" prop="unit" />
-        <el-table-column label="单价" align="center" prop="price">
-          <template #default="{ row }">
-            {{ row.price }}
-          </template>
-        </el-table-column>
-        <el-table-column label="消耗数量" align="center" prop="depleteCount">
-          <template #default="scope">
-            <el-input-number :precision="2" :step="0.1" v-model="scope.row.depleteCount" />
-          </template>
-        </el-table-column>
-        <el-table-column label="总库存数量" align="center" prop="totalCount" />
-        <el-table-column label="备注" align="center" prop="remark">
-          <template #default="scope">
-            <el-input v-model="scope.row.remark" />
-          </template>
-        </el-table-column>
-        <el-table-column label="物料来源" align="center" prop="sourceType" />
+        <el-table-column label="资产编码" align="center" prop="deviceCode" />
+        <el-table-column label="设备名称" align="center" prop="deviceName" />
+        <el-table-column label="维修项" align="center" prop="name" />
+
         <el-table-column label="操作" align="center" min-width="120px">
           <template #default="scope">
             <div style="display: flex; justify-content: center; align-items: center; width: 100%">
@@ -209,6 +197,16 @@
                   移除
                 </el-button>
               </div>
+              <div style="margin-left: 12px">
+                <el-button link type="primary" @click="openMaterialForm(scope.row)">
+                  选择物料
+                </el-button>
+              </div>
+              <div style="margin-left: 12px">
+                <el-button link type="primary" @click="handleViewNew(scope.row.bomNodeId)">
+                  物料详情
+                </el-button>
+              </div>
             </div>
           </template>
         </el-table-column>
@@ -216,13 +214,8 @@
     </ContentWrap>
 
     <!-- 表单弹窗:添加/修改 -->
-    <ChooseMaterial ref="materialFormRef" :deptId="formData.deptId" @choose="selectChoose" />
-    <MaintainMaterialDrawer
-      ref="showDrawer"
-      :model-value="drawerVisible"
-      @update:model-value="(val) => (drawerVisible = val)"
-      @add="handleChildSubmit"
-    />
+    <WorkOrderMaterial ref="materialFormRef" @choose="selectChoose" />
+    <ChooseMaintain ref="maintainFormRef" @choose="maintainChoose" />
   </ContentWrap>
   <ContentWrap>
     <el-form>
@@ -234,6 +227,37 @@
   </ContentWrap>
   <DeviceList ref="deviceFormRef" @choose="deviceChoose" />
   <CustomerList ref="customerFormRef" @choose="customerChoose" />
+  <MaterialListDrawer
+    :model-value="drawerVisible"
+    @update:model-value="(val) => (drawerVisible = val)"
+    :node-id="currentBomNodeId"
+    :materials="materialList.filter((item) => item.bomNodeId === currentBomNodeId)"
+  />
+  <Dialog title="维修项" v-model="addItemVisible" style="min-height: 300px">
+    <el-form
+      ref="addFormRef"
+      :model="addFormData"
+      :rules="addFormRules"
+      label-position="right"
+      label-width="68px"
+    >
+      <el-form-item label="资产编码" prop="deviceCode">
+        <el-input v-model="addFormData.deviceCode" disabled />
+      </el-form-item>
+      <el-form-item label="设备名称" prop="deviceName">
+        <el-input v-model="addFormData.deviceName" disabled />
+      </el-form-item>
+      <el-form-item label="维修项" prop="name">
+        <el-input v-model="addFormData.name" placeholder="请输入维修项" />
+      </el-form-item>
+    </el-form>
+    <el-form>
+      <el-form-item style="float: right">
+        <el-button @click="handleConfirm" type="primary">确 定</el-button>
+        <el-button @click="closeDialog">取 消</el-button>
+      </el-form-item>
+    </el-form>
+  </Dialog>
 </template>
 <script setup lang="ts">
 import { IotMaintainApi } from '@/api/pms/maintain'
@@ -241,17 +265,18 @@ import { DICT_TYPE, getBoolDictOptions, getStrDictOptions } from '@/utils/dict'
 import DeviceList from '@/views/pms/failure/DeviceList.vue'
 import * as UserApi from '@/api/system/user'
 import { useUserStore } from '@/store/modules/user'
-import ChooseMaterial from '@/views/pms/maintain/material/ChooseMaterial.vue'
-import MaintainMaterialDrawer from '@/views/pms/maintain/material/MaintainMaterialDrawer.vue'
 import { ref } from 'vue'
 import { IotMaintainMaterialVO } from '@/api/pms/maintain/material'
 import { useTagsViewStore } from '@/store/modules/tagsView'
 import { CACHE_KEY, useCache } from '@/hooks/web/useCache'
 import CustomerList from '@/views/pms/device/CustomerList.vue'
+import WorkOrderMaterial from '@/views/pms/iotmainworkorder/WorkOrderMaterial.vue'
+import { IotMainWorkOrderBomMaterialVO } from '@/api/pms/iotmainworkorderbommaterial'
+import MaterialListDrawer from '@/views/pms/iotmainworkorder/SelectedMaterialDrawer.vue'
 
 /** 维修工单 表单 */
 defineOptions({ name: 'IotMaintainAe' })
-
+const addItemVisible = ref(false) // 弹窗的是否展示
 const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
 const { delView } = useTagsViewStore() // 视图操作
@@ -267,6 +292,11 @@ const list = ref<IotMaintainMaterialVO[]>([]) // 列表的数据
 const { params, name } = useRoute() // 查询参数
 const id = params.id
 const supplierLabel = ref('') // 表单的类型:create - 新增;update - 修改
+const addFormData = ref({
+  name: '',
+  deviceName: '',
+  deviceCode: ''
+})
 const formData = ref({
   id: undefined,
   failureCode: undefined,
@@ -297,11 +327,11 @@ const formData = ref({
 const strictRules = {
   required: true,
   message: '请输入维修费用'
-};
+}
 const supplierRules = {
   required: true,
   message: '请选择供应商'
-};
+}
 const formRules = reactive({
   deviceName: [{ required: true, message: '设备不能为空', trigger: 'blur' }],
   failureCode: [{ required: true, message: '故障编码不能为空', trigger: 'blur' }],
@@ -317,6 +347,9 @@ const formRules = reactive({
   // status: [{ required: true, message: '状态不能为空', trigger: 'blur' }]
 })
 
+const addFormRules = reactive({
+  name: [{ required: true, message: '维修项不能为空', trigger: 'blur' }]
+})
 const outFormRules = reactive({
   deviceName: [{ required: true, message: '设备不能为空', trigger: 'blur' }],
   failureCode: [{ required: true, message: '故障编码不能为空', trigger: 'blur' }],
@@ -332,6 +365,10 @@ const outFormRules = reactive({
   supplier: [{ required: true, message: '供应商不能为空', trigger: 'blur' }]
 })
 
+const handleConfirm = () => {
+  list.value.push(addFormData.value)
+  addItemVisible.value = false
+}
 const customerChoose = (row) => {
   formData.value.supplier = row.id
   supplierLabel.value = row.name
@@ -342,9 +379,11 @@ const openCustomer = (type) => {
   customerFormRef.value.open(type)
 }
 const formRef = ref() // 表单 Ref
+const addFormRef = ref()
 const deviceChoose = (row) => {
   formData.value.deviceId = row.id
   formData.value.deviceName = row.deviceName
+  formData.value.deviceCode = row.deviceCode
   formData.value.deptId = row.deptId
   deviceLabel.value = row.deviceName
 }
@@ -354,12 +393,25 @@ const openForm = () => {
 }
 
 const materialFormRef = ref()
-const openMaterialForm = (type: string, id?: number) => {
-  if (!formData.value.deptId) {
+const currentBomNodeId = ref() // 当前选中的bom节点
+const openMaterialForm = (row: any) => {
+  bomNodeId.value = row.bomNodeId
+  console.log('这是一个对象:', row.bomNodeId)
+  materialFormRef.value.open(formData.value.deptId, bomNodeId.value)
+}
+
+const maintainFormRef = ref()
+const openMaintainForm = (type: string, id?: number) => {
+  if (!formData.value.deviceId) {
     message.error('请选择设备')
     return
   }
-  materialFormRef.value.open(type, id)
+  maintainFormRef.value.open(type, formData.value.deviceId)
+}
+const openMaintainItem = () => {
+  addItemVisible.value = true
+  addFormData.value.deviceName = formData.value.deviceName
+  addFormData.value.deviceCode = formData.value.deviceCode
 }
 const endTimeBlur = () => {
   if (formData.value.maintainEndTime <= formData.value.maintainStartTime) {
@@ -369,26 +421,55 @@ const endTimeBlur = () => {
 }
 const close = () => {
   delView(unref(currentRoute))
-  push({ name: 'IotMaintain', params:{}})
-  // delView(unref(currentRoute))
-  // push({
-  //   name: 'IotMaintain',
-  //   query: {
-  //     date: new Date().getTime()
-  //   }
-  // })
+  push({ name: 'IotMaintain', params: {} })
+}
+const closeDialog = () => {
+  addItemVisible.value = false
 }
-const handleView = () => {
+
+const handleViewNew = (nodeId) => {
+  currentBomNodeId.value = nodeId
   drawerVisible.value = true
-  showDrawer.value.openDrawer()
+  // showDrawer.value.openDrawer()
+  console.log('当前bom节点:', currentBomNodeId.value)
 }
-const selectChoose = (formData) => {
-  console.log('接收到的数据:', JSON.stringify(formData))
-  list.value.push(formData)
+const materialList = ref<IotMainWorkOrderBomMaterialVO[]>([]) // 保养工单bom关联物料列表
+const bomNodeId = ref() // 最新的bomNodeId
+const selectChoose = (selectedMaterial) => {
+  // console.log('接收到的数据:', JSON.stringify(formData))
+  // list.value.push(formData)
+  selectedMaterial.bomNodeId = bomNodeId.value
+  // 关联 bomNodeId
+  const processedMaterials = selectedMaterial.map((material) => ({
+    ...material,
+    bomNodeId: bomNodeId.value // 统一关联当前行的 bomNodeId
+  }))
+
+  // 避免重复添加
+  processedMaterials.forEach((newMaterial) => {
+    // 检查是否已存在相同 bomNodeId + materialCode 的条目
+    const isExist = materialList.value.some(
+      (item) => item.bomNodeId === bomNodeId.value && item.materialCode === newMaterial.materialCode
+    )
+
+    if (!isExist) {
+      materialList.value.push(newMaterial)
+    }
+  })
+  console.log('选择完成的数据:', JSON.stringify(selectedMaterial))
+  console.log('添加到本地列表的数据:', materialList.value)
+}
+const maintainChoose = (formData) => {
+  console.log('接收到的数据eee:', JSON.stringify(formData))
+  formData.forEach((item) => {
+    list.value.push(item)
+  })
 }
 const handleChildSubmit = (formData) => {
   const modified = removeOnesFromKeys(formData)
-  list.value.push(modified)
+  modified.forEach((item) => {
+    list.value.push(item)
+  })
 }
 
 const removeOnesFromKeys = (obj: Record<string, any>) => {
@@ -406,14 +487,14 @@ const emit = defineEmits(['success']) // 定义 success 事件,用于操作成
 const submitForm = async () => {
   // 校验表单
   await formRef.value.validate()
-  if (list.value.length > 0) {
-    const nullList = list.value.filter((item) => item.depleteCount === null)
-    debugger
-    if (nullList.length > 0) {
-      message.error('请填写消耗数量')
-      return
-    }
-  }
+  // if (list.value.length > 0) {
+  //   const nullList = list.value.filter((item) => item.depleteCount === null)
+  //   debugger
+  //   if (nullList.length > 0) {
+  //     message.error('请填写消耗数量')
+  //     return
+  //   }
+  // }
   // 提交请求
   formLoading.value = true
   try {

+ 242 - 0
src/views/pms/maintain/material/ChooseMaintain.vue

@@ -0,0 +1,242 @@
+<template>
+  <Dialog v-model="dialogVisible" title="选择维修项" style="width: 1100px; max-height: 800px">
+    <ContentWrap>
+      <el-form
+        class="-mb-15px"
+        :model="queryParams"
+        ref="queryFormRef"
+        :inline="true"
+        label-width="68px"
+      >
+        <el-form-item label="物料编码" prop="code">
+          <el-input
+            v-model="queryParams.code"
+            placeholder="请输入物料编码"
+            clearable
+            @keyup.enter="handleQuery"
+          />
+        </el-form-item>
+        <el-form-item label="物料名称" prop="name">
+          <el-input
+            v-model="queryParams.name"
+            placeholder="请输入物料名称"
+            clearable
+            @keyup.enter="handleQuery"
+          />
+        </el-form-item>
+        <el-form-item>
+          <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
+          <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
+          <el-button @click="handleConfirm" class="custom-green-button"
+            ><Icon icon="ep:check" class="mr-5px" /> 确认选择</el-button
+          >
+          <el-button @click="toggleAll" type="primary"
+            ><Icon icon="ep:refresh" class="mr-5px" />全选</el-button
+          >
+          <el-button @click="invertSelection" type="info"
+            ><Icon icon="ep:refresh" class="mr-5px" />取消全选</el-button
+          >
+        </el-form-item>
+      </el-form>
+    </ContentWrap>
+    <ContentWrap>
+      <el-table
+        ref="tableRef"
+        v-loading="loading"
+        :data="list"
+        :stripe="true"
+        :show-overflow-tooltip="true"
+        @row-click="handleRowClick"
+        row-key="id"
+        @selection-change="handleSelectionChange"
+      >
+        <el-table-column
+          type="selection"
+          :reserve-selection="true"
+          :selectable="(row) => !row.disabled"
+        />
+        <el-table-column
+          label="资产编码"
+          align="center"
+          prop="deviceCode"
+          :show-overflow-tooltip="true"
+          class="!w-100px"
+        />
+        <el-table-column
+          label="设备名称"
+          align="center"
+          prop="deviceName"
+          :show-overflow-tooltip="true"
+        />
+        <el-table-column
+          label="设备名称"
+          align="center"
+          prop="deviceName"
+          :show-overflow-tooltip="true"
+        />
+        <el-table-column label="维修项" align="center" prop="name" :show-overflow-tooltip="true" />
+        <el-table-column
+          label="创建时间"
+          align="center"
+          prop="createTime"
+          :formatter="dateFormatter"
+          width="180px"
+        />
+      </el-table>
+      <!-- 分页 -->
+      <Pagination
+        :total="total"
+        v-model:page="queryParams.pageNo"
+        v-model:limit="queryParams.pageSize"
+        @pagination="getList"
+      />
+    </ContentWrap>
+  </Dialog>
+</template>
+
+<script setup lang="ts">
+import { IotDeviceApi } from '@/api/pms/device'
+import { IotMaintainMaterialVO } from '@/api/pms/maintain/material'
+import { propTypes } from '@/utils/propTypes'
+import { dateFormatter } from '@/utils/formatTime'
+const message = useMessage() // 消息弹窗
+const emit = defineEmits(['choose']) // 定义 success 事件,用于操作成功后的回调
+const dialogVisible = ref(false) // 弹窗的是否展示
+const loading = ref(true) // 列表的加载中
+const queryFormRef = ref() // 搜索的表单
+const selectedRows = ref<any[]>([]) // 多选数据(存储所有选中行的数组)
+const list = ref<any[]>([]) // 列表的数据
+const total = ref(0) // 列表的总页数
+const tableRef = ref()
+const queryParams = reactive({
+  pageNo: 1,
+  pageSize: 10,
+  deviceIds: []
+})
+const props = defineProps({
+  deptId: propTypes.number.def(undefined)
+})
+const invertSelection = () => {
+  selectedRows.value.forEach((row) => {
+    tableRef.value.toggleRowSelection(row, false)
+    selectedRows.value.splice(row)
+  })
+}
+const toggleAll = () => {
+  list.value.forEach((row) => {
+    tableRef.value.toggleRowSelection(row, true)
+  })
+}
+const selectedRow = ref(null)
+const handleConfirm = () => {
+  if (selectedRows.value.length === 0) {
+    ElMessage.warning('请至少选择一个维修项')
+    return
+  }
+
+  // emit('choose', selectedRows.value);
+  emit(
+    'choose',
+    selectedRows.value.map((row) => ({
+      ...row
+      // 确保返回必要字段
+      // code: row.item,
+      // name: row.standard
+    }))
+  )
+  dialogVisible.value = false
+  handleClose()
+}
+// 关闭时清空选择
+const handleClose = () => {
+  tableRef.value?.clearSelection()
+  selectedRows.value = []
+  emit('close')
+}
+// 处理单选逻辑
+const selectRow = (row) => {
+  selectedRow.value = selectedRow.value?.id === row.id ? null : row
+  emit('choose', row)
+  dialogVisible.value = false
+}
+
+// 点击整行选中
+const handleRowClick = (row) => {
+  toggleRow(row)
+}
+const toggleRow = (row) => {
+  const includes = selectedRows.value.includes(row)
+  if (includes) {
+    selectedRows.value.splice(row)
+  } else {
+    selectedRows.value.push(row) // 选中
+  }
+  tableRef.value.toggleRowSelection(row, !includes)
+}
+const handleSelectionChange = (val) => {
+  selectedRows.value = val
+}
+const open = async (type: string, id?: number) => {
+  dialogVisible.value = true
+  queryParams.deviceIds.push(id)
+  await getList()
+}
+defineExpose({ open }) // 提供 open 方法,用于打开弹窗
+const getList = async () => {
+  loading.value = true
+  try {
+    const res = await IotDeviceApi.deviceAssociateBomListPage(queryParams)
+    debugger
+    const rawData = res || []
+    if (rawData.length === 0) {
+      message.error('选择的设备不存在待保养BOM项')
+    }
+    list.value = rawData.list
+    total.value = rawData.total
+  } finally {
+    loading.value = false
+  }
+}
+
+/** 搜索按钮操作 */
+const handleQuery = () => {
+  queryParams.pageNo = 1
+  getList()
+}
+const choose = (row: IotMaintainMaterialVO) => {
+  emit('choose', row)
+  dialogVisible.value = false
+}
+/** 重置按钮操作 */
+const resetQuery = () => {
+  queryFormRef.value.resetFields()
+  handleQuery()
+}
+</script>
+<style lang="scss">
+.no-label-radio .el-radio__label {
+  display: none;
+}
+.no-label-radio .el-radio__inner {
+  margin-right: 0;
+}
+/* 自定义淡绿色按钮 */
+:deep(.custom-green-button) {
+  background-color: #e1f3d8;
+  border-color: #e1f3d8;
+  color: #67c23a;
+}
+
+/* 悬停效果 */
+:deep(.custom-green-button:hover) {
+  background-color: #d1e8c0;
+  border-color: #d1e8c0;
+  color: #5daf34;
+}
+
+/* 点击效果 */
+:deep(.custom-green-button:active) {
+  background-color: #c2dca8;
+  border-color: #c2dca8;
+}
+</style>

+ 3 - 0
src/views/pms/maintain/material/MaterialSelect.vue

@@ -95,6 +95,8 @@ import * as DictTypeApi from '@/api/system/dict/dict.type'
 import { checkPermi } from '@/utils/permission'
 import * as MaterialApi from '@/api/pms/material'
 import {DICT_TYPE} from "@/utils/dict";
+import {CrmStatisticCustomerAreaRespVO} from "@/api/crm/statistics/portrait";
+import {areaReplace} from "@/utils";
 
 const emit = defineEmits(['choose']) // 定义 success 事件,用于操作成功后的回调
 const dialogVisible = ref(false) // 弹窗的是否展示
@@ -125,6 +127,7 @@ const handleRowClick = (row) => {
 }
 const open = async (type: string, id?: number) => {
   dialogVisible.value = true
+  selectedRow.value = ''
   await getList()
 }
 defineExpose({ open }) // 提供 open 方法,用于打开弹窗