From 2fc58fbb10745abd97168b8da21d4142e11d7f2e Mon Sep 17 00:00:00 2001
From: chenhj <1263187585@qq.com>
Date: 星期四, 18 十二月 2025 13:36:43 +0800
Subject: [PATCH] 新增设备维修保养过程描述,上传对应附件

---
 src/components/ImagePreview/ImagePreviewDialog.vue       |   64 ++++++++++
 src/views/equipmentManagement/upkeep/index.vue           |   23 +++
 src/api/basicData/common.js                              |   12 ++
 src/components/ImageUpload/ImageUpload.vue               |  112 ++++++++++++++++++
 src/views/equipmentManagement/repair/index.vue           |   23 +++
 src/views/equipmentManagement/repair/Form/RepairForm.vue |   64 +++++++---
 src/views/equipmentManagement/upkeep/Form/PlanForm.vue   |   16 ++
 src/views/equipmentManagement/upkeep/Modal/PlanModal.vue |    2 
 8 files changed, 289 insertions(+), 27 deletions(-)

diff --git a/src/api/basicData/common.js b/src/api/basicData/common.js
new file mode 100644
index 0000000..82012ab
--- /dev/null
+++ b/src/api/basicData/common.js
@@ -0,0 +1,12 @@
+import request from '@/utils/request'
+
+export function upload(data) {
+    return request({
+        url: '/common/minioUploads',
+        method: 'post',
+        data: data,
+        headers: {
+            'Content-Type': 'multipart/form-data'
+        }
+    })
+}
diff --git a/src/components/ImagePreview/ImagePreviewDialog.vue b/src/components/ImagePreview/ImagePreviewDialog.vue
new file mode 100644
index 0000000..d4e7ee3
--- /dev/null
+++ b/src/components/ImagePreview/ImagePreviewDialog.vue
@@ -0,0 +1,64 @@
+<template>
+  <el-dialog
+      v-model="visible"
+      title="鍥剧墖棰勮"
+      width="800px"
+      destroy-on-close
+      align-center
+  >
+    <el-carousel
+        v-if="images.length"
+        height="450px"
+        indicator-position="outside"
+        arrow="always"
+    >
+      <el-carousel-item
+          v-for="(img, index) in images"
+          :key="index"
+      >
+        <el-image
+            :src="img"
+            fit="contain"
+            style="width: 100%; height: 100%"
+            :preview-src-list="images"
+            :initial-index="index"
+            preview-teleported
+        />
+      </el-carousel-item>
+    </el-carousel>
+
+    <div v-else class="empty">
+      鏆傛棤鍥剧墖
+    </div>
+  </el-dialog>
+</template>
+
+<script setup>
+import { computed } from 'vue'
+
+const props = defineProps({
+  modelValue: {
+    type: Boolean,
+    default: false
+  },
+  images: {
+    type: Array,
+    default: () => []
+  }
+})
+
+const emit = defineEmits(['update:modelValue'])
+
+const visible = computed({
+  get: () => props.modelValue,
+  set: val => emit('update:modelValue', val)
+})
+</script>
+
+<style scoped>
+.empty {
+  text-align: center;
+  color: #999;
+  padding: 80px 0;
+}
+</style>
diff --git a/src/components/ImageUpload/ImageUpload.vue b/src/components/ImageUpload/ImageUpload.vue
new file mode 100644
index 0000000..37f0ee0
--- /dev/null
+++ b/src/components/ImageUpload/ImageUpload.vue
@@ -0,0 +1,112 @@
+<template>
+  <el-upload
+      class="image-upload"
+      list-type="picture-card"
+      :file-list="fileList"
+      action="#"
+      :http-request="customUpload"
+      :before-upload="beforeUpload"
+      :on-remove="handleRemove"
+      :on-preview="handlePreview"
+      :multiple="true"
+  >
+    <el-icon>
+      <Plus/>
+    </el-icon>
+  </el-upload>
+</template>
+
+<script>
+import {Plus} from '@element-plus/icons-vue'
+import {upload} from "@/api/basicData/common.js";
+
+export default {
+  name: 'ImageUpload',
+  emits: ['update:value'],
+  components: {Plus},
+  props: {
+    value: {
+      type: Array,
+      default: () => []
+    },
+    type: {
+      type: Number,
+      required: true
+    },
+    bucketName: {
+      type: String,
+      default: ''
+    }
+  },
+  data() {
+    return {
+      fileList: []
+    }
+  },
+  watch: {
+    /** 缂栬緫鍥炴樉 */
+    value: {
+      immediate: true,
+      handler(val) {
+        this.fileList = (val || []).map((item, index) => ({
+          id: item.id,
+          name: item.originalFilename || `image_${index}`,
+          url: item.url,
+          status: 'success',
+          response: item
+        }))
+      }
+    }
+  },
+  methods: {
+    beforeUpload(file) {
+      const isImage = file.type.startsWith('image/')
+      if (!isImage) {
+        this.$message.error('鍙兘涓婁紶鍥剧墖')
+      }
+      return isImage
+    },
+
+    customUpload({file, onSuccess, onError}) {
+      const formData = new FormData()
+      formData.append('file', file)
+      formData.append('bucketName', this.bucketName === '' ? undefined : this.bucketName)
+      formData.append('type', this.type)
+
+      upload(formData).then(res => {
+        this.fileList.push({
+          id: res.data[0].id,
+          name: res.data[0].originalFilename,
+          url: res.data[0].url,
+          status: 'success',
+          response: res.data[0]
+        })
+        onSuccess(res.data)
+        this.emitChange()
+      }).catch(err => {
+        onError(err)
+      })
+    },
+
+    handleRemove(file, fileList) {
+      this.fileList = fileList
+      this.emitChange()
+    },
+
+    handlePreview(file) {
+      window.open(file.url)
+    },
+
+    emitChange() {
+      this.$emit('update:value', this.fileList.map(item => item.response))   // v-model
+    }
+  }
+}
+</script>
+
+<style scoped>
+.image-upload ::v-deep(.el-upload--picture-card) {
+  width: 120px;
+  height: 120px;
+}
+</style>
diff --git a/src/views/equipmentManagement/repair/Form/RepairForm.vue b/src/views/equipmentManagement/repair/Form/RepairForm.vue
index 1fadde4..44f49f1 100644
--- a/src/views/equipmentManagement/repair/Form/RepairForm.vue
+++ b/src/views/equipmentManagement/repair/Form/RepairForm.vue
@@ -5,10 +5,10 @@
         <el-form-item label="璁惧鍚嶇О">
           <el-select v-model="form.deviceLedgerId" @change="setDeviceModel">
             <el-option
-              v-for="(item, index) in deviceOptions"
-              :key="index"
-              :label="item.deviceName"
-              :value="item.id"
+                v-for="(item, index) in deviceOptions"
+                :key="index"
+                :label="item.deviceName"
+                :value="item.id"
             ></el-option>
           </el-select>
         </el-form-item>
@@ -16,38 +16,53 @@
       <el-col :span="12">
         <el-form-item label="瑙勬牸鍨嬪彿">
           <el-input
-            v-model="form.deviceModel"
-            placeholder="璇疯緭鍏ヨ鏍煎瀷鍙�"
-            disabled
+              v-model="form.deviceModel"
+              placeholder="璇疯緭鍏ヨ鏍煎瀷鍙�"
+              disabled
           />
         </el-form-item>
       </el-col>
       <el-col :span="12">
         <el-form-item label="鎶ヤ慨鏃ユ湡">
           <el-date-picker
-            v-model="form.repairTime"
-            placeholder="璇烽�夋嫨鎶ヤ慨鏃ユ湡"
-            format="YYYY-MM-DD"
-            value-format="YYYY-MM-DD"
-            type="date"
-            clearable
-            style="width: 100%"
+              v-model="form.repairTime"
+              placeholder="璇烽�夋嫨鎶ヤ慨鏃ユ湡"
+              format="YYYY-MM-DD"
+              value-format="YYYY-MM-DD"
+              type="date"
+              clearable
+              style="width: 100%"
           />
         </el-form-item>
       </el-col>
       <el-col :span="12">
         <el-form-item label="鎶ヤ慨浜�">
-          <el-input v-model="form.repairName" placeholder="璇疯緭鍏ユ姤淇汉" />
+          <el-input v-model="form.repairName" placeholder="璇疯緭鍏ユ姤淇汉"/>
         </el-form-item>
       </el-col>
       <el-col :span="24">
         <el-form-item label="鏁呴殰鐜拌薄">
           <el-input
-            v-model="form.remark"
-            :rows="2"
-            type="textarea"
-            placeholder="璇疯緭鍏ユ晠闅滅幇璞�"
+              v-model="form.remark"
+              :rows="2"
+              type="textarea"
+              placeholder="璇疯緭鍏ユ晠闅滅幇璞�"
           />
+        </el-form-item>
+      </el-col>
+      <el-col :span="24">
+        <el-form-item label="杩囩▼鎻忚堪">
+          <el-input
+              v-model="form.maintenanceProcessDesc"
+              :rows="2"
+              type="textarea"
+              placeholder="璇疯緭鍏ヨ繃绋嬫弿杩�"
+          />
+        </el-form-item>
+      </el-col>
+      <el-col :span="24">
+        <el-form-item label="闄勪欢">
+          <image-upload v-model:value="form.files" :type="4"/>
         </el-form-item>
       </el-col>
     </el-row>
@@ -56,8 +71,9 @@
 
 <script setup>
 import useFormData from "@/hooks/useFormData";
-import { getDeviceLedger } from "@/api/equipmentManagement/ledger";
+import {getDeviceLedger} from "@/api/equipmentManagement/ledger";
 import useUserStore from "@/store/modules/user";
+import ImageUpload from "@/components/ImageUpload/ImageUpload.vue";
 
 defineOptions({
   name: "璁惧鎶ヤ慨琛ㄥ崟",
@@ -67,17 +83,19 @@
 const deviceOptions = ref([]);
 
 const loadDeviceName = async () => {
-  const { data } = await getDeviceLedger();
+  const {data} = await getDeviceLedger();
   deviceOptions.value = data;
 };
 
-const { form, resetForm } = useFormData({
+const {form, resetForm} = useFormData({
   deviceLedgerId: undefined, // 璁惧Id
   deviceName: undefined, // 璁惧鍚嶇О
   deviceModel: undefined, // 瑙勬牸鍨嬪彿
   repairTime: undefined, // 鎶ヤ慨鏃ユ湡
   repairName: userStore.nickName, // 鎶ヤ慨浜�
   remark: undefined, // 鏁呴殰鐜拌薄
+  maintenanceProcessDesc: undefined,
+  files: []
 });
 
 const setDeviceModel = (id) => {
@@ -96,6 +114,8 @@
   form.repairTime = data.repairTime;
   form.repairName = data.repairName;
   form.remark = data.remark;
+  form.maintenanceProcessDesc = data.maintenanceProcessDesc;
+  form.files = data.files;
 };
 
 // onMounted(() => {
diff --git a/src/views/equipmentManagement/repair/index.vue b/src/views/equipmentManagement/repair/index.vue
index 1a2ff1e..9aad3c2 100644
--- a/src/views/equipmentManagement/repair/index.vue
+++ b/src/views/equipmentManagement/repair/index.vue
@@ -119,6 +119,14 @@
             缂栬緫
           </el-button>
           <el-button
+              type="primary"
+              text
+              icon="editPen"
+              @click="showImage(row)"
+          >
+            闄勪欢
+          </el-button>
+          <el-button
             type="danger"
             text
             icon="delete"
@@ -131,17 +139,19 @@
     </div>
     <RepairModal ref="repairModalRef" @ok="getTableData" />
     <MaintainModal ref="maintainModalRef" @ok="getTableData" />
+    <ImagePreviewDialog v-model:model-value="showImages" :images="imageUrls" />
   </div>
 </template>
 
 <script setup>
 import { usePaginationApi } from "@/hooks/usePaginationApi";
-import { getRepairPage, delRepair } from "@/api/equipmentManagement/repair";
+import {getRepairPage, delRepair, getRepairById} from "@/api/equipmentManagement/repair";
 import { onMounted, getCurrentInstance } from "vue";
 import RepairModal from "./Modal/RepairModal.vue";
 import { ElMessageBox, ElMessage } from "element-plus";
 import dayjs from "dayjs";
 import MaintainModal from "./Modal/MaintainModal.vue";
+import ImagePreviewDialog from "@/components/ImagePreview/ImagePreviewDialog.vue";
 
 defineOptions({
   name: "璁惧鎶ヤ慨",
@@ -152,6 +162,9 @@
 // 妯℃�佹瀹炰緥
 const repairModalRef = ref();
 const maintainModalRef = ref();
+
+const showImages = ref(false)
+const imageUrls = ref([])
 
 // 琛ㄦ牸澶氶�夋閫変腑椤�
 const multipleList = ref([]);
@@ -231,7 +244,7 @@
       dataType: "slot",
       slot: "operation",
       align: "center",
-      width: "200px",
+      width: "300px",
     },
   ]
 );
@@ -309,6 +322,12 @@
     });
 };
 
+const showImage = async (row) => {
+  const {data} = await getRepairById(row.id)
+  imageUrls.value = data?.files.map((item) => item.url)
+  showImages.value = true
+}
+
 onMounted(() => {
   getTableData();
 });
diff --git a/src/views/equipmentManagement/upkeep/Form/PlanForm.vue b/src/views/equipmentManagement/upkeep/Form/PlanForm.vue
index e5e40c3..ff2b2c0 100644
--- a/src/views/equipmentManagement/upkeep/Form/PlanForm.vue
+++ b/src/views/equipmentManagement/upkeep/Form/PlanForm.vue
@@ -35,6 +35,17 @@
         clearable
       />
     </el-form-item>
+    <el-form-item label="杩囩▼鎻忚堪">
+      <el-input
+          v-model="form.maintenanceProcessDesc"
+          :rows="2"
+          type="textarea"
+          placeholder="璇疯緭鍏ヨ繃绋嬫弿杩�"
+      />
+    </el-form-item>
+    <el-form-item label="闄勪欢">
+      <image-upload v-model:value="form.files" :type="5"/>
+    </el-form-item>
   </el-form>
 </template>
 
@@ -43,6 +54,7 @@
 import { getDeviceLedger } from "@/api/equipmentManagement/ledger";
 import { onMounted } from "vue";
 import dayjs from "dayjs";
+import ImageUpload from "@/components/ImageUpload/ImageUpload.vue";
 
 defineOptions({
   name: "璁″垝琛ㄥ崟",
@@ -59,6 +71,8 @@
   deviceName: undefined, // 璁惧鍚嶇О
   deviceModel: undefined, // 瑙勬牸鍨嬪彿
   maintenancePlanTime: undefined, // 璁″垝淇濆吇鏃ユ湡
+  maintenanceProcessDesc: undefined,
+  files: [],
 });
 
 const setDeviceModel = (id) => {
@@ -78,6 +92,8 @@
   form.deviceLedgerId = data.deviceLedgerId;
   form.deviceName = data.deviceName;
   form.deviceModel = data.deviceModel;
+  form.maintenanceProcessDesc = data.maintenanceProcessDesc;
+  form.files = data.files;
   form.maintenancePlanTime = dayjs(data.maintenancePlanTime).format(
     "YYYY-MM-DD HH:mm:ss"
   );
diff --git a/src/views/equipmentManagement/upkeep/Modal/PlanModal.vue b/src/views/equipmentManagement/upkeep/Modal/PlanModal.vue
index d9cf246..9df28cf 100644
--- a/src/views/equipmentManagement/upkeep/Modal/PlanModal.vue
+++ b/src/views/equipmentManagement/upkeep/Modal/PlanModal.vue
@@ -2,7 +2,7 @@
   <el-dialog
     v-model="visible"
     :title="modalOptions.title"
-    width="30%"
+    width="50%"
     @close="close"
   >
     <PlanForm ref="planFormRef"></PlanForm>
diff --git a/src/views/equipmentManagement/upkeep/index.vue b/src/views/equipmentManagement/upkeep/index.vue
index a85a351..00312b7 100644
--- a/src/views/equipmentManagement/upkeep/index.vue
+++ b/src/views/equipmentManagement/upkeep/index.vue
@@ -107,6 +107,14 @@
             缂栬緫
           </el-button>
           <el-button
+              type="primary"
+              text
+              icon="editPen"
+              @click="showImage(row)"
+          >
+            闄勪欢
+          </el-button>
+          <el-button
             type="danger"
             text
             icon="delete"
@@ -119,15 +127,17 @@
     </div>
     <PlanModal ref="planModalRef" @ok="getTableData" />
     <MaintenanceModal ref="maintainModalRef" @ok="getTableData" />
+    <ImagePreviewDialog v-model:model-value="showImages" :images="imageUrls" />
   </div>
 </template>
 
 <script setup>
 import { usePaginationApi } from "@/hooks/usePaginationApi";
-import { getUpkeepPage, delUpkeep } from "@/api/equipmentManagement/upkeep";
+import {getUpkeepPage, delUpkeep, getUpkeepById} from "@/api/equipmentManagement/upkeep";
 import { onMounted, getCurrentInstance } from "vue";
 import PlanModal from "./Modal/PlanModal.vue";
 import MaintenanceModal from "./Modal/MaintenanceModal.vue";
+import ImagePreviewDialog from "@/components/ImagePreview/ImagePreviewDialog.vue";
 import dayjs from "dayjs";
 import { ElMessageBox, ElMessage } from "element-plus";
 
@@ -144,6 +154,9 @@
 
 // 琛ㄦ牸澶氶�夋閫変腑椤�
 const multipleList = ref([]);
+
+const showImages = ref(false)
+const imageUrls = ref([])
 
 // 澶氶�夊悗鍋氫粈涔�
 const handleSelectionChange = (selectionList) => {
@@ -225,7 +238,7 @@
     dataType: "slot",
     slot: "operation",
     align: "center",
-    width: "200px",
+    width: "300px",
   },
 ]);
 // type == 1瀹為檯淇濆吇鏃堕棿 2璁″垝淇濆吇鏃堕棿
@@ -296,6 +309,12 @@
     });
 };
 
+const showImage = async (row) => {
+  const {data} = await getUpkeepById(row.id)
+  imageUrls.value = data?.files.map((item) => item.url)
+  showImages.value = true
+}
+
 onMounted(() => {
   getTableData();
 });

--
Gitblit v1.9.3