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