From b88332e0a2686e68023e26438af97f79247b1ddd Mon Sep 17 00:00:00 2001
From: gongchunyi <deslre0381@gmail.com>
Date: 星期六, 16 五月 2026 14:14:53 +0800
Subject: [PATCH] feat: 设备保养修改,新增保养人、详情
---
src/views/equipmentManagement/upkeep/index.vue | 111 ++++++---
src/views/equipmentManagement/upkeep/Form/UpkeepDetailModal.vue | 202 ++++++++++++++++
src/views/equipmentManagement/upkeep/Form/PlanModal.vue | 245 ++++++++++++++++---
src/views/equipmentManagement/upkeep/Form/formDia.vue | 80 ++++-
src/components/Dialog/FileListDialog.vue | 16 +
src/views/equipmentManagement/upkeep/Form/MaintenanceModal.vue | 9
src/api/equipmentManagement/maintenanceTaskFile.js | 14 +
7 files changed, 568 insertions(+), 109 deletions(-)
diff --git a/src/api/equipmentManagement/maintenanceTaskFile.js b/src/api/equipmentManagement/maintenanceTaskFile.js
index 8373ae3..2e4dd4e 100644
--- a/src/api/equipmentManagement/maintenanceTaskFile.js
+++ b/src/api/equipmentManagement/maintenanceTaskFile.js
@@ -18,6 +18,20 @@
});
}
+export function bindMaintenanceTaskFile(data) {
+ return addMaintenanceTaskFile(data);
+}
+
+// 涓婁紶淇濆吇璁″垝闄勪欢
+export function uploadMaintenanceTaskFile(formData) {
+ return request({
+ url: "/maintenanceTaskFile/upload",
+ method: "post",
+ data: formData,
+ headers: { "Content-Type": "multipart/form-data" },
+ });
+}
+
// 鍒犻櫎淇濆吇浠诲姟闄勪欢
export function delMaintenanceTaskFile(id) {
return request({
diff --git a/src/components/Dialog/FileListDialog.vue b/src/components/Dialog/FileListDialog.vue
index fc82411..ce1eced 100644
--- a/src/components/Dialog/FileListDialog.vue
+++ b/src/components/Dialog/FileListDialog.vue
@@ -10,6 +10,7 @@
class="upload-demo"
:action="uploadAction"
:headers="uploadHeaders"
+ :data="uploadData"
:show-file-list="false"
:on-success="handleDefaultUploadSuccess"
:on-error="handleDefaultUploadError">
@@ -169,6 +170,14 @@
type: String,
default: `${import.meta.env.VITE_APP_BASE_API}/file/upload`,
},
+ uploadData: {
+ type: Object,
+ default: () => ({}),
+ },
+ uploadDirectSave: {
+ type: Boolean,
+ default: false,
+ },
isShowPagination: {
type: Boolean,
default: false,
@@ -278,8 +287,13 @@
ElMessage.error(res?.msg || "鏂囦欢涓婁紶澶辫触");
return;
}
+ if (props.uploadDirectSave) {
+ ElMessage.success("涓婁紶鎴愬姛");
+ emit("upload", res?.data || {});
+ return;
+ }
if (!props.rulesRegulationsManagementId) {
- ElMessage.error("缂哄皯瑙勭珷鍒跺害ID锛屾棤娉曚繚瀛橀檮浠�");
+ ElMessage.error("缂哄皯涓氬姟ID锛屾棤娉曚繚瀛橀檮浠�");
return;
}
const fileName = res?.data?.originalName || file?.name;
diff --git a/src/views/equipmentManagement/upkeep/Form/MaintenanceModal.vue b/src/views/equipmentManagement/upkeep/Form/MaintenanceModal.vue
index c660840..6b574a5 100644
--- a/src/views/equipmentManagement/upkeep/Form/MaintenanceModal.vue
+++ b/src/views/equipmentManagement/upkeep/Form/MaintenanceModal.vue
@@ -2,7 +2,7 @@
<FormDialog
v-model="visible"
:title="'璁惧淇濆吇'"
- width="500px"
+ width="640px"
@confirm="sendForm"
@cancel="handleCancel"
@close="handleClose"
@@ -35,8 +35,13 @@
<el-form-item label="淇濆吇缁撴灉">
<el-input
v-model="form.maintenanceResult"
+ type="textarea"
+ :rows="6"
placeholder="璇疯緭鍏ヤ繚鍏荤粨鏋�"
- type="text" />
+ maxlength="2000"
+ show-word-limit
+ resize="vertical"
+ />
</el-form-item>
</el-form>
</FormDialog>
diff --git a/src/views/equipmentManagement/upkeep/Form/PlanModal.vue b/src/views/equipmentManagement/upkeep/Form/PlanModal.vue
index bb686dc..efa04a5 100644
--- a/src/views/equipmentManagement/upkeep/Form/PlanModal.vue
+++ b/src/views/equipmentManagement/upkeep/Form/PlanModal.vue
@@ -2,7 +2,7 @@
<FormDialog
v-model="visible"
:title="id ? '缂栬緫璁惧淇濆吇璁″垝' : '鏂板璁惧淇濆吇璁″垝'"
- width="500px"
+ width="640px"
@confirm="sendForm"
@cancel="handleCancel"
@close="handleClose"
@@ -35,25 +35,17 @@
<el-form-item label="淇濆吇椤圭洰">
<el-input
v-model="form.maintenanceLocation"
+ type="textarea"
+ :rows="3"
placeholder="璇疯緭鍏ヤ繚鍏婚」鐩�"
/>
</el-form-item>
<el-form-item label="褰曞叆浜�">
- <el-select
- v-model="form.createUser"
- placeholder="璇烽�夋嫨"
- filterable
- default-first-option
- :reserve-keyword="false"
- clearable
- >
- <el-option
- v-for="item in userList"
- :key="item.userId"
- :label="item.nickName"
- :value="item.userId"
- />
- </el-select>
+ <el-input
+ :model-value="registrantDisplayName"
+ disabled
+ placeholder="褰撳墠鐧诲綍鐢ㄦ埛"
+ />
</el-form-item>
<el-form-item v-if="id" label="淇濅慨鐘舵��">
<el-select v-model="form.status">
@@ -73,6 +65,18 @@
clearable
/>
</el-form-item>
+ <el-form-item label="闄勪欢">
+ <el-upload
+ :http-request="handlePlanFileUpload"
+ :file-list="planFileList"
+ :on-remove="handlePlanFileRemove"
+ multiple
+ list-type="picture-card"
+ >
+ <el-icon><Plus /></el-icon>
+ </el-upload>
+ <span v-if="!id" class="upload-tip">鍙厛閫夋嫨闄勪欢锛屼繚瀛樿鍒掑悗鑷姩鍏宠仈鍒版湰璁″垝</span>
+ </el-form-item>
</el-form>
</FormDialog>
</template>
@@ -84,18 +88,42 @@
editUpkeep,
getUpkeepById,
} from "@/api/equipmentManagement/upkeep";
+import {
+ listMaintenanceTaskFiles,
+ bindMaintenanceTaskFile,
+ uploadMaintenanceTaskFile,
+ delMaintenanceTaskFile,
+} from "@/api/equipmentManagement/maintenanceTaskFile";
import { ElMessage } from "element-plus";
+import { Plus } from "@element-plus/icons-vue";
import useFormData from "@/hooks/useFormData";
import { getDeviceLedger } from "@/api/equipmentManagement/ledger";
-import { onMounted } from "vue";
+import { computed, onMounted, ref } from "vue";
import dayjs from "dayjs";
-import { userListNoPage } from "@/api/system/user.js";
+import useUserStore from "@/store/modules/user.js";
+import request from "@/utils/request";
defineOptions({
name: "璁惧淇濆吇鏂板璁″垝",
});
const emits = defineEmits(["ok"]);
+
+const userStore = useUserStore();
+const javaApi = import.meta.env.VITE_APP_BASE_API;
+
+const pendingTempFiles = ref([]);
+const planFileList = ref([]);
+
+const registrantDisplayName = computed(
+ () => userStore.nickName || userStore.name || "褰撳墠鐧诲綍鐢ㄦ埛"
+);
+
+const syncCreateUserFromLogin = () => {
+ if (userStore.id != null && userStore.id !== "") {
+ form.createUser = userStore.id;
+ }
+};
const id = ref();
const visible = ref(false);
@@ -108,64 +136,178 @@
};
const { form, resetForm } = useFormData({
- deviceLedgerId: undefined, // 璁惧Id
- deviceName: undefined, // 璁惧鍚嶇О
- deviceModel: undefined, // 瑙勬牸鍨嬪彿
- maintenanceLocation: undefined, // 淇濆吇椤圭洰
- maintenancePlanTime: undefined, // 璁″垝淇濆吇鏃ユ湡
- createUser: undefined, // 褰曞叆浜�
- status: 0, //淇濅慨鐘舵��
+ deviceLedgerId: undefined,
+ deviceName: undefined,
+ deviceModel: undefined,
+ maintenanceLocation: undefined,
+ maintenancePlanTime: undefined,
+ createUser: undefined,
+ status: 0,
});
const setDeviceModel = (deviceId) => {
const option = deviceOptions.value.find((item) => item.id === deviceId);
- form.deviceModel = option.deviceModel;
+ if (option) {
+ form.deviceModel = option.deviceModel;
+ }
};
-/**
- * @desc 璁剧疆琛ㄥ崟鍐呭
- * @param data 璁惧淇℃伅
- */
+const resetAttachmentState = () => {
+ pendingTempFiles.value = [];
+ planFileList.value = [];
+};
+
+const normalizeFilePreviewUrl = (url = "") => {
+ if (!url) return "";
+ if (url.startsWith("http")) return url;
+ if (url.startsWith("/profile")) return javaApi + url;
+ return url;
+};
+
+const loadPlanFiles = async (planId) => {
+ if (!planId) return;
+ const res = await listMaintenanceTaskFiles({
+ current: 1,
+ size: 100,
+ deviceMaintenanceId: planId,
+ });
+ const records = res?.data?.records || [];
+ planFileList.value = records.map((item) => ({
+ name: item.name,
+ url: normalizeFilePreviewUrl(item.url),
+ status: "success",
+ uid: `saved-${item.id}`,
+ fileId: item.id,
+ }));
+};
+
+const uploadTempFile = (file) => {
+ const fd = new FormData();
+ fd.append("file", file);
+ fd.append("type", "16");
+ return request({
+ url: "/file/upload",
+ method: "post",
+ data: fd,
+ headers: { "Content-Type": "multipart/form-data" },
+ });
+};
+
+const handlePlanFileUpload = async (options) => {
+ const { file, onSuccess, onError } = options;
+ try {
+ if (id.value) {
+ const fd = new FormData();
+ fd.append("file", file);
+ fd.append("deviceMaintenanceId", String(id.value));
+ const res = await uploadMaintenanceTaskFile(fd);
+ if (res.code === 200) {
+ await loadPlanFiles(id.value);
+ onSuccess(res);
+ ElMessage.success("闄勪欢涓婁紶鎴愬姛");
+ } else {
+ onError(new Error(res.msg || "涓婁紶澶辫触"));
+ }
+ return;
+ }
+ const res = await uploadTempFile(file);
+ if (res.code !== 200) {
+ onError(new Error(res.msg || "涓婁紶澶辫触"));
+ return;
+ }
+ const data = res.data || {};
+ pendingTempFiles.value.push({
+ tempId: data.tempId,
+ name: data.originalName || file.name,
+ });
+ onSuccess(res);
+ planFileList.value.push({
+ name: data.originalName || file.name,
+ url: "",
+ status: "success",
+ uid: data.tempId,
+ tempId: data.tempId,
+ });
+ } catch (e) {
+ onError(e);
+ ElMessage.error("闄勪欢涓婁紶澶辫触");
+ }
+};
+
+const handlePlanFileRemove = async (file) => {
+ if (file.fileId) {
+ try {
+ await delMaintenanceTaskFile(file.fileId);
+ await loadPlanFiles(id.value);
+ } catch (e) {
+ ElMessage.error("鍒犻櫎闄勪欢澶辫触");
+ }
+ return;
+ }
+ const tempId = file.tempId || file.uid;
+ pendingTempFiles.value = pendingTempFiles.value.filter((f) => f.tempId !== tempId);
+ planFileList.value = planFileList.value.filter((f) => (f.tempId || f.uid) !== tempId);
+};
+
+const bindPendingFiles = async (planId) => {
+ if (!pendingTempFiles.value.length) return;
+ for (const item of pendingTempFiles.value) {
+ await bindMaintenanceTaskFile({
+ tempId: item.tempId,
+ name: item.name,
+ deviceMaintenanceId: planId,
+ });
+ }
+};
+
const setForm = (data) => {
form.deviceLedgerId = data.deviceLedgerId;
form.deviceName = data.deviceName;
form.deviceModel = data.deviceModel;
form.maintenanceLocation = data.maintenanceLocation;
- form.createUser = Number(data.createUser);
form.status = data.status;
+ syncCreateUserFromLogin();
form.maintenancePlanTime = dayjs(data.maintenancePlanTime).format(
"YYYY-MM-DD HH:mm:ss"
);
};
-// 鐢ㄦ埛鍒楄〃
-const userList = ref([]);
-
onMounted(() => {
loadDeviceName();
- userListNoPage().then((res) => {
- userList.value = res.data;
- });
});
const openEdit = async (editId) => {
+ resetAttachmentState();
const { data } = await getUpkeepById(editId);
id.value = editId;
visible.value = true;
await nextTick();
setForm(data);
+ await loadPlanFiles(editId);
};
const sendForm = async () => {
+ syncCreateUserFromLogin();
loading.value = true;
try {
- const { code } = id.value
- ? await editUpkeep({ id: unref(id), ...form })
- : await addUpkeep(form);
- if (code == 200) {
- ElMessage.success(`${id.value ? "缂栬緫" : "鏂板"}璁″垝鎴愬姛`);
- visible.value = false;
- emits("ok");
+ if (id.value) {
+ const { code } = await editUpkeep({ id: unref(id), ...form });
+ if (code == 200) {
+ ElMessage.success("缂栬緫璁″垝鎴愬姛");
+ visible.value = false;
+ emits("ok");
+ }
+ } else {
+ const res = await addUpkeep(form);
+ if (res.code == 200) {
+ const planId = res.data?.id;
+ if (planId) {
+ await bindPendingFiles(planId);
+ }
+ ElMessage.success("鏂板璁″垝鎴愬姛");
+ visible.value = false;
+ emits("ok");
+ }
}
} finally {
loading.value = false;
@@ -174,16 +316,21 @@
const handleCancel = () => {
resetForm();
+ resetAttachmentState();
visible.value = false;
};
const handleClose = () => {
resetForm();
+ resetAttachmentState();
visible.value = false;
};
const openModal = () => {
id.value = undefined;
+ resetForm();
+ resetAttachmentState();
+ syncCreateUserFromLogin();
visible.value = true;
};
@@ -193,4 +340,12 @@
});
</script>
-<style lang="scss" scoped></style>
+<style lang="scss" scoped>
+.upload-tip {
+ display: block;
+ font-size: 12px;
+ color: #999;
+ margin-top: 8px;
+ line-height: 1.4;
+}
+</style>
diff --git a/src/views/equipmentManagement/upkeep/Form/UpkeepDetailModal.vue b/src/views/equipmentManagement/upkeep/Form/UpkeepDetailModal.vue
new file mode 100644
index 0000000..972cb34
--- /dev/null
+++ b/src/views/equipmentManagement/upkeep/Form/UpkeepDetailModal.vue
@@ -0,0 +1,202 @@
+<template>
+ <el-dialog
+ v-model="visible"
+ title="淇濆吇璁″垝璇︽儏"
+ width="820px"
+ destroy-on-close
+ @closed="onClosed"
+ >
+ <div v-loading="loading" class="upkeep-detail">
+ <template v-if="detail">
+ <el-descriptions :column="2" border size="small">
+ <el-descriptions-item label="璁惧鍚嶇О">{{ detail.deviceName || "鈥�" }}</el-descriptions-item>
+ <el-descriptions-item label="瑙勬牸鍨嬪彿">{{ detail.deviceModel || "鈥�" }}</el-descriptions-item>
+ <el-descriptions-item label="淇濆吇椤圭洰" :span="2">
+ <div class="multiline">{{ detail.maintenanceLocation || "鈥�" }}</div>
+ </el-descriptions-item>
+ <el-descriptions-item label="淇濆吇浜�">{{ detail.maintenancePerson || "鈥�" }}</el-descriptions-item>
+ <el-descriptions-item label="璁″垝淇濆吇鏃ユ湡">{{ fmtDate(detail.maintenancePlanTime) }}</el-descriptions-item>
+ <el-descriptions-item label="褰曞叆浜�">{{ detail.createUserName || "鈥�" }}</el-descriptions-item>
+ <el-descriptions-item label="瀹為檯淇濆吇浜�">{{ detail.maintenanceActuallyName || "鈥�" }}</el-descriptions-item>
+ <el-descriptions-item label="瀹為檯淇濆吇鏃ユ湡">{{ fmtDateTime(detail.maintenanceActuallyTime) }}</el-descriptions-item>
+ <el-descriptions-item label="鐘舵��">
+ <el-tag v-if="detail.status === 2" type="danger" size="small">澶辫触</el-tag>
+ <el-tag v-else-if="detail.status === 1" type="success" size="small">瀹岀粨</el-tag>
+ <el-tag v-else-if="detail.status === 0" type="warning" size="small">寰呬繚鍏�</el-tag>
+ <span v-else>鈥�</span>
+ </el-descriptions-item>
+ <el-descriptions-item label="淇濆吇缁撴灉" :span="2">
+ <div class="multiline">{{ detail.maintenanceResult || "鈥�" }}</div>
+ </el-descriptions-item>
+ <el-descriptions-item label="褰曞叆鏃堕棿">{{ fmtDateTime(detail.createTime) }}</el-descriptions-item>
+ <el-descriptions-item label="鏇存柊鏃堕棿">{{ fmtDateTime(detail.updateTime) }}</el-descriptions-item>
+ </el-descriptions>
+
+ <div class="attach-block">
+ <div class="attach-title">闄勪欢锛坽{ fileList.length }}锛�</div>
+ <div v-if="fileList.length" class="img-grid">
+ <div v-for="file in fileList" :key="file.id" class="attach-item">
+ <el-image
+ v-if="isImageFile(file.name)"
+ :src="file.url"
+ fit="cover"
+ class="thumb"
+ :preview-src-list="imagePreviewList"
+ preview-teleported
+ />
+ <div v-else class="file-chip">
+ <el-link type="primary" :href="file.url" target="_blank">{{ file.name }}</el-link>
+ </div>
+ <div class="file-name" :title="file.name">{{ file.name }}</div>
+ </div>
+ </div>
+ <el-empty v-else description="鏆傛棤闄勪欢" :image-size="56" />
+ </div>
+ </template>
+ </div>
+ <template #footer>
+ <el-button type="primary" @click="visible = false">鍏抽棴</el-button>
+ </template>
+ </el-dialog>
+</template>
+
+<script setup>
+import { computed, ref } from "vue";
+import dayjs from "dayjs";
+import { getUpkeepById } from "@/api/equipmentManagement/upkeep";
+import { listMaintenanceTaskFiles } from "@/api/equipmentManagement/maintenanceTaskFile";
+
+defineOptions({ name: "UpkeepDetailModal" });
+
+const props = defineProps({
+ javaApi: {
+ type: String,
+ default: "",
+ },
+});
+
+const visible = ref(false);
+const loading = ref(false);
+const detail = ref(null);
+const fileList = ref([]);
+
+const apiBase = computed(() => props.javaApi || import.meta.env.VITE_APP_BASE_API || "");
+
+const imagePreviewList = computed(() =>
+ fileList.value.filter((f) => isImageFile(f.name)).map((f) => f.url)
+);
+
+const fmtDate = (v) => (v ? dayjs(v).format("YYYY-MM-DD") : "鈥�");
+const fmtDateTime = (v) => (v ? dayjs(v).format("YYYY-MM-DD HH:mm:ss") : "鈥�");
+
+const isImageFile = (name = "") => /\.(jpg|jpeg|png|gif|webp|bmp)$/i.test(name);
+
+const normalizeFileUrl = (rawUrl = "") => {
+ let fileUrl = rawUrl || "";
+ if (!fileUrl) return "";
+ if (fileUrl.startsWith("http://") || fileUrl.startsWith("https://")) return fileUrl;
+ if (fileUrl.indexOf("\\") > -1) {
+ const lowerPath = fileUrl.toLowerCase();
+ const uploadPathIndex = lowerPath.indexOf("uploadpath");
+ if (uploadPathIndex > -1) {
+ fileUrl = fileUrl.substring(uploadPathIndex).replace(/\\/g, "/");
+ } else {
+ fileUrl = fileUrl.replace(/\\/g, "/");
+ }
+ }
+ fileUrl = fileUrl.replace(/^\/?uploadPath/i, "/profile");
+ if (!fileUrl.startsWith("/")) fileUrl = "/" + fileUrl;
+ if (!fileUrl.startsWith(apiBase.value)) fileUrl = apiBase.value + fileUrl;
+ return fileUrl;
+};
+
+const loadFiles = async (id) => {
+ const res = await listMaintenanceTaskFiles({
+ current: 1,
+ size: 100,
+ deviceMaintenanceId: id,
+ });
+ const records = res?.data?.records || [];
+ fileList.value = records.map((item) => ({
+ id: item.id,
+ name: item.name,
+ url: normalizeFileUrl(item.url),
+ }));
+};
+
+const open = async (row) => {
+ if (!row?.id) return;
+ visible.value = true;
+ loading.value = true;
+ detail.value = null;
+ fileList.value = [];
+ try {
+ const { data } = await getUpkeepById(row.id);
+ detail.value = { ...row, ...data };
+ await loadFiles(row.id);
+ } finally {
+ loading.value = false;
+ }
+};
+
+const onClosed = () => {
+ detail.value = null;
+ fileList.value = [];
+};
+
+defineExpose({ open });
+</script>
+
+<style lang="scss" scoped>
+.upkeep-detail {
+ min-height: 120px;
+}
+.multiline {
+ white-space: pre-wrap;
+ word-break: break-word;
+ line-height: 1.6;
+}
+.attach-block {
+ margin-top: 20px;
+}
+.attach-title {
+ font-size: 14px;
+ font-weight: 600;
+ margin-bottom: 12px;
+ color: #303133;
+}
+.img-grid {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 12px;
+}
+.attach-item {
+ width: 100px;
+}
+.thumb {
+ width: 100px;
+ height: 100px;
+ border-radius: 4px;
+ border: 1px solid #ebeef5;
+}
+.file-chip {
+ width: 100px;
+ height: 100px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 8px;
+ border: 1px dashed #dcdfe6;
+ border-radius: 4px;
+ box-sizing: border-box;
+}
+.file-name {
+ display: block;
+ margin-top: 6px;
+ font-size: 12px;
+ color: #606266;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+</style>
diff --git a/src/views/equipmentManagement/upkeep/Form/formDia.vue b/src/views/equipmentManagement/upkeep/Form/formDia.vue
index 3ce522b..4c07007 100644
--- a/src/views/equipmentManagement/upkeep/Form/formDia.vue
+++ b/src/views/equipmentManagement/upkeep/Form/formDia.vue
@@ -35,8 +35,17 @@
<el-row>
<el-col :span="12">
<el-form-item label="褰曞叆浜�" prop="inspector">
+ <el-input
+ :model-value="registrantDisplayName"
+ disabled
+ placeholder="褰撳墠鐧诲綍鐢ㄦ埛"
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="淇濆吇浜�" prop="maintenancePerson">
<el-select
- v-model="form.inspector"
+ v-model="form.maintenancePerson"
filterable
default-first-option
:reserve-keyword="false"
@@ -47,11 +56,13 @@
v-for="item in userList"
:label="item.nickName"
:value="item.userId"
- :key="item.userId"
+ :key="'mp-' + item.userId"
/>
</el-select>
</el-form-item>
</el-col>
+ </el-row>
+ <el-row>
<el-col :span="12">
<el-form-item label="鐧昏鏃堕棿" prop="registrationDate">
<el-date-picker
@@ -123,7 +134,19 @@
</el-col>
</el-row>
<el-row>
- <el-col :span="12">
+ <el-col :span="24">
+ <el-form-item label="淇濆吇椤圭洰" prop="maintenanceItems">
+ <el-input
+ v-model="form.maintenanceItems"
+ type="textarea"
+ :rows="3"
+ placeholder="璇疯緭鍏ヤ繚鍏婚」鐩�"
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row>
+ <el-col :span="24">
<el-form-item label="澶囨敞" prop="remarks">
<el-input v-model="form.remarks" placeholder="璇疯緭鍏ュ娉�" type="textarea" />
</el-form-item>
@@ -135,7 +158,7 @@
<script setup>
import FormDialog from "@/components/Dialog/FormDialog.vue";
-import { reactive, ref, getCurrentInstance, toRefs } from "vue";
+import { reactive, ref, computed, getCurrentInstance, toRefs } from "vue";
import {userListNoPageByTenantId} from "@/api/system/user.js";
import { getDeviceLedger } from "@/api/equipmentManagement/ledger";
import { deviceMaintenanceTaskAdd, deviceMaintenanceTaskEdit } from "@/api/equipmentManagement/upkeep";
@@ -152,8 +175,10 @@
form: {
taskId: undefined,
taskName: undefined,
- // 褰曞叆浜猴細鍗曢�変竴涓敤鎴� id
+ // 褰曞叆浜恒�佷繚鍏讳汉锛氱敤鎴� id
inspector: undefined,
+ maintenancePerson: undefined,
+ maintenanceItems: '',
remarks: '',
frequencyType: '',
frequencyDetail: '',
@@ -165,6 +190,8 @@
rules: {
taskId: [{ required: true, message: "璇烽�夋嫨璁惧", trigger: "change" },],
inspector: [{ required: true, message: "璇烽�夋嫨褰曞叆浜�", trigger: "blur" },],
+ maintenancePerson: [{ required: true, message: "璇烽�夋嫨淇濆吇浜�", trigger: "change" }],
+ maintenanceItems: [{ required: true, message: "璇疯緭鍏ヤ繚鍏婚」鐩�", trigger: "blur" }],
registrationDate: [{ required: true, message: "璇烽�夋嫨鐧昏鏃堕棿", trigger: "change" }],
frequencyDetail: [{
validator: (rule, value, callback) => {
@@ -192,6 +219,16 @@
})
const { form, rules } = toRefs(data)
const userList = ref([])
+
+const registrantDisplayName = computed(
+ () => userStore.nickName || userStore.name || "褰撳墠鐧诲綍鐢ㄦ埛"
+)
+
+const syncRegistrantFromLogin = () => {
+ if (userStore.id != null && userStore.id !== "") {
+ form.value.inspector = userStore.id
+ }
+}
const loadDeviceName = async () => {
const { data } = await getDeviceLedger();
@@ -226,21 +263,17 @@
if (type === 'edit' && row) {
form.value = { ...row }
- // 缂栬緫鏃剁敤鎺ュ彛杩斿洖鐨� registrantId 鍥炴樉褰曞叆浜�
- if (row.registrantId) {
- form.value.inspector = row.registrantId
+ if (row.maintenancePersonId) {
+ form.value.maintenancePerson = row.maintenancePersonId
}
-
- // 濡傛灉鏈夎澶嘔D锛岃嚜鍔ㄨ缃澶囦俊鎭�
if (form.value.taskId) {
setDeviceModel(form.value.taskId);
}
} else if (type === 'add') {
- // 鏂板鏃惰缃櫥璁版棩鏈熶负褰撳ぉ
form.value.registrationDate = getCurrentDate();
- // 鏂板鏃惰缃綍鍏ヤ汉涓哄綋鍓嶇櫥褰曡处鎴�
- form.value.inspector = userStore.id;
+ form.value.maintenancePerson = userStore.id;
}
+ syncRegistrantFromLogin()
}
// 鍏抽棴瀵硅瘽妗�
@@ -260,7 +293,8 @@
taskId: undefined,
taskName: undefined,
inspector: undefined,
- inspector: undefined,
+ maintenancePerson: undefined,
+ maintenanceItems: '',
remarks: '',
frequencyType: '',
frequencyDetail: '',
@@ -273,19 +307,21 @@
// 鎻愪氦琛ㄥ崟
const submitForm = () => {
+ syncRegistrantFromLogin()
proxy.$refs["formRef"].validate(async valid => {
if (valid) {
try {
const payload = { ...form.value }
- // 涓嶅啀鍚戝悗绔紶淇濆吇浜哄瓧娈碉紝浠呬娇鐢ㄦ帴鍙h姹傜殑 registrant / registrantId
- // 鏍规嵁閫夋嫨鐨�"褰曞叆浜�"璁剧疆 registrant / registrantId
- if (payload.inspector) {
- const selectedUser = userList.value.find(
- (u) => String(u.userId) === String(payload.inspector)
+ payload.registrantId = userStore.id
+ payload.registrant = userStore.nickName || userStore.name
+ const maintenancePersonUserId = form.value.maintenancePerson
+ if (maintenancePersonUserId) {
+ const maintainer = userList.value.find(
+ (u) => String(u.userId) === String(maintenancePersonUserId)
)
- if (selectedUser) {
- payload.registrantId = selectedUser.userId
- payload.registrant = selectedUser.nickName
+ if (maintainer) {
+ payload.maintenancePersonId = maintainer.userId
+ payload.maintenancePerson = maintainer.nickName
}
}
delete payload.inspector
diff --git a/src/views/equipmentManagement/upkeep/index.vue b/src/views/equipmentManagement/upkeep/index.vue
index 4cf6fc0..9820910 100644
--- a/src/views/equipmentManagement/upkeep/index.vue
+++ b/src/views/equipmentManagement/upkeep/index.vue
@@ -162,23 +162,19 @@
@selection-change="handleSelectionChange"
@pagination="changePage"
>
- <template #maintenanceResultRef="{ row }">
- <div>{{ row.maintenanceResult || '-' }}</div>
- </template>
<template #statusRef="{ row }">
<el-tag v-if="row.status === 2" type="danger">澶辫触</el-tag>
<el-tag v-if="row.status === 1" type="success">瀹岀粨</el-tag>
<el-tag v-if="row.status === 0" type="warning">寰呬繚鍏�</el-tag>
</template>
<template #operation="{ row }">
- <!-- 杩欎釜鍔熻兘璺熸柊澧炰繚鍏诲姛鑳戒竴妯′竴鏍凤紝鏈夊暐鎰忎箟锛� -->
- <!-- <el-button
- type="primary"
- text
- @click="addMaintain(row)"
+ <el-button
+ type="primary"
+ link
+ @click="openDetail(row)"
>
- 鏂板淇濆吇
- </el-button> -->
+ 璇︽儏
+ </el-button>
<el-button
type="primary"
link
@@ -218,15 +214,20 @@
<PlanModal ref="planModalRef" @ok="getTableData" />
<MaintenanceModal ref="maintainModalRef" @ok="getTableData" />
<FormDia ref="formDiaRef" @closeDia="getScheduledTableData" />
- <FileListDialog
+ <UpkeepDetailModal ref="upkeepDetailModalRef" :java-api="javaApi" />
+ <FileListDialog
ref="fileListDialogRef"
v-model="fileDialogVisible"
- :show-upload-button="true"
- :show-delete-button="true"
+ :title="currentRecordFinished ? '闄勪欢锛堝凡瀹岀粨锛屼粎鍙煡鐪嬶級' : '闄勪欢'"
+ :show-upload-button="!currentRecordFinished"
+ :show-delete-button="!currentRecordFinished"
:delete-method="handleAttachmentDelete"
:name-column-label="'闄勪欢鍚嶇О'"
- :rulesRegulationsManagementId="currentMaintenanceTaskId"
- @upload="handleAttachmentUpload" />
+ :upload-url="maintenanceFileUploadUrl"
+ :upload-data="maintenanceFileUploadData"
+ :upload-direct-save="true"
+ @upload="refreshFileList"
+ />
</div>
</template>
@@ -236,6 +237,7 @@
import { ElMessage, ElMessageBox } from 'element-plus'
import PlanModal from './Form/PlanModal.vue'
import MaintenanceModal from './Form/MaintenanceModal.vue'
+import UpkeepDetailModal from './Form/UpkeepDetailModal.vue'
import FormDia from './Form/formDia.vue'
import FileListDialog from '@/components/Dialog/FileListDialog.vue'
import {
@@ -246,7 +248,6 @@
} from '@/api/equipmentManagement/upkeep'
import {
listMaintenanceTaskFiles,
- addMaintenanceTaskFile,
delMaintenanceTaskFile,
} from '@/api/equipmentManagement/maintenanceTaskFile'
import dayjs from 'dayjs'
@@ -260,12 +261,40 @@
const planModalRef = ref()
// 淇濆吇寮圭獥鎺у埗鍣�
const maintainModalRef = ref()
+const upkeepDetailModalRef = ref()
// 瀹氭椂浠诲姟寮圭獥鎺у埗鍣�
const formDiaRef = ref()
// 闄勪欢寮圭獥
const fileListDialogRef = ref(null)
const fileDialogVisible = ref(false)
const currentMaintenanceTaskId = ref(null)
+/** 褰撳墠闄勪欢鎵�灞炶褰曟槸鍚﹀凡瀹岀粨锛坰tatus=1锛� */
+const currentRecordFinished = ref(false)
+
+const javaApi = import.meta.env.VITE_APP_BASE_API
+const maintenanceFileUploadUrl = `${javaApi}/maintenanceTaskFile/upload`
+const maintenanceFileUploadData = computed(() => ({
+ deviceMaintenanceId: currentMaintenanceTaskId.value,
+}))
+
+const normalizeMaintenanceFileUrl = (rawUrl = "") => {
+ let fileUrl = rawUrl || ""
+ if (!fileUrl) return ""
+ if (fileUrl.startsWith("http://") || fileUrl.startsWith("https://")) return fileUrl
+ if (fileUrl.indexOf("\\") > -1) {
+ const lowerPath = fileUrl.toLowerCase()
+ const uploadPathIndex = lowerPath.indexOf("uploadpath")
+ if (uploadPathIndex > -1) {
+ fileUrl = fileUrl.substring(uploadPathIndex).replace(/\\/g, "/")
+ } else {
+ fileUrl = fileUrl.replace(/\\/g, "/")
+ }
+ }
+ fileUrl = fileUrl.replace(/^\/?uploadPath/i, "/profile")
+ if (!fileUrl.startsWith("/")) fileUrl = "/" + fileUrl
+ if (!fileUrl.startsWith(javaApi)) fileUrl = javaApi + fileUrl
+ return fileUrl
+}
// 浠诲姟璁板綍tab锛堝師璁惧淇濆吇椤甸潰锛夌浉鍏冲彉閲�
const filters = reactive({
@@ -338,6 +367,13 @@
}
},
{ prop: "registrant", label: "鐧昏浜�", minWidth: 100 },
+ { prop: "maintenancePerson", label: "淇濆吇浜�", minWidth: 100 },
+ {
+ prop: "maintenanceItems",
+ label: "淇濆吇椤圭洰",
+ minWidth: 180,
+ showOverflowTooltip: true,
+ },
{ prop: "registrationDate", label: "鐧昏鏃ユ湡", minWidth: 100 },
{
fixed: "right",
@@ -365,6 +401,12 @@
label: "淇濆吇椤圭洰",
align: "center",
prop: "maintenanceLocation",
+ showOverflowTooltip: true,
+ },
+ {
+ label: "淇濆吇浜�",
+ align: "center",
+ prop: "maintenancePerson",
},
{
label: "璁″垝淇濆吇鏃ユ湡",
@@ -400,8 +442,8 @@
label: "淇濆吇缁撴灉",
align: "center",
prop: "maintenanceResult",
- dataType: "slot",
- slot: "maintenanceResultRef",
+ minWidth: 200,
+ showOverflowTooltip: true,
},
{
label: "鐘舵��",
@@ -416,7 +458,7 @@
dataType: "slot",
slot: "operation",
align: "center",
- width: "350px",
+ width: "400px",
},
])
@@ -610,14 +652,13 @@
current: 1,
size: 100,
deviceMaintenanceId,
- rulesRegulationsManagementId:deviceMaintenanceId
}
const res = await listMaintenanceTaskFiles(params)
const records = res?.data?.records || []
const mapped = records.map(item => ({
id: item.id,
name: item.fileName || item.name,
- url: item.fileUrl || item.url,
+ url: normalizeMaintenanceFileUrl(item.fileUrl || item.url),
raw: item,
}))
fileListDialogRef.value?.setList(mapped)
@@ -626,9 +667,14 @@
}
}
+const openDetail = (row) => {
+ upkeepDetailModalRef.value?.open(row)
+}
+
// 鎵撳紑闄勪欢寮圭獥
const openFileDialog = async (row) => {
currentMaintenanceTaskId.value = row.id
+ currentRecordFinished.value = row.status === 1
fileDialogVisible.value = true
await fetchMaintenanceTaskFiles(row.id)
}
@@ -639,25 +685,12 @@
await fetchMaintenanceTaskFiles(currentMaintenanceTaskId.value)
}
-// 涓婁紶闄勪欢
-const handleAttachmentUpload = async (filePayload) => {
- if (!currentMaintenanceTaskId.value) return
- try {
- const payload = {
- name: filePayload?.fileName || filePayload?.name,
- url: filePayload?.fileUrl || filePayload?.url,
- deviceMaintenanceId: currentMaintenanceTaskId.value,
- }
- await addMaintenanceTaskFile(payload)
- ElMessage.success('鏂囦欢涓婁紶鎴愬姛')
- await refreshFileList()
- } catch (error) {
- ElMessage.error('鏂囦欢涓婁紶澶辫触')
- }
-}
-
-// 鍒犻櫎闄勪欢
+// 鍒犻櫎闄勪欢锛堝凡瀹岀粨涓嶅彲鍒狅級
const handleAttachmentDelete = async (row) => {
+ if (currentRecordFinished.value) {
+ ElMessage.warning('璇ヤ繚鍏诲凡瀹岀粨锛屼笉鍙垹闄ら檮浠�')
+ return false
+ }
if (!row?.id) return false
try {
await ElMessageBox.confirm('纭鍒犻櫎璇ラ檮浠讹紵', '鎻愮ず', { type: 'warning' })
--
Gitblit v1.9.3