From 51081f3acbeef7e5358e20a653c38b0ed3afbe23 Mon Sep 17 00:00:00 2001
From: gongchunyi <deslre0381@gmail.com>
Date: 星期五, 15 五月 2026 19:39:19 +0800
Subject: [PATCH] feat: 设备维修新增报修人、验收人、维修人
---
src/views/equipmentManagement/repair/index.vue | 309 ++++++++++++++++++++++++++++++++++++++-------------
1 files changed, 228 insertions(+), 81 deletions(-)
diff --git a/src/views/equipmentManagement/repair/index.vue b/src/views/equipmentManagement/repair/index.vue
index e14ab37..3f48df5 100644
--- a/src/views/equipmentManagement/repair/index.vue
+++ b/src/views/equipmentManagement/repair/index.vue
@@ -98,74 +98,109 @@
@pagination="changePage"
>
<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>
+ <el-tag v-else-if="row.status === 3" type="info">寰呴獙鏀�</el-tag>
+ <el-tag v-else-if="row.status === 1" type="success">瀹屾垚</el-tag>
+ <el-tag v-else-if="row.status === 2" type="danger">缁翠慨澶辫触</el-tag>
</template>
<template #operation="{ row }">
- <el-button
- type="primary"
- link
- :disabled="row.status === 1"
- @click="editRepair(row.id)"
- >
+ <el-button type="info" link @click="openRepairDetail(row.id)">
+ 璇︽儏
+ </el-button>
+ <el-button type="primary" link :disabled="!canEdit(row)" @click="editRepair(row.id)">
缂栬緫
</el-button>
- <el-button
- type="info"
- link
- :disabled="row.status === 1"
- @click="openAttachment(row)"
- >
- 闄勪欢
- </el-button>
- <el-button
- type="success"
- link
- :disabled="row.status === 1"
- @click="addMaintain(row)"
- >
+ <el-button type="success" link :disabled="!canMaintain(row)" @click="addMaintain(row)">
缁翠慨
</el-button>
- <el-button
- type="danger"
- link
- :disabled="row.status === 1"
- @click="delRepairByIds(row.id)"
- >
+ <el-button type="warning" link :disabled="!canAccept(row)" @click="openAcceptance(row)">
+ 楠屾敹
+ </el-button>
+ <el-button type="danger" link :disabled="!canDelete(row)" @click="delRepairByIds(row.id)">
鍒犻櫎
+ </el-button>
+ <el-button type="primary" link @click="openAttachment(row)">
+ 闄勪欢
</el-button>
</template>
</PIMTable>
</div>
<RepairModal ref="repairModalRef" @ok="getTableData"/>
<MaintainModal ref="maintainModalRef" @ok="getTableData"/>
+ <AcceptanceModal ref="acceptanceModalRef" @ok="getTableData"/>
+ <RepairDetailModal ref="repairDetailModalRef" :java-api="javaApi" />
- <el-dialog v-model="attachment.visible" title="闄勪欢" width="860px" @closed="onAttachmentClosed">
+ <el-dialog v-model="attachment.visible" title="闄勪欢" width="900px" @closed="onAttachmentClosed">
<div v-loading="attachment.loading" class="attachment-wrap">
- <div class="attachment-actions">
- <el-upload
- v-model:file-list="attachment.fileList"
- :action="upload.url"
- multiple
- ref="attachmentFileUpload"
- auto-upload
- :headers="upload.headers"
- :data="{ deviceRepairId: attachment.deviceRepairId }"
- :before-upload="handleAttachmentBeforeUpload"
- :on-error="handleAttachmentUploadError"
- :on-success="handleAttachmentUploadSuccess"
- :on-preview="handleAttachmentPreview"
- :on-remove="handleAttachmentRemove"
- list-type="picture-card"
- :limit="9"
- accept="image/png,image/jpeg,image/jpg"
- >
- +
- </el-upload>
+ <p v-if="attachmentReadOnly" class="attachment-readonly-tip">
+ 宸插紑濮嬬淮淇紝姝ゅ浠呭彲鏌ョ湅锛涜澶囬棶棰樺浘璇峰湪鎶ヤ慨銆屽緟缁翠慨銆嶆椂浜庛�岀紪杈戙�嶄腑缁存姢锛涚淮淇畬鎴愬浘璇峰湪銆岀淮淇�嶆椂涓婁紶銆�
+ </p>
+ <div class="attachment-section">
+ <div class="attachment-section-title">璁惧闂鍥剧墖</div>
+ <template v-if="attachmentReadOnly">
+ <div v-if="attachment.problemFileList.length" class="attachment-readonly-grid">
+ <div
+ v-for="f in attachment.problemFileList"
+ :key="f.id"
+ class="attachment-readonly-item"
+ @click="handleAttachmentPreview(f)"
+ >
+ <el-image :src="f.url" fit="cover" class="attachment-readonly-img" />
+ </div>
+ </div>
+ <el-empty
+ v-else
+ description="鏆傛棤璁惧闂鍥剧墖"
+ :image-size="60"
+ />
+ </template>
+ <template v-else>
+ <el-upload
+ v-model:file-list="attachment.problemFileList"
+ :action="upload.url"
+ multiple
+ auto-upload
+ :headers="upload.headers"
+ :data="uploadDataProblem"
+ :before-upload="handleAttachmentBeforeUpload"
+ :on-error="handleAttachmentUploadError"
+ :on-success="() => handleAttachmentUploadSuccess('problem')"
+ :on-preview="handleAttachmentPreview"
+ :on-remove="(file) => handleAttachmentRemove(file, 'problem')"
+ list-type="picture-card"
+ :limit="9"
+ accept="image/png,image/jpeg,image/jpg"
+ >
+ +
+ </el-upload>
+ <el-empty
+ v-if="!attachment.loading && attachment.problemFileList.length === 0"
+ description="鏆傛棤璁惧闂鍥剧墖"
+ :image-size="60"
+ />
+ </template>
</div>
-
- <el-empty v-if="!attachment.loading && attachment.files.length === 0" description="鏆傛棤闄勪欢" />
+ <div class="attachment-section">
+ <div class="attachment-section-title">缁翠慨瀹屾垚鍥剧墖</div>
+ <p v-if="!attachmentReadOnly" class="attachment-readonly-tip" style="margin-top: 0">
+ 缁翠慨瀹屾垚鍥捐鍦ㄥ垪琛ㄣ�岀淮淇�嶆搷浣滀腑涓婁紶锛屾澶勪粎鏌ョ湅銆�
+ </p>
+ <div v-if="attachment.maintainFileList.length" class="attachment-readonly-grid">
+ <div
+ v-for="f in attachment.maintainFileList"
+ :key="f.id"
+ class="attachment-readonly-item"
+ @click="handleAttachmentPreview(f)"
+ >
+ <el-image :src="f.url" fit="cover" class="attachment-readonly-img" />
+ </div>
+ </div>
+ <el-empty
+ v-else
+ description="鏆傛棤缁翠慨瀹屾垚鍥剧墖"
+ :image-size="60"
+ />
+ </div>
</div>
<template #footer>
<el-button @click="attachment.visible = false">鍏抽棴</el-button>
@@ -203,7 +238,15 @@
import {ElMessageBox, ElMessage} from "element-plus";
import dayjs from "dayjs";
import MaintainModal from "./Modal/MaintainModal.vue";
+import AcceptanceModal from "./Modal/AcceptanceModal.vue";
+import RepairDetailModal from "./Modal/RepairDetailModal.vue";
import { getToken } from "@/utils/auth";
+import useUserStore from "@/store/modules/user";
+import {
+ REPAIR_FILE_TYPE_PROBLEM,
+ isProblemRepairFile,
+ isMaintainRepairFile,
+} from "@/api/equipmentManagement/repairFileType.js";
defineOptions({
name: "璁惧鎶ヤ慨",
@@ -215,6 +258,9 @@
// 妯℃�佹瀹炰緥
const repairModalRef = ref();
const maintainModalRef = ref();
+const acceptanceModalRef = ref();
+const repairDetailModalRef = ref();
+const userStore = useUserStore();
// 琛ㄦ牸澶氶�夋閫変腑椤�
const multipleList = ref([]);
@@ -223,10 +269,30 @@
visible: false,
loading: false,
deviceRepairId: undefined,
+ /** 鎶ヤ慨鍗曠姸鎬侊細闈炲緟缁翠慨(0)鏃堕檮浠跺脊绐楀彧璇� */
+ repairStatus: undefined,
files: [],
- fileList: [],
+ problemFileList: [],
+ maintainFileList: [],
previewVisible: false,
previewUrl: "",
+});
+
+/** 宸插紑濮嬬淮淇悗锛氬垪琛ㄣ�岄檮浠躲�嶄粎鏌ョ湅锛屼笉鍙鍒� */
+const attachmentReadOnly = computed(
+ () => attachment.repairStatus != null && attachment.repairStatus !== 0
+);
+
+const uploadDataProblem = computed(() => ({
+ deviceRepairId: attachment.deviceRepairId,
+ fileType: REPAIR_FILE_TYPE_PROBLEM,
+}));
+
+const toUploadFileItem = (item) => ({
+ id: item.id,
+ name: item.name,
+ url: getFileAccessUrl(item),
+ fileType: item.type,
});
const getFileAccessUrl = (file = {}) => {
@@ -312,6 +378,11 @@
prop: "repairName",
},
{
+ label: "楠屾敹浜�",
+ align: "center",
+ prop: "acceptanceName",
+ },
+ {
label: "鏁呴殰鐜拌薄",
align: "center",
prop: "remark",
@@ -345,10 +416,27 @@
dataType: "slot",
slot: "operation",
align: "center",
- width: "300px",
+ width: "420px",
},
]
);
+
+const isCurrentUser = (name) => !!name && name === userStore.nickName;
+
+const canEdit = (row) => row.status === 0;
+/** 浠呮姤淇椂鎸囧畾鐨勭淮淇汉鍙淮淇� */
+const canMaintain = (row) => {
+ if (row.status !== 0) return false;
+ if (!row.maintenanceName) return false;
+ return isCurrentUser(row.maintenanceName);
+};
+const canDelete = (row) => row.status === 0;
+/** 浠呮姤淇椂鎸囧畾鐨勯獙鏀朵汉鍙獙鏀� */
+const canAccept = (row) => {
+ if (row.status !== 3) return false;
+ if (!row.acceptanceName) return false;
+ return isCurrentUser(row.acceptanceName);
+};
// type === 1 缁翠慨 2鎶ヤ慨闂�
const handleDateChange = (value, type) => {
@@ -371,10 +459,14 @@
multipleList.value = selectionList;
};
-// 妫�鏌ラ�変腑鐨勮褰曚腑鏄惁鏈夊畬缁撶姸鎬佺殑
+// 鎵归噺鍒犻櫎锛氫粎鍏佽寰呯淮淇�
const hasFinishedStatus = computed(() => {
- return multipleList.value.some(item => item.status === 1)
-})
+ return multipleList.value.some((item) => item.status !== 0);
+});
+
+const openRepairDetail = (id) => {
+ repairDetailModalRef.value?.open(id);
+};
// 鏂板鎶ヤ慨
const addRepair = () => {
@@ -386,9 +478,22 @@
repairModalRef.value.openEdit(id);
};
-// 鏂板缁翠慨
+// 缁翠慨锛堜粎鎸囧畾缁翠慨浜猴級
const addMaintain = (row) => {
+ if (!canMaintain(row)) {
+ ElMessage.warning("浠呮寚瀹氱殑缁翠慨浜哄彲杩涜缁翠慨");
+ return;
+ }
maintainModalRef.value.open(row.id, row);
+};
+
+// 楠屾敹锛堜粎鎶ヤ慨鏃舵寚瀹氱殑楠屾敹浜恒�佷笖寰呴獙鏀剁姸鎬佸彲鐐癸級
+const openAcceptance = (row) => {
+ if (!canAccept(row)) {
+ ElMessage.warning("浠呮寚瀹氱殑楠屾敹浜哄彲杩涜楠屾敹");
+ return;
+ }
+ acceptanceModalRef.value.open(row.id, row);
};
const changePage = ({page, limit}) => {
@@ -401,13 +506,13 @@
const delRepairByIds = async (ids) => {
// 妫�鏌ユ槸鍚︽湁瀹岀粨鐘舵�佺殑璁板綍
const idsArray = Array.isArray(ids) ? ids : [ids];
- const hasFinished = idsArray.some(id => {
- const record = dataList.value.find(item => item.id === id);
- return record && record.status === 1;
+ const cannotDelete = idsArray.some((id) => {
+ const record = dataList.value.find((item) => item.id === id);
+ return record && record.status !== 0;
});
- if (hasFinished) {
- ElMessage.warning('涓嶈兘鍒犻櫎鐘舵�佷负瀹岀粨鐨勮褰�');
+ if (cannotDelete) {
+ ElMessage.warning("浠呭緟缁翠慨鐘舵�佸彲鍒犻櫎");
return;
}
@@ -440,7 +545,9 @@
};
const openAttachment = async (row) => {
- attachment.fileList = [];
+ attachment.problemFileList = [];
+ attachment.maintainFileList = [];
+ attachment.repairStatus = row?.status;
attachment.visible = true;
attachment.deviceRepairId = row?.id;
await refreshAttachmentList();
@@ -452,11 +559,12 @@
try {
const res = await getRepairFileList(attachment.deviceRepairId);
attachment.files = Array.isArray(res?.data) ? res.data : [];
- attachment.fileList = attachment.files.map((item) => ({
- id: item.id,
- name: item.name,
- url: getFileAccessUrl(item),
- }));
+ attachment.problemFileList = attachment.files
+ .filter((item) => isProblemRepairFile(item.type))
+ .map(toUploadFileItem);
+ attachment.maintainFileList = attachment.files
+ .filter((item) => isMaintainRepairFile(item.type))
+ .map(toUploadFileItem);
} finally {
attachment.loading = false;
}
@@ -465,13 +573,18 @@
const onAttachmentClosed = () => {
attachment.loading = false;
attachment.deviceRepairId = undefined;
+ attachment.repairStatus = undefined;
attachment.files = [];
- attachment.fileList = [];
+ attachment.problemFileList = [];
+ attachment.maintainFileList = [];
attachment.previewVisible = false;
attachment.previewUrl = "";
};
const handleAttachmentBeforeUpload = (file) => {
+ if (attachmentReadOnly.value) {
+ return false;
+ }
const isImage = ["image/png", "image/jpeg", "image/jpg"].includes(file.type);
if (!isImage) {
ElMessage.error("鍙兘涓婁紶 png/jpg/jpeg 鍥剧墖");
@@ -480,11 +593,9 @@
return true;
};
-const handleAttachmentUploadSuccess = async (res) => {
- if (res?.code === 200) {
- ElMessage.success("涓婁紶鎴愬姛");
- await refreshAttachmentList();
- }
+const handleAttachmentUploadSuccess = async () => {
+ ElMessage.success("涓婁紶鎴愬姛");
+ await refreshAttachmentList();
};
const handleAttachmentUploadError = () => {
@@ -501,15 +612,19 @@
attachment.previewVisible = true;
};
-const handleAttachmentRemove = async (file) => {
- // 浠呯Щ闄ゅ墠绔湭鍏ュ簱鏂囦欢鏃讹紝涓嶈皟鐢ㄥ垹闄ゆ帴鍙�
+const handleAttachmentRemove = async (file, category) => {
+ if (attachmentReadOnly.value) {
+ return false;
+ }
const matched = attachment.files.find((item) => item.id === file?.id)
|| attachment.files.find((item) => item.name === file?.name);
if (!matched) return;
+ const expectProblem = category === "problem";
+ if (expectProblem && !isProblemRepairFile(matched.type)) return;
+ if (!expectProblem && !isMaintainRepairFile(matched.type)) return;
try {
await confirmDeleteAttachment(matched);
} finally {
- // 鍙栨秷鍒犻櫎鏃讹紝el-upload 宸插厛绉婚櫎锛屽埛鏂颁竴娆′繚鎸佷笌鍚庣涓�鑷�
await refreshAttachmentList();
}
};
@@ -548,11 +663,43 @@
min-height: 240px;
}
-.attachment-actions {
- display: flex;
- align-items: center;
- justify-content: space-between;
+.attachment-section {
+ margin-bottom: 20px;
+}
+.attachment-section-title {
+ font-size: 14px;
+ font-weight: 600;
+ color: #303133;
margin-bottom: 12px;
+ padding-left: 8px;
+ border-left: 3px solid var(--el-color-primary);
+}
+
+.attachment-readonly-tip {
+ font-size: 13px;
+ color: var(--el-text-color-secondary);
+ margin-bottom: 16px;
+ line-height: 1.5;
+}
+
+.attachment-readonly-grid {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 10px;
+}
+
+.attachment-readonly-item {
+ width: 100px;
+ height: 100px;
+ border-radius: 6px;
+ overflow: hidden;
+ cursor: pointer;
+ border: 1px solid var(--el-border-color);
+}
+
+.attachment-readonly-img {
+ width: 100%;
+ height: 100%;
}
.attachment-preview-wrap {
--
Gitblit v1.9.3