lipenghui hai 4 meses
pai
achega
cea5294249

+ 49 - 1
src/router/modules/remaining.ts

@@ -213,7 +213,55 @@ const remainingRouter: AppRouteRecordRaw[] = [
       },
     ]
   },
-
+  {
+    path: '/iotpms/iotmaintenance',
+    component: Layout,
+    name: 'PmsMaintenanceCenter',
+    meta: {
+      hidden: true
+    },
+    children: [
+      {
+        path: 'maintenance/add',
+        component: () => import('@/views/pms/maintenance/IotMaintenance.vue'),
+        name: 'MaintenanceAdd',
+        meta: {
+          noCache: false,
+          hidden: true,
+          canTo: true,
+          icon: 'ep:add',
+          title: '保养计划添加',
+          activeMenu: '/maintenance/add'
+        }
+      },
+      {
+        path: 'maintenance/edit/:id(\\d+)',
+        component: () => import('@/views/pms/maintenance/IotMaintenance.vue'),
+        name: 'MaintenanceEdit',
+        meta: {
+          noCache: true,
+          hidden: true,
+          canTo: true,
+          icon: 'ep:edit',
+          title: '保养计划编辑',
+          activeMenu: '/maintenance/edit'
+        }
+      },
+      // {
+      //   path: 'maintenance/detail/:id(\\d+)',
+      //   component: () => import('@/views/pms/maintenance/IotMaintenanceDetail.vue'),
+      //   name: 'MaintenanceDetail',
+      //   meta: {
+      //     noCache: false,
+      //     hidden: true,
+      //     canTo: true,
+      //     icon: 'ep:add',
+      //     title: '保养计划详情',
+      //     activeMenu: '/maintenance/detail'
+      //   }
+      // },
+    ]
+  },
   {
     path: '/failure',
     component: Layout,

+ 438 - 0
src/views/pms/maintenance/IotMaintenance.vue

@@ -0,0 +1,438 @@
+<template>
+  <ContentWrap v-loading="formLoading">
+    <el-form
+      ref="formRef"
+      :model="formData"
+      :rules="formRules"
+      v-loading="formLoading"
+      style="margin-right: 4em; margin-left: 0.5em; margin-top: 1em"
+      label-width="130px"
+    >
+      <div class="base-expandable-content">
+        <el-row>
+          <el-col :span="6">
+            <el-form-item label="设备" prop="deviceName">
+              <el-select
+                v-model="formData.deviceName"
+                :model-value="deviceLabel"
+                placeholder="请选择设备"
+                @click="openForm"
+              />
+            </el-form-item>
+          </el-col>
+          <el-col :span="6">
+            <el-form-item label="状态" prop="status">
+              <el-select v-model="formData.status" placeholder="请选择状态" clearable>
+                <el-option
+                  v-for="dict in getStrDictOptions(DICT_TYPE.PMS_MAIN_STATUS_NO)"
+                  :key="dict.value"
+                  :label="dict.label"
+                  :value="dict.value"
+                />
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="6">
+            <el-form-item label="维修类型" prop="type">
+              <el-select disabled v-model="formData.type" placeholder="请选择维修类型" clearable>
+                <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="6">
+            <el-form-item label="是否停机" prop="ifStop">
+              <el-select v-model="formData.ifStop" placeholder="请选择是否停机" clearable>
+                <el-option
+                  v-for="dict in getStrDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
+                  :key="dict.value"
+                  :label="dict.label"
+                  :value="dict.value"
+                />
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="6">
+            <el-form-item label="故障时间" prop="failureTime">
+              <el-date-picker
+                style="width: 150%"
+                v-model="formData.failureTime"
+                type="datetime"
+                value-format="x"
+                placeholder="选择故障时间"
+              />
+            </el-form-item>
+          </el-col>
+          <el-col :span="6">
+            <el-form-item label="维修开始时间" prop="maintainStartTime">
+              <el-date-picker
+                style="width: 150%"
+                v-model="formData.maintainStartTime"
+                type="datetime"
+                value-format="x"
+                placeholder="选择维修开始时间"
+              />
+            </el-form-item>
+          </el-col>
+          <el-col :span="6">
+            <el-form-item label="维修负责人" prop="maintainPerson">
+              <el-select v-model="formData.maintainPerson" filterable clearable style="width: 100%">
+                <el-option
+                  v-for="item in deptUsers"
+                  :key="item.id"
+                  :label="item.nickname"
+                  :value="item.id"
+                />
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="6">
+            <el-form-item label="故障影响" prop="failureInfluence">
+              <el-input v-model="formData.failureInfluence" placeholder="请输入故障影响" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="6">
+            <el-form-item label="故障系统" prop="failureSystem">
+              <el-input v-model="formData.failureSystem" placeholder="请输入故障系统" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="6">
+            <el-form-item label="维修结束时间" prop="maintainEndTime">
+              <el-date-picker
+                style="width: 150%"
+                v-model="formData.maintainEndTime"
+                type="datetime"
+                value-format="x"
+                placeholder="选择维修结束时间"
+              />
+            </el-form-item>
+          </el-col>
+          <el-col :span="6">
+            <el-form-item label="图片" prop="pic">
+              <!--        <el-input v-model="formData.pic" placeholder="请输入图片" />-->
+              <UploadImg v-model="formData.pic" height="55px" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="6">
+            <el-form-item label="故障描述" prop="description">
+              <el-input type="textarea" v-model="formData.description" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="6">
+            <el-form-item label="维修描述" prop="maintainDescription">
+              <el-input type="textarea" v-model="formData.maintainDescription" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="6">
+            <el-form-item label="解决办法" prop="solution">
+              <el-input type="textarea" v-model="formData.solution" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="备注" prop="remark">
+              <el-input v-model="formData.remark" type="textarea" placeholder="请输入备注" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </div>
+    </el-form>
+  </ContentWrap>
+  <ContentWrap>
+    <ContentWrap>
+      <!-- 搜索工作栏 -->
+      <el-form
+        class="-mb-15px"
+        :model="queryParams"
+        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="handleView" 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" :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" />
+        <el-table-column label="消耗数量" align="center" prop="depleteCount">
+          <template #default="scope">
+            <el-input 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" min-width="120px">
+          <template #default="scope">
+            <div style="display: flex; justify-content: center; align-items: center; width: 100%">
+              <div>
+                <Icon style="vertical-align: middle; color: #ea3434" icon="ep:zoom-out" />
+                <el-button
+                  style="vertical-align: middle"
+                  link
+                  type="danger"
+                  @click="handleDelete(scope.row.code)"
+                >
+                  移除
+                </el-button>
+              </div>
+            </div>
+          </template>
+        </el-table-column>
+      </el-table>
+    </ContentWrap>
+
+    <!-- 表单弹窗:添加/修改 -->
+    <ChooseMaterial ref="materialFormRef" :deptId="formData.deptId" @choose="selectChoose" />
+    <MaintainMaterialDrawer
+      ref="showDrawer"
+      :model-value="drawerVisible"
+      @update:model-value="(val) => (drawerVisible = val)"
+      @add="handleChildSubmit"
+    />
+  </ContentWrap>
+  <ContentWrap>
+    <el-form>
+      <el-form-item style="float: right">
+        <el-button @click="submitForm" type="primary" :disabled="formLoading">保 存</el-button>
+        <el-button @click="close">取 消</el-button>
+      </el-form-item>
+    </el-form>
+  </ContentWrap>
+  <DeviceList ref="deviceFormRef" @choose="deviceChoose" />
+</template>
+<script setup lang="ts">
+import { IotMaintainApi, IotMaintainVO } from '@/api/pms/maintain'
+import { DICT_TYPE, 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 {IotDeviceApi} from "@/api/pms/device";
+import {CACHE_KEY, useCache} from "@/hooks/web/useCache";
+
+/** 维修工单 表单 */
+defineOptions({ name: 'IotMaintain' })
+
+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 formData = ref({
+  id: undefined,
+  failureCode: undefined,
+  failureName: undefined,
+  deviceId: undefined,
+  status: undefined,
+  type: undefined,
+  ifStop: undefined,
+  failureTime: undefined,
+  failureInfluence: undefined,
+  failureSystem: undefined,
+  description: undefined,
+  pic: undefined,
+  solution: undefined,
+  maintainStartTime: undefined,
+  maintainEndTime: undefined,
+  remark: undefined,
+  deviceName: undefined,
+  processInstanceId: undefined,
+  auditStatus: undefined,
+  deptId: undefined,
+  maintainPerson: undefined,
+  maintainDescription: undefined,
+})
+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' }],
+  failureTime: [{ required: true, message: '故障时间不能为空', trigger: 'blur' }],
+  maintainStartTime: [{ 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 formRef = ref() // 表单 Ref
+const deviceChoose = (row) => {
+  formData.value.deviceId = row.id
+  formData.value.deviceName = row.deviceName
+  formData.value.deptId = row.deptId
+  deviceLabel.value = row.deviceName
+}
+const deviceFormRef = ref()
+const openForm = () => {
+  deviceFormRef.value.open()
+}
+
+const materialFormRef = ref()
+const openMaterialForm = (type: string, id?: number) => {
+  if (!formData.value.deptId) {
+    message.error('请选择设备')
+    return
+  }
+  materialFormRef.value.open(type, id)
+}
+const close = () => {
+  delView(unref(currentRoute))
+  push({
+    name: 'IotMaintain',
+    query: {
+      date: new Date().getTime()
+    }
+  })
+}
+const handleView = () => {
+  drawerVisible.value = true
+  showDrawer.value.openDrawer()
+}
+const selectChoose = (formData) => {
+  console.log('接收到的数据:', JSON.stringify(formData))
+  list.value.push(formData)
+}
+const handleChildSubmit = (formData) => {
+  const modified = removeOnesFromKeys(formData)
+  list.value.push(modified)
+}
+
+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()
+  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 {
+    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,
+    solution: undefined,
+    maintainStartTime: undefined,
+    maintainEndTime: undefined,
+    remark: undefined,
+    deviceName: undefined,
+    processInstanceId: undefined,
+    auditStatus: undefined,
+    deptId: undefined
+  }
+  formRef.value?.resetFields()
+}
+onMounted(async () => {
+  const deptId = useUserStore().getUser.deptId
+  deptUsers.value = await UserApi.getDeptUsersByDeptId(deptId)
+  if (id){
+    formType.value = 'update'
+    const iotMaintain = await IotMaintainApi.getIotMaintain(id);
+    debugger
+    deviceLabel.value = iotMaintain.deviceName
+    formData.value = iotMaintain
+  } else {
+    formData.value.type = 'in'
+    formType.value = 'create';
+    const { wsCache } = useCache()
+    const userInfo = wsCache.get(CACHE_KEY.USER)
+    formData.value.maintainPerson = userInfo.user.id;
+  }
+})
+const handleDelete = async (id: number) => {
+  try {
+    const index = list.value.findIndex((item) => item.code === id)
+    debugger
+    if (index !== -1) {
+      // 通过 splice 删除元素
+      list.value.splice(index, 1)
+    }
+  } catch {}
+}
+</script>
+<style scoped>
+.base-expandable-content {
+  overflow: hidden; /* 隐藏溢出的内容 */
+  transition: max-height 0.3s ease; /* 平滑过渡效果 */
+}
+</style>

+ 2 - 2
src/views/pms/maintenance/details/IotMaintenanceDetailsForm.vue

@@ -63,7 +63,7 @@
   </Dialog>
 </template>
 <script setup lang="ts">
-import { IotMaintenanceDetailsApi, IotMaintenanceDetailsVO } from '@/api/rq/iotmaintenancedetails'
+import { IotMaintenanceDetailsApi, IotMaintenanceDetailsVO } from '@/api/pms/maintenance/details'
 
 /** 保养计划明细 表单 */
 defineOptions({ name: 'IotMaintenanceDetailsForm' })
@@ -155,4 +155,4 @@ const resetForm = () => {
   }
   formRef.value?.resetFields()
 }
-</script>
+</script>

+ 2 - 2
src/views/pms/maintenance/details/index.vue

@@ -216,7 +216,7 @@
 <script setup lang="ts">
 import { dateFormatter } from '@/utils/formatTime'
 import download from '@/utils/download'
-import { IotMaintenanceDetailsApi, IotMaintenanceDetailsVO } from '@/api/rq/iotmaintenancedetails'
+import { IotMaintenanceDetailsApi, IotMaintenanceDetailsVO } from '@/api/pms/maintenance/details'
 import IotMaintenanceDetailsForm from './IotMaintenanceDetailsForm.vue'
 
 /** 保养计划明细 列表 */
@@ -310,4 +310,4 @@ const handleExport = async () => {
 onMounted(() => {
   getList()
 })
-</script>
+</script>

+ 9 - 3
src/views/pms/maintenance/index.vue

@@ -128,7 +128,7 @@
     </el-col>
   </el-row>
   <!-- 表单弹窗:添加/修改 -->
-  <IotMaintenancePlanForm ref="formRef" @success="getList" />
+<!--  <IotMaintenancePlanForm ref="formRef" @success="getList" />-->
 </template>
 
 <script setup lang="ts">
@@ -137,6 +137,7 @@ import download from '@/utils/download'
 import { IotMaintenancePlanApi, IotMaintenancePlanVO } from '@/api/pms/maintenance'
 import IotMaintenancePlanForm from './IotMaintenancePlanForm.vue'
 import DeptTree from "@/views/system/user/DeptTree.vue";
+const { push } = useRouter() // 路由跳转
 
 /** 保养计划 列表 */
 defineOptions({ name: 'IotMaintenancePlan' })
@@ -191,9 +192,14 @@ const resetQuery = () => {
 }
 
 /** 添加/修改操作 */
-const formRef = ref()
 const openForm = (type: string, id?: number) => {
-  formRef.value.open(type, id)
+  //修改
+  if (typeof id === 'number') {
+    push({ name: 'MaintainEdit', params: {id } })
+    return
+  }
+  // 新增
+  push({ name: 'MaintainAdd', params:{} })
 }
 
 /** 删除按钮操作 */