Browse Source

资料库前端处理

lipenghui 2 weeks ago
parent
commit
72cd92a046

+ 0 - 1
src/views/pms/iotinfo/IotInfoFormTree.vue

@@ -190,7 +190,6 @@ const handleUploadSuccess = (data) => {
     formData.value.folderTree = []
   }
   formData.value.folderTree.push(data.response.data);
-  console.log('777777777777777'+JSON.stringify(formData.value.folderTree))
   message.success(`"${data.name}" 上传成功`);
 };
 

+ 883 - 0
src/views/pms/maintain/IotMaintainAddEdit.vue

@@ -0,0 +1,883 @@
+<template>
+  <ContentWrap v-loading="formLoading">
+    <ContentWrap>
+      <el-form
+        ref="formRef"
+        :model="formData"
+        :rules="formRules"
+        style="margin-right: 4em; margin-left: 0.5em; margin-top: 1em"
+        label-width="130px"
+      >
+        <div class="base-expandable-content">
+          <el-row>
+            <el-col :span="8">
+              <el-form-item :label="t('iotMaintain.device')" prop="deviceName">
+                <el-select
+                  :disabled="formType === 'update'"
+                  v-model="formData.deviceName"
+                  clearable
+                  @clear="deviceClear"
+                  :placeholder="t('iotMaintain.deviceHolder')"
+                  @click="formType === 'update' ? undefined : openForm()"
+                />
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item :label="t('iotMaintain.repairType')" prop="type">
+                <el-select v-model="formData.type" :placeholder="t('iotMaintain.repairTypeHolder')" clearable @change="typeChange">
+                  <el-option
+                    v-for="dict in getStrDictOptions(DICT_TYPE.PMS_MAIN_TYPE)"
+                    :key="dict.value"
+                    :label="dict.label"
+                    :value="dict.value"
+                  />
+                </el-select>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item :label="t('iotMaintain.shutDown')" prop="ifStop">
+                <el-select v-model="formData.ifStop" :placeholder="t('iotMaintain.shutDownHolder')" clearable>
+                  <el-option
+                    v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
+                    :key="dict.value"
+                    :label="dict.label"
+                    :value="dict.value"
+                  />
+                </el-select>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item
+                :label="t('iotMaintain.startTime')"
+                prop="maintainStartTime"
+                :rules="formData.type === 'in' ? startRule : []"
+              >
+                <el-date-picker
+                  style="width: 150%"
+                  v-model="formData.maintainStartTime"
+                  type="datetime"
+                  value-format="x"
+                  :placeholder="t('iotMaintain.startTimeHolder')"
+                />
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item
+                :label="t('iotMaintain.endTime')"
+                prop="maintainEndTime"
+                :rules="formData.type === 'in' ? endRule : []"
+              >
+                <el-date-picker
+                  @change="endTimeBlur"
+                  style="width: 150%"
+                  v-model="formData.maintainEndTime"
+                  type="datetime"
+                  value-format="x"
+                  :placeholder="t('iotMaintain.endTimeHolder')"
+                />
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item :label="t('iotMaintain.failureTime')" prop="failureTime" :rules="formData.type==='out'?failureTimeRule:[]" >
+                <el-date-picker
+                  @change="failureTimeBlur"
+                  :disabled="formData.maintainType==='故障上报'"
+                  style="width: 150%"
+                  v-model="formData.failureTime"
+                  type="datetime"
+                  value-format="x"
+                  :placeholder="t('iotMaintain.failureTimeHolder')"
+                />
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item :label="t('iotMaintain.failureImpact')" prop="failureInfluence">
+                <el-input v-model="formData.failureInfluence" :placeholder="t('iotMaintain.failureImpactHolder')" />
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item :label="t('iotMaintain.faultySystem')" prop="failureSystem">
+                <el-input v-model="formData.failureSystem" :placeholder="t('iotMaintain.faultySystemHolder')" />
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item :label="t('iotMaintain.picture')" prop="pics">
+                <UploadImgs v-model="formData.pics" height="55px" />
+              </el-form-item>
+            </el-col>
+            <el-col :span="8" v-if="formData.type === 'out'">
+              <el-form-item :label="t('iotMaintain.applyPerson')" prop="applyPersonId" :rules="formData.type==='out'?classifyRules:[]">
+                <el-select v-model="formData.applyPersonId" :placeholder="t('iotMaintain.applyPersonHolder')" clearable filterable>
+                  <el-option
+                    v-for="person in applyPeoPle"
+                    :key="person.oaId"
+                    :label="person.lastname"
+                    :value="person.oaId"
+                  />
+                </el-select>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8" v-if="formData.type === 'out'">
+              <el-form-item :label="t('iotMaintain.maintainClassify')" prop="maintainClassify" :rules="formData.type==='out'?classifyRules:[]">
+                <el-select v-model="formData.maintainClassify" :placeholder="t('iotMaintain.maintainClassifyHolder')" clearable>
+                  <el-option
+                    v-for="dict in getStrDictOptions(DICT_TYPE.PMS_MAIN_CLASSIFY)"
+                    :key="dict.value"
+                    :label="dict.label"
+                    :value="dict.value"
+                  />
+                </el-select>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8" v-if="formData.type === 'out'">
+              <el-form-item :label="t('iotMaintain.kmHour')" prop="kmHour">
+                <el-input v-model="formData.kmHour" :placeholder="t('iotMaintain.kmHourHolder')" />
+              </el-form-item>
+            </el-col>
+            <el-col :span="8" v-if="formData.type === 'out'">
+              <el-form-item :label="t('deviceForm.model')" prop="model" :rules="formData.type==='out'?modelRules:[]">
+                <el-input v-model="formData.model" :placeholder="t('deviceForm.modelHolder')" />
+              </el-form-item>
+            </el-col>
+            <el-col :span="8" v-if="formData.type === 'out'">
+              <el-form-item :label="t('deviceForm.enable')" prop="enableDate" :rules="formData.type==='out'?modelRules:[]">
+                <el-date-picker
+                  style="width: 150%"
+                  v-model="formData.enableDate"
+                  type="date"
+                  value-format="YYYY-MM-DD"
+                  :placeholder="t('deviceForm.enableHolder')"
+                />
+              </el-form-item>
+            </el-col>
+            <el-col :span="8" v-if="formData.type === 'out'">
+              <div style="display: flex;flex-direction: row">
+              <el-form-item :label="t('iotMaintain.supplier')" prop="supplier" style="width: 86%" :rules="formData.type==='out'?supplierRules:[]">
+                <el-input
+                  clearable
+                  v-model="formData.supplier"
+                  :placeholder="t('iotMaintain.suppHolder')"
+                />
+              </el-form-item>
+              <el-button type="info" @click="openCustomer('supplier')">请选择</el-button>
+              </div>
+            </el-col>
+            <el-col :span="8" >
+              <el-form-item :label="t('iotMaintain.repairCosts')" prop="maintainFee" :rules="formData.type==='out'?feeRules:[]">
+                <el-input-number
+                  :disabled="formData.type==='in'"
+                  v-model="formData.maintainFee"
+                  :min="0"
+                  :precision="2"
+                  :step="0.1"
+                  style="width: 100%"
+                />
+              </el-form-item>
+            </el-col>
+            <el-col :span="8" v-if="formData.type === 'out'">
+              <el-form-item :label="t('iotMaintain.projectManager')" prop="projectManager" :rules="formData.type==='out'?projectRules:[]">
+                <el-select v-model="formData.projectManager" :placeholder="t('iotMaintain.projectManagerHolder')" clearable filterable>
+                  <el-option
+                    v-for="person in projectManager"
+                    :key="person.oaId"
+                    :label="person.lastname"
+                    :value="person.oaId"
+                  />
+                </el-select>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8"  v-if="formData.type === 'out'">
+              <el-form-item :label="t('iotMaintain.address')" prop="address">
+                <el-input  v-model="formData.address"/>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8" v-if="formData.type === 'out'">
+              <el-form-item :label="t('iotMaintain.attachment')" prop="outFiles">
+                <UploadFile v-model="formData.outFiles" :is-show-tip="false" class="min-w-80px" multiple :limit="9" />
+              </el-form-item>
+            </el-col>
+            <el-col :span="16"  v-if="formData.type === 'out'" >
+              <el-form-item :label="t('iotMaintain.maintainItem')" prop="maintainItem" :rules="formData.type==='out'?itemRules:[]">
+                <el-input type="textarea" v-model="formData.maintainItem"/>
+              </el-form-item>
+            </el-col>
+            <el-col :span="16">
+              <el-form-item :label="t('iotMaintain.faultDescription')" prop="description">
+                <el-input type="textarea" v-model="formData.description"/>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item :label="t('iotMaintain.repairDescription')" prop="maintainDescription">
+                <el-input type="textarea" v-model="formData.maintainDescription" />
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item :label="t('iotMaintain.solution')" prop="solution">
+                <el-input type="textarea" v-model="formData.solution" />
+              </el-form-item>
+            </el-col>
+            <el-col :span="24">
+              <el-form-item :label="t('iotMaintain.remark')" prop="remark">
+                <el-input v-model="formData.remark" type="textarea" :placeholder="t('iotMaintain.remarkHolder')" />
+              </el-form-item>
+            </el-col>
+          </el-row>
+        </div>
+      </el-form>
+    </ContentWrap>
+    <ContentWrap>
+      <ContentWrap>
+        <!-- 搜索工作栏 -->
+        <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="openMaintainForm" type="primary"
+              ><Icon icon="ep:plus" class="mr-5px" />
+              {{ t('iotMaintain.selectMaintenanceItem') }}</el-button
+            >
+            <el-button @click="openMaintainItem" type="warning"
+              ><Icon icon="ep:plus" class="mr-5px" />
+              {{ t('iotMaintain.addMaintenanceItems') }}</el-button
+            >
+            <!--          <el-button @click="handleViewNew" type="warning"-->
+            <!--            ><Icon icon="ep:plus" class="mr-5px" /> 新增物料</el-button>-->
+          </el-form-item>
+        </el-form>
+      </ContentWrap>
+
+      <!-- 列表 -->
+      <ContentWrap>
+        <el-table v-loading="loading" :data="list" class="abc"  @row-click="handleRowClick"
+        :row-class-name="tableRowClassName">
+          <el-table-column :label="t('iotMaintain.deviceCode')" align="center" prop="deviceCode" />
+          <el-table-column :label="t('iotMaintain.deviceName')" align="center" prop="deviceName" />
+          <el-table-column :label="t('iotMaintain.repairItems')"  align="center" prop="name" />
+          <el-table-column :label="t('iotMaintain.numberOfMaterials')" align="center" prop="materialCount" >
+            <template #default="scope">
+              <el-tag v-if="scope.row.materialCount" type="danger"> {{scope.row.materialCount}}</el-tag>
+            </template>
+          </el-table-column>
+          <el-table-column :label="t('iotMaintain.ifNeed')"  align="center" prop="ifNeed">
+            <template #default="scope">
+              <el-switch
+                v-model="scope.row.ifNeed"
+                @change="handleIfNeedChange(scope.row)"
+              />
+            </template>
+
+          </el-table-column>
+          <el-table-column :label="t('iotMaintain.operation')" align="center" min-width="120px">
+            <template #default="scope">
+              <div style="display: flex; justify-content: center; align-items: center; width: 100%">
+                <div>
+                  <el-button
+                    style="vertical-align: middle"
+                    link
+                    type="danger"
+                    @click="handleDelete(scope.row.bomNodeId)"
+                  >
+                    <Icon style="vertical-align: middle; color: #ea3434" icon="ep:zoom-out" />
+                    {{ t('iotMaintain.remove') }}
+                  </el-button>
+                </div>
+              </div>
+            </template>
+          </el-table-column>
+        </el-table>
+      </ContentWrap>
+
+
+      <!-- 表单弹窗:添加/修改 -->
+      <WorkOrderMaterial ref="materialFormRef" @choose="selectChoose" />
+      <ChooseMaintain ref="maintainFormRef" @choose="maintainChoose" />
+    </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)"
+      @delete = "materialDelete"
+    />
+    <Dialog :title="t('iotMaintain.repairItems')" 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="t('iotMaintain.BOMNodeID')" v-if="false" prop="deviceCode">
+          <el-input v-model="addFormData.bomNodeId" disabled />
+        </el-form-item>
+        <el-form-item :label="t('iotMaintain.deviceCode')" prop="deviceCode">
+          <el-input v-model="addFormData.deviceCode" disabled />
+        </el-form-item>
+        <el-form-item :label="t('iotMaintain.deviceName')" prop="deviceName">
+          <el-input v-model="addFormData.deviceName" disabled />
+        </el-form-item>
+        <el-form-item :label="t('iotMaintain.repairItems')" prop="name">
+          <el-input v-model="addFormData.name" :placeholder="t('iotMaintain.repairItemsHolder')" />
+        </el-form-item>
+      </el-form>
+      <el-form>
+        <el-form-item style="float: right">
+          <el-button @click="handleConfirm" type="primary">{{ t('iotMaintain.ok') }}</el-button>
+          <el-button @click="closeDialog">{{  t('iotMaintain.cancel')  }}</el-button>
+        </el-form-item>
+      </el-form>
+    </Dialog>
+  </ContentWrap>
+  <ContentWrap v-if="materialIfShow">
+    <ContentWrap>
+      <!-- 搜索工作栏 -->
+      <el-form class="-mb-15px" ref="queryFormRef" :inline="true" label-width="68px">
+        <el-form-item>
+          <el-button type="danger" @click="openMaterialForm()">
+            {{ t('iotMaintain.selectMaterials') }}
+          </el-button>
+        </el-form-item>
+      </el-form>
+    </ContentWrap>
+    <ContentWrap>
+      <el-table :data="filteredMaterials" style="width: 100%">
+        <el-table-column prop="bomNodeId" :label="t('bomList.bomNode')" width="180" v-if="false"/>
+        <el-table-column prop="factory" :label="t('workOrderMaterial.factory')" width="180" v-if="!hideExtraColumns"/>
+        <el-table-column prop="costCenter" :label="t('workOrderMaterial.costCenter')" width="180" v-if="!hideExtraColumns"/>
+        <el-table-column prop="projectDepartment" :label="t('workOrderMaterial.storageLocation')"  width="180" v-if="!hideExtraColumns"/>
+        <el-table-column prop="materialName" :label="t('workOrderMaterial.materialName')" width="180" />
+        <el-table-column prop="materialCode" :label="t('workOrderMaterial.materialCode')" width="180" />
+        <el-table-column prop="unit" :label="t('workOrderMaterial.unit')" width="180" />
+        <el-table-column prop="unitPrice" :label="t('workOrderMaterial.unitPrice')" width="180" />
+        <el-table-column prop="quantity" :label="t('workOrderMaterial.ConsumptionQuantity')" width="180" />
+        <el-table-column prop="materialSource" :label="t('bomList.type')" width="180" />
+        <el-table-column :label="t('workplace.operation')" align="right" v-if="true">
+          <template #default="scope">
+            <el-button
+              size="small"
+              type="danger"
+              @click="handleDelete(scope.row)"
+            >{{ t('form.delete') }}</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+    </ContentWrap>
+    <ContentWrap>
+      <el-form>
+        <el-form-item style="float: right">
+          <el-button @click="submitForm" type="primary" :disabled="formLoading">{{ t('iotMaintain.save') }}</el-button>
+          <el-button @click="close">{{ t('iotMaintain.cancel') }}</el-button>
+        </el-form-item>
+      </el-form>
+    </ContentWrap>
+  </ContentWrap>
+</template>
+<script setup lang="ts">
+import { IotMaintainApi } from '@/api/pms/maintain'
+import { DICT_TYPE, getBoolDictOptions, getStrDictOptions } from '@/utils/dict'
+import DeviceList from '@/views/pms/failure/DeviceList.vue'
+import * as UserApi from '@/api/system/user'
+import { ref } from 'vue'
+import { IotMaintainMaterialVO } from '@/api/pms/maintain/material'
+import { useTagsViewStore } from '@/store/modules/tagsView'
+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'
+import ChooseMaintain from '@/views/pms/maintain/material/ChooseMaintain.vue'
+import { CACHE_KEY, useCache } from '@/hooks/web/useCache'
+import dayjs from 'dayjs'
+import {checkPermi} from "@/utils/permission";
+/** 维修工单 表单 */
+defineOptions({ name: 'MaintainAdd' })
+const addItemVisible = ref(false) // 弹窗的是否展示
+const materialIfShow = ref(true)
+const { t } = useI18n() // 国际化
+const message = useMessage() // 消息弹窗
+const { delView } = useTagsViewStore() // 视图操作
+const { currentRoute, push } = useRouter()
+const deptUsers = ref<UserApi.UserVO[]>([]) // 用户列表
+const dialogTitle = ref('') // 弹窗的标题
+const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
+const formType = ref('') // 表单的类型:create - 新增;update - 修改
+const deviceLabel = ref('') // 表单的类型:create - 新增;update - 修改
+const drawerVisible = ref<boolean>(false)
+const showDrawer = ref()
+const list = ref<IotMaintainMaterialVO[]>([]) // 列表的数据
+const { params, name } = useRoute() // 查询参数
+const id = params.id
+const supplierLabel = ref('') // 表单的类型:create - 新增;update - 修改
+const totalFee = ref(0)
+const applyPeoPle = ref([])
+const projectManager = ref([])
+const { wsCache } = useCache()
+const hideExtraColumns = ref(false)
+const filteredMaterials = ref([])
+const selectedRowId = ref<number | null>(null)
+const selectedRow = ref({})
+const loading = ref(false)
+
+const addFormData = ref({
+  name: '',
+  deviceName: '',
+  deviceCode: '',
+  bomNodeId: '',
+})
+const formData = ref({
+  kmHour:undefined,
+  maintainItem:undefined,
+  enableDate: undefined,
+  projectManager:undefined,
+  applyPersonId:undefined,
+  maintainClassify: undefined,
+  address:undefined,
+  model:undefined,
+  id: undefined,
+  failureCode: undefined,
+  failureName: undefined,
+  deviceId: undefined,
+  status: undefined,
+  type: undefined,
+  ifStop: undefined,
+  failureTime: undefined,
+  failureInfluence: undefined,
+  failureSystem: undefined,
+  description: undefined,
+  pic: undefined,
+  pics: [],
+  outFiles:[],
+  solution: undefined,
+  maintainStartTime: undefined,
+  maintainEndTime: undefined,
+  remark: undefined,
+  deviceName: undefined,
+  deviceCode: undefined,
+  processInstanceId: undefined,
+  auditStatus: undefined,
+  deptId: undefined,
+  maintainPerson: undefined,
+  maintainDescription: undefined,
+  supplier: undefined,
+  maintainFee: undefined,
+  outFile: undefined,
+  maintainType: undefined,
+})
+const failureTimeRule = [{ required: true, message: '故障时间不能为空', trigger: 'blur' }]
+const supplierRules = [{ required: true, message: '供应商不能为空', trigger: 'blur' }]
+const projectRules = [{ required: true, message: '项目经理不能为空', trigger: 'blur' }]
+const itemRules = [{ required: true, message: '维修项目不能为空', trigger: 'blur' }]
+const classifyRules = [{ required: true, message: '维修类别不能为空', trigger: 'blur' }]
+const feeRules = [{ required: true, message: '维修费用不能为空', trigger: 'blur' }]
+const modelRules = [{ required: true, message: '规格型号不能为空', trigger: 'blur' }]
+const startRule = [{ required: true, message: '维修开始时间不能为空', trigger: 'blur' }]
+const descriptionRule = [{required: true, message:'维修描述不能为空', trigger: 'blur' }]
+const endRule = [{ required: true, message: '维修结束时间不能为空', trigger: 'blur' }]
+const formRules = reactive({
+  deviceName: [{ required: true, message: '设备不能为空', trigger: 'blur' }],
+  failureCode: [{ required: true, message: '故障编码不能为空', trigger: 'blur' }],
+  type: [{ required: true, message: '维修类型不能为空', trigger: 'blur' }],
+  ifStop: [{ required: true, message: '是否停机不能为空', trigger: 'blur' }],
+  failureName: [{ required: true, message: '故障名称不能为空', trigger: 'blur' }],
+  description: [{ required: true, message: '故障描述不能为空', trigger: 'blur' }],
+  maintainDescription: [{ required: true, message: '维修描述不能为空', trigger: 'blur' }],
+  // failureTime: [{ required: true, message: '故障时间不能为空', trigger: 'blur' }],
+  // maintainStartTime: [{ required: true, message: '维修开始时间不能为空', trigger: 'blur' }],
+  // maintainEndTime: [{ required: true, message: '维修结束时间不能为空', trigger: 'blur' }],
+  // maintainDescription: [{ required: true, message: '维修描述不能为空', trigger: 'blur' }],
+  // maintainPerson: [{ required: true, message: '维修负责人不能为空', trigger: 'blur' }],
+  deviceId: [{ required: true, message: '设备id不能为空', trigger: 'blur' }]
+  // status: [{ required: true, message: '状态不能为空', trigger: 'blur' }]
+})
+const handleIfNeedChange = (row) =>{
+  debugger
+  if (row.ifNeed) {
+    materialIfShow.value = true
+  } else {
+    materialIfShow.value = false
+  }
+}
+// 行点击事件处理函数
+const handleRowClick = (row: any) => {
+  if (selectedRowId.value === row.bomNodeId) {
+    selectedRowId.value = null
+    selectedRow.value = null
+  } else {
+    // 否则选中当前行
+    selectedRowId.value = row.bomNodeId
+    selectedRow.value = row
+  }
+  // 保留原有的点击逻辑(如果有的话)
+  console.log('点击了行:', selectedRowId.value)
+  debugger
+  if (selectedRow.value === null) {
+    filteredMaterials.value = materialList.value;
+  }
+  filteredMaterials.value = materialList.value.filter((item) => item.bomNodeId === row.bomNodeId)
+  if (row.ifNeed) {
+    materialIfShow.value = true
+  } else {
+    materialIfShow.value = false
+  }
+}
+
+// 行样式类名方法
+const tableRowClassName = ({ row }: { row: any }) => {
+  // 如果是选中的行,返回自定义类名
+  return row.bomNodeId === selectedRowId.value ? 'green-row' : ''
+}
+const addFormRules = reactive({
+  name: [{ required: true, message: '维修项不能为空', trigger: 'blur' }]
+})
+
+const typeChange = async () =>{
+  if (formData.value.type === 'out') {
+    await IotMaintainApi.getApplyUsers("").then((res) => {
+      applyPeoPle.value = res
+    })
+    await IotMaintainApi.getProjectUsers("").then((res) => {
+      debugger
+      projectManager.value = res
+    })
+  }
+}
+
+const handleConfirm = () => {
+  addFormData.value.bomNodeId = Math.floor(100000 + Math.random() * 900000)
+
+  const index = list.value.findIndex((item) => item.name === addFormData.value.name)
+  if (index !== -1) {
+    message.warning("维修项重复")
+    return
+  }
+  const addItem = {...addFormData.value}
+  addItem.ifNeed = true
+  list.value.push(addItem)
+  addItemVisible.value = false
+}
+const customerChoose = (row) => {
+  formData.value.supplier = row.name
+  // supplierLabel.value = row.name
+}
+
+const customerFormRef = ref()
+const openCustomer = (type) => {
+  customerFormRef.value.open(type)
+}
+const formRef = ref() // 表单 Ref
+const addFormRef = ref()
+const deviceChoose = (row) => {
+  formData.value.model = row.model
+  formData.value.enableDate = row.enableDate
+  formData.value.deviceId = row.id
+  formData.value.deviceName = row.deviceName
+  formData.value.deviceCode = row.deviceCode
+  formData.value.deptId = row.deptId
+  // deviceLabel.value = row.deviceName
+  list.value = []
+}
+const deviceClear = () => {
+  formData.value.deviceId = undefined
+  formData.value.deviceName = undefined
+  formData.value.deviceCode = undefined
+  formData.value.deptId = undefined
+  list.value = []
+}
+const deviceFormRef = ref()
+const openForm = () => {
+  deviceFormRef.value.open()
+}
+const materialFormRef = ref()
+const currentBomNodeId = ref() // 当前选中的bom节点
+const openMaterialForm = () => {
+  debugger
+  if (selectedRowId.value === null) {
+    message.error('请点击选择维修项');
+    return
+  }
+  const row = selectedRow.value
+  bomNodeId.value = row.bomNodeId
+  console.log('设备id:', formData.value.deviceId)
+  row.deviceId = formData.value.deviceId
+  const type = 'repair'
+  materialFormRef.value.open(formData.value.deptId, bomNodeId.value, row, type)
+}
+
+const maintainFormRef = ref()
+const openMaintainForm = (type: string, id?: number) => {
+  if (!formData.value.deviceId) {
+    message.error(t('iotMaintain.deviceHolder'))
+    return
+  }
+  maintainFormRef.value.open(type, formData.value.deviceId)
+}
+const openMaintainItem = () => {
+  if (!formData.value.deviceId) {
+    message.error(t('iotMaintain.deviceHolder'))
+    return
+  }
+  addItemVisible.value = true
+  addFormData.value.deviceName = formData.value.deviceName
+  addFormData.value.deviceCode = formData.value.deviceCode
+  addFormData.value.name = ''
+}
+const endTimeBlur = () => {
+  if (formData.value.maintainEndTime <= formData.value.maintainStartTime) {
+    message.error('维修结束时间不得早于开始时间')
+    formData.value.maintainEndTime = undefined
+  }
+  const now = dayjs();
+  const target = dayjs(formData.value.maintainEndTime);
+  if (target.isAfter(now)) {
+    message.error('维修结束时间不得晚于当前时间')
+    formData.value.maintainEndTime = undefined
+  }
+}
+
+const failureTimeBlur = () => {
+  if (formData.value.maintainStartTime < formData.value.failureTime) {
+    message.error('维修开始时间不得早于故障时间')
+    formData.value.maintainStartTime = undefined
+  }
+  if (formData.value.maintainEndTime < formData.value.failureTime) {
+    message.error('维修结束时间不得早于故障时间')
+    formData.value.maintainEndTime = undefined
+  }
+}
+const close = () => {
+  delView(unref(currentRoute))
+  push({ name: 'IotMaintain', params: {} })
+}
+const closeDialog = () => {
+  addItemVisible.value = false
+}
+
+const handleViewNew = (nodeId) => {
+  currentBomNodeId.value = nodeId
+  drawerVisible.value = true
+  console.log('当前bom节点:', currentBomNodeId.value)
+}
+
+const materialDelete = (row) =>{
+  totalFee.value = 0
+  const index = materialList.value.findIndex((item) => item.bomNodeId === bomNodeId.value&&item.materialCode===row.materialCode)
+  if (index>-1) {
+    materialList.value.splice(index,1)
+  }
+  list.value.forEach((item)=>{
+    if (item.bomNodeId === row.bomNodeId){
+      item.materials = materialList.value.filter((item)=>item.bomNodeId===row.bomNodeId)
+        item.materialCount = item.materials.length;
+      }
+    })
+
+  materialList.value.forEach((it) => {
+    totalFee.value = it.unitPrice * it.quantity + totalFee.value
+  })
+  formData.value.maintainFee = totalFee.value
+}
+
+const materialList = ref<IotMainWorkOrderBomMaterialVO[]>([]) // 保养工单bom关联物料列表
+const bomNodeId = ref() // 最新的bomNodeId
+
+const selectChoose = (selectedMaterial) => {
+  debugger
+  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)
+    }
+  })
+  totalFee.value = 0;
+  list.value.forEach((item) => {
+    if (item.bomNodeId === bomNodeId.value) {
+      item.materials = materialList.value.filter((item) => item.bomNodeId === bomNodeId.value)
+      if (item.materials) {
+        item.materialCount = item.materials.length;
+      }
+    }
+  })
+  materialList.value.forEach((it) => {
+    totalFee.value = it.unitPrice * it.quantity + totalFee.value
+  })
+  formData.value.maintainFee = totalFee.value
+  console.log('选择完成的数据:', JSON.stringify(selectedMaterial))
+  console.log('添加到本地列表的数据:', materialList.value)
+  filteredMaterials.value = materialList.value.filter((item) => item.bomNodeId === bomNodeId.value)
+}
+const maintainChoose = (formData) => {
+  formData.forEach((item) => {
+    const index = list.value.findIndex((li) => item.name === li.name)
+    if (index==-1){
+      item.ifNeed= true
+      list.value.push(item)
+      if (item.deviceBomMaterials) {
+        item.deviceBomMaterials.forEach((it) => {
+          it.bomNodeId = item.bomNodeId
+          it.materialCode = it.code;
+          it.materialName = it.name
+          materialList.value.push(it)
+        })
+      }
+    }
+  })
+  if (selectedRow.value === null) {
+    filteredMaterials.value = materialList.value
+  }
+}
+
+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 emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
+const submitForm = async () => {
+  // 校验表单
+  await formRef.value.validate()
+  // 提交请求
+  formLoading.value = true
+  try {
+    if (formData.value.type==='in') {
+      formData.value.status = 'finished'
+    } else {
+      formData.value.status = 'tx'
+    }
+
+    // let files: any[]
+    // files = formData.value.outFile
+    // if (files) {
+    //   formData.value.outFile = files
+    //     .map((element) => {
+    //       return element.path
+    //     })
+    //     .join(',')
+    // }
+    const data = {
+      maintain: formData.value,
+      maintainMaterials: list.value
+    }
+    if (formType.value === 'create') {
+      await IotMaintainApi.createIotMaintain(data)
+      message.success(t('common.createSuccess'))
+      close()
+    } else {
+      await IotMaintainApi.updateIotMaintain(data)
+      message.success(t('common.updateSuccess'))
+      close()
+    }
+    // 发送操作成功的事件
+    emit('success')
+  } finally {
+    formLoading.value = false
+  }
+}
+
+/** 重置表单 */
+const resetForm = () => {
+  formData.value = {
+    id: undefined,
+    failureCode: undefined,
+    failureName: undefined,
+    deviceId: undefined,
+    status: undefined,
+    ifStop: undefined,
+    failureTime: undefined,
+    failureInfluence: undefined,
+    failureSystem: undefined,
+    description: undefined,
+    pic: undefined,
+    pics:[],
+    solution: undefined,
+    maintainStartTime: undefined,
+    maintainEndTime: undefined,
+    remark: undefined,
+    deviceName: undefined,
+    processInstanceId: undefined,
+    auditStatus: undefined,
+    deptId: undefined
+  }
+  formRef.value?.resetFields()
+}
+const userId = ref('')
+onMounted(async () => {
+  const userInfo = wsCache.get(CACHE_KEY.USER)
+  userId.value = userInfo.user.id;
+  if (id) {
+    formType.value = 'update'
+    const iotMaintain = await IotMaintainApi.getIotMaintain(id)
+    deviceLabel.value = iotMaintain.deviceName
+    formData.value = iotMaintain
+    formData.value.status = undefined
+    if (formData.value.type === 'out') {
+      await IotMaintainApi.getApplyUsers("").then((res) => {
+        applyPeoPle.value = res
+      })
+      await IotMaintainApi.getProjectUsers("").then((res) => {
+        debugger
+        projectManager.value = res
+      })
+    }
+  } else {
+    formData.value.type = 'in'
+    formType.value = 'create'
+  }
+})
+const handleDelete = async (id: number) => {
+  try {
+    const index = list.value.findIndex((item) => item.bomNodeId === id)
+    if (index !== -1) {
+      // 通过 splice 删除元素
+      list.value.splice(index, 1)
+      totalFee.value = 0
+      list.value.forEach(item => {
+        item.materials.forEach((it) => {
+          totalFee.value = it.unitPrice * it.quantity + totalFee.value
+        })
+      })
+      formData.value.maintainFee = totalFee.value
+    }
+  } catch {}
+}
+</script>
+<style scoped>
+.base-expandable-content {
+  overflow: hidden; /* 隐藏溢出的内容 */
+  transition: max-height 0.3s ease; /* 平滑过渡效果 */
+}
+/* 添加绿色行的样式 */
+::v-deep .abc .el-table__row.green-row {
+  background-color: #6af48f; /* 浅绿色背景 */
+}
+
+::v-deep .abc .el-table__row.green-row:hover > td {
+  background-color: #6af48f !important; /* 鼠标悬停时的绿色背景 */
+}
+
+::v-deep .abc .el-table__row.green-row > td {
+  background-color: #6af48f; /* 选中行的单元格背景 */
+}
+
+/* 可选:添加选中行的边框样式 */
+::v-deep .abc .el-table__row.green-row {
+  border-left: 3px solid #52c41a; /* 左侧绿色边框标识 */
+}
+</style>