|
|
@@ -30,7 +30,7 @@
|
|
|
</el-select>
|
|
|
</el-form-item>
|
|
|
<el-form-item label="维护状态">
|
|
|
- <el-select v-model="queryParams.inspectionStatus" placeholder="全部状态" clearable style="width: 200px" @change="handleQuery">
|
|
|
+ <el-select v-model="queryParams.maintenanceStatus" placeholder="全部状态" clearable style="width: 200px" @change="handleQuery">
|
|
|
<el-option label="全部状态" value="" />
|
|
|
<el-option
|
|
|
v-for="d in maintenanceStatusOptions"
|
|
|
@@ -74,6 +74,9 @@
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
<el-table-column label="安装位置" align="center" prop="location" :show-overflow-tooltip="true" min-width="160" />
|
|
|
+ <el-table-column label="下次维护日期" align="center" prop="nextMaintenanceDate" width="130">
|
|
|
+ <template #default="{ row }">{{ row.nextMaintenanceDate ? String(row.nextMaintenanceDate).substring(0, 10) : '—' }}</template>
|
|
|
+ </el-table-column>
|
|
|
<el-table-column label="维护开始时间" align="center" width="170">
|
|
|
<template #default="{ row }">{{ formatMaintenanceTime(row, 'start') }}</template>
|
|
|
</el-table-column>
|
|
|
@@ -253,6 +256,54 @@
|
|
|
show-word-limit
|
|
|
/>
|
|
|
</el-form-item>
|
|
|
+ <el-form-item label="维护结果">
|
|
|
+ <el-input
|
|
|
+ v-model="maintainForm.maintenanceResult"
|
|
|
+ type="textarea"
|
|
|
+ :rows="2"
|
|
|
+ placeholder="请输入维护结果(选填)"
|
|
|
+ maxlength="500"
|
|
|
+ show-word-limit
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ <!-- ④ 维护完成时必须录入下一次维护时间 -->
|
|
|
+ <el-form-item
|
|
|
+ v-if="maintainForm.maintenanceStatus === '已维护'"
|
|
|
+ label="下次维护时间"
|
|
|
+ prop="nextMaintenanceDate"
|
|
|
+ >
|
|
|
+ <el-date-picker
|
|
|
+ v-model="maintainForm.nextMaintenanceDate"
|
|
|
+ type="date"
|
|
|
+ placeholder="请选择下次维护时间(必填)"
|
|
|
+ value-format="YYYY-MM-DD"
|
|
|
+ format="YYYY-MM-DD"
|
|
|
+ style="width: 100%"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ <!-- 维护照片上传(可选项) -->
|
|
|
+ <el-form-item label="维护照片">
|
|
|
+ <div class="upload-row">
|
|
|
+ <el-button type="primary" plain @click="triggerMaintainUpload">选择文件</el-button>
|
|
|
+ <span class="upload-tip">{{ maintainPreviewPhotos.length > 0 ? `已选择 ${maintainPreviewPhotos.length} 个文件` : '未选择任何文件' }}</span>
|
|
|
+ <el-button v-if="maintainPreviewPhotos.length > 0" link type="danger" style="margin-left: 8px" @click="clearMaintainPhotos">清空</el-button>
|
|
|
+ </div>
|
|
|
+ <input
|
|
|
+ ref="maintainPhotoInputRef"
|
|
|
+ type="file"
|
|
|
+ multiple
|
|
|
+ accept=".jpg,.jpeg,.png"
|
|
|
+ style="display: none"
|
|
|
+ @change="onMaintainPhotoInputChange"
|
|
|
+ />
|
|
|
+ <div v-if="maintainPreviewPhotos.length > 0" class="photo-preview-list">
|
|
|
+ <div v-for="(url, idx) in maintainPreviewPhotos" :key="idx" class="photo-thumb">
|
|
|
+ <el-image :src="url" :preview-src-list="maintainPreviewPhotos" :initial-index="idx" fit="cover" />
|
|
|
+ <el-icon class="photo-remove" @click="removeMaintainPhoto(idx)"><CircleCloseFilled /></el-icon>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="el-upload__tip">支持 JPG、PNG 格式</div>
|
|
|
+ </el-form-item>
|
|
|
</el-form>
|
|
|
<template #footer>
|
|
|
<div class="dialog-footer">
|
|
|
@@ -338,7 +389,10 @@ import {
|
|
|
} from '@/api/risk/specialEquipment';
|
|
|
import {
|
|
|
listEquipmentMaintenance,
|
|
|
- addEquipmentMaintenance
|
|
|
+ addEquipmentMaintenance,
|
|
|
+ updateEquipmentMaintenance,
|
|
|
+ getLatestInProgressMaintenance,
|
|
|
+ listEquipmentMaintenanceByEquipment
|
|
|
} from '@/api/risk/equipmentMaintenance';
|
|
|
import { uploadFile } from '@/api/risk/file';
|
|
|
import { getDicts } from '@/api/system/dict/data';
|
|
|
@@ -365,6 +419,10 @@ const equipmentPhotoList = ref<any[]>([]);
|
|
|
const equipmentPhotoPreview = ref<string[]>([]);
|
|
|
const equipmentPhotoInputRef = ref<HTMLInputElement>();
|
|
|
|
|
|
+// 维护照片队列(自管文件)
|
|
|
+const maintainPreviewPhotos = ref<string[]>([]);
|
|
|
+const maintainPhotoInputRef = ref<HTMLInputElement>();
|
|
|
+
|
|
|
const queryFormRef = ref<FormInstance>();
|
|
|
const formRef = ref<FormInstance>();
|
|
|
const maintainFormRef = ref<FormInstance>();
|
|
|
@@ -421,14 +479,20 @@ const maintainForm = reactive<any>({
|
|
|
equipmentId: undefined,
|
|
|
equipmentName: '',
|
|
|
equipmentCode: '',
|
|
|
- maintenanceStatus: '待维护',
|
|
|
+ maintenanceStatus: '维护中',
|
|
|
planStartTime: '',
|
|
|
planEndTime: '',
|
|
|
actualStartTime: '',
|
|
|
actualEndTime: '',
|
|
|
+ /** 下次维护时间:仅当 maintenanceStatus='已维护' 时必填 */
|
|
|
+ nextMaintenanceDate: '',
|
|
|
+ /** 维护结果(可选项) */
|
|
|
+ maintenanceResult: '',
|
|
|
maintainerName: '',
|
|
|
siteName: '',
|
|
|
- maintenanceContent: ''
|
|
|
+ maintenanceContent: '',
|
|
|
+ /** 维护照片 JSON 字符串 */
|
|
|
+ photoList: '[]'
|
|
|
});
|
|
|
|
|
|
const maintainRules = {
|
|
|
@@ -448,7 +512,20 @@ const maintainRules = {
|
|
|
}
|
|
|
],
|
|
|
maintainerName: [{ required: true, message: '请选择维护人员', trigger: 'blur' }],
|
|
|
- siteName: [{ required: true, message: '请选择现场人员', trigger: 'blur' }]
|
|
|
+ siteName: [{ required: true, message: '请选择现场人员', trigger: 'blur' }],
|
|
|
+ // 已维护时下次维护时间必填(④)
|
|
|
+ nextMaintenanceDate: [
|
|
|
+ {
|
|
|
+ validator: (_rule: any, value: any, callback: any) => {
|
|
|
+ if (maintainForm.maintenanceStatus === '已维护' && !value) {
|
|
|
+ callback(new Error('维护完成时,请录入下次维护时间'));
|
|
|
+ } else {
|
|
|
+ callback();
|
|
|
+ }
|
|
|
+ },
|
|
|
+ trigger: 'change'
|
|
|
+ }
|
|
|
+ ]
|
|
|
};
|
|
|
|
|
|
const recordList = ref<RiskEquipmentMaintenanceVo[]>([]);
|
|
|
@@ -509,11 +586,9 @@ const formatDateTime = (val: any): string => {
|
|
|
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}`;
|
|
|
};
|
|
|
|
|
|
+// 取最新一条维护记录注入的字段(由后端 fillLatestMaintenance 填充)
|
|
|
const formatMaintenanceTime = (row: any, type: 'start' | 'end') => {
|
|
|
- if (row.maintenanceStatus === '已维护') {
|
|
|
- return formatDateTime(type === 'start' ? row.actualStartTime : row.actualEndTime);
|
|
|
- }
|
|
|
- return formatDateTime(type === 'start' ? row.planStartTime : row.planEndTime);
|
|
|
+ return formatDateTime(type === 'start' ? row.maintenanceStartTime : row.maintenanceEndTime);
|
|
|
};
|
|
|
|
|
|
const disabledEndDate = (time: Date, startTime: string) => {
|
|
|
@@ -525,8 +600,8 @@ const getList = async () => {
|
|
|
loading.value = true;
|
|
|
if (nextDateRange.value && nextDateRange.value.length === 2) {
|
|
|
queryParams.value.params = {
|
|
|
- beginNextInspectionDate: nextDateRange.value[0],
|
|
|
- endNextInspectionDate: nextDateRange.value[1]
|
|
|
+ beginNextMaintenanceDate: nextDateRange.value[0],
|
|
|
+ endNextMaintenanceDate: nextDateRange.value[1]
|
|
|
};
|
|
|
} else {
|
|
|
queryParams.value.params = {};
|
|
|
@@ -547,7 +622,7 @@ const resetQuery = () => {
|
|
|
nextDateRange.value = [];
|
|
|
queryParams.value.equipmentName = '';
|
|
|
queryParams.value.equipmentType = '';
|
|
|
- queryParams.value.inspectionStatus = '';
|
|
|
+ queryParams.value.maintenanceStatus = '';
|
|
|
handleQuery();
|
|
|
};
|
|
|
|
|
|
@@ -626,6 +701,52 @@ const clearEquipmentPhotos = () => {
|
|
|
equipmentPhotoPreview.value = [];
|
|
|
};
|
|
|
|
|
|
+// ============ 维护照片上传 ============
|
|
|
+const triggerMaintainUpload = () => {
|
|
|
+ maintainPhotoInputRef.value?.click();
|
|
|
+};
|
|
|
+
|
|
|
+const onMaintainPhotoInputChange = async (e: Event) => {
|
|
|
+ const input = e.target as HTMLInputElement;
|
|
|
+ const files = Array.from(input.files || []);
|
|
|
+ if (files.length === 0) return;
|
|
|
+ for (const file of files) {
|
|
|
+ if (!['image/jpeg', 'image/png', 'image/jpg'].includes(file.type)) {
|
|
|
+ ElMessage.error(`文件 ${file.name} 格式不支持,仅允许 JPG/PNG`);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ if (file.size / 1024 / 1024 >= 10) {
|
|
|
+ ElMessage.error(`文件 ${file.name} 超过 10MB`);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ await uploadMaintainPhoto(file);
|
|
|
+ }
|
|
|
+ input.value = '';
|
|
|
+};
|
|
|
+
|
|
|
+const uploadMaintainPhoto = async (file: File) => {
|
|
|
+ try {
|
|
|
+ const res: any = await uploadFile(file as any);
|
|
|
+ const url: string | undefined = res?.url || res?.data?.url;
|
|
|
+ if (url) {
|
|
|
+ maintainPreviewPhotos.value.push(url);
|
|
|
+ ElMessage.success(`${file.name} 上传成功`);
|
|
|
+ } else {
|
|
|
+ ElMessage.error(`${file.name} 上传失败`);
|
|
|
+ }
|
|
|
+ } catch (e: any) {
|
|
|
+ ElMessage.error(`${file.name} 上传失败: ${e?.message || '网络异常'}`);
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+const removeMaintainPhoto = (idx: number) => {
|
|
|
+ maintainPreviewPhotos.value.splice(idx, 1);
|
|
|
+};
|
|
|
+
|
|
|
+const clearMaintainPhotos = () => {
|
|
|
+ maintainPreviewPhotos.value = [];
|
|
|
+};
|
|
|
+
|
|
|
const submitForm = () => {
|
|
|
formRef.value?.validate(async (valid: boolean) => {
|
|
|
if (valid) {
|
|
|
@@ -667,40 +788,90 @@ const closeDialog = () => {
|
|
|
reset();
|
|
|
};
|
|
|
|
|
|
-const handleMaintain = (row: RiskSpecialEquipmentVo) => {
|
|
|
- maintainForm.id = undefined;
|
|
|
- maintainForm.equipmentId = row.id;
|
|
|
- maintainForm.equipmentName = row.equipmentName;
|
|
|
- maintainForm.equipmentCode = row.equipmentCode;
|
|
|
- maintainForm.maintenanceStatus = '待维护';
|
|
|
- maintainForm.planStartTime = '';
|
|
|
- maintainForm.planEndTime = '';
|
|
|
- maintainForm.actualStartTime = '';
|
|
|
- maintainForm.actualEndTime = '';
|
|
|
- maintainForm.maintainerName = '';
|
|
|
- maintainForm.siteName = '';
|
|
|
- maintainForm.maintenanceContent = '';
|
|
|
- maintainDialog.visible = true;
|
|
|
+// 设备维护按钮 - 按用户需求 ③:
|
|
|
+// 先查 latestInProgress: 若有"维护中" -> 打开维护编辑页(继续);若无 -> 打开新增维护页
|
|
|
+const handleMaintain = async (row: RiskSpecialEquipmentVo) => {
|
|
|
+ try {
|
|
|
+ const res: any = await getLatestInProgressMaintenance(row.id);
|
|
|
+ const inProgress: RiskEquipmentMaintenanceVo | null = res?.data || null;
|
|
|
+ if (inProgress && inProgress.id) {
|
|
|
+ // 有维护中:回填到维护表单,编辑模式
|
|
|
+ maintainForm.id = inProgress.id;
|
|
|
+ maintainForm.equipmentId = row.id;
|
|
|
+ maintainForm.equipmentName = row.equipmentName;
|
|
|
+ maintainForm.equipmentCode = row.equipmentCode;
|
|
|
+ maintainForm.maintenanceStatus = inProgress.maintenanceStatus || '维护中';
|
|
|
+ maintainForm.planStartTime = inProgress.planStartTime || '';
|
|
|
+ maintainForm.planEndTime = inProgress.planEndTime || '';
|
|
|
+ maintainForm.actualStartTime = inProgress.actualStartTime || '';
|
|
|
+ maintainForm.actualEndTime = inProgress.actualEndTime || '';
|
|
|
+ maintainForm.maintainerName = inProgress.maintainerName || '';
|
|
|
+ maintainForm.siteName = inProgress.siteName || '';
|
|
|
+ maintainForm.maintenanceContent = inProgress.maintenanceContent || '';
|
|
|
+ maintainForm.nextMaintenanceDate = inProgress.nextMaintenanceDate || '';
|
|
|
+ maintainForm.maintenanceResult = inProgress.maintenanceResult || '';
|
|
|
+ // 维护中的照片(只读展示)
|
|
|
+ maintainForm.photoList = inProgress.photoList || '[]';
|
|
|
+ maintainDialog.title = '继续维护(维护中)';
|
|
|
+ } else {
|
|
|
+ // 无维护中:新增维护
|
|
|
+ maintainForm.id = undefined;
|
|
|
+ maintainForm.equipmentId = row.id;
|
|
|
+ maintainForm.equipmentName = row.equipmentName;
|
|
|
+ maintainForm.equipmentCode = row.equipmentCode;
|
|
|
+ maintainForm.maintenanceStatus = '维护中';
|
|
|
+ maintainForm.planStartTime = '';
|
|
|
+ maintainForm.planEndTime = '';
|
|
|
+ maintainForm.actualStartTime = '';
|
|
|
+ maintainForm.actualEndTime = '';
|
|
|
+ maintainForm.maintainerName = '';
|
|
|
+ maintainForm.siteName = '';
|
|
|
+ maintainForm.maintenanceContent = '';
|
|
|
+ maintainForm.nextMaintenanceDate = '';
|
|
|
+ maintainForm.maintenanceResult = '';
|
|
|
+ maintainForm.photoList = '[]';
|
|
|
+ maintainDialog.title = '新增设备维护';
|
|
|
+ }
|
|
|
+ maintainDialog.visible = true;
|
|
|
+ } catch (e: any) {
|
|
|
+ ElMessage.error('查询维护中记录失败: ' + (e?.message || '网络异常'));
|
|
|
+ }
|
|
|
};
|
|
|
|
|
|
const submitMaintainForm = () => {
|
|
|
maintainFormRef.value?.validate(async (valid: boolean) => {
|
|
|
- if (valid) {
|
|
|
- const submit = { ...maintainForm };
|
|
|
- if (submit.maintenanceStatus === '已维护' && !submit.actualStartTime) {
|
|
|
- submit.actualStartTime = submit.planStartTime;
|
|
|
- submit.actualEndTime = submit.planEndTime;
|
|
|
- }
|
|
|
+ if (!valid) return;
|
|
|
+ // ④ 已维护 -> 必须录入下次维护时间
|
|
|
+ if (maintainForm.maintenanceStatus === '已维护' && !maintainForm.nextMaintenanceDate) {
|
|
|
+ ElMessage.error('请录入下次维护时间');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ const submit: any = { ...maintainForm };
|
|
|
+ // 同步照片列表到 photoList(JSON 字符串)
|
|
|
+ submit.photoList = JSON.stringify(maintainPreviewPhotos.value);
|
|
|
+ // 已维护:自动回填实际开始/结束时间为预计时间(若未填)
|
|
|
+ if (submit.maintenanceStatus === '已维护') {
|
|
|
+ if (!submit.actualStartTime) submit.actualStartTime = submit.planStartTime;
|
|
|
+ if (!submit.actualEndTime) submit.actualEndTime = submit.planEndTime;
|
|
|
+ }
|
|
|
+ // 新增或更新(按 maintainForm.id 判断)
|
|
|
+ if (submit.id) {
|
|
|
+ await updateEquipmentMaintenance(submit);
|
|
|
+ proxy?.$modal.msgSuccess('维护记录已更新');
|
|
|
+ } else {
|
|
|
await addEquipmentMaintenance(submit);
|
|
|
proxy?.$modal.msgSuccess('维护记录已保存');
|
|
|
- maintainDialog.visible = false;
|
|
|
}
|
|
|
+ maintainDialog.visible = false;
|
|
|
+ await getList();
|
|
|
});
|
|
|
};
|
|
|
|
|
|
const closeMaintainDialog = () => {
|
|
|
maintainDialog.visible = false;
|
|
|
maintainFormRef.value?.resetFields();
|
|
|
+ // 关闭时同时清空照片队列,避免下次打开看到旧照片
|
|
|
+ clearMaintainPhotos();
|
|
|
};
|
|
|
|
|
|
const handleViewRecords = async (row: RiskSpecialEquipmentVo) => {
|
|
|
@@ -712,8 +883,9 @@ const handleViewRecords = async (row: RiskSpecialEquipmentVo) => {
|
|
|
const loadRecordList = async (equipmentId: string | number) => {
|
|
|
recordLoading.value = true;
|
|
|
try {
|
|
|
- const res = await listEquipmentMaintenance({ equipmentId } as any);
|
|
|
- recordList.value = res.rows || [];
|
|
|
+ // 使用 listByEquipment 接口直接获取列表,无需分页参数
|
|
|
+ const res: any = await listEquipmentMaintenanceByEquipment(equipmentId);
|
|
|
+ recordList.value = (res?.data || []) as RiskEquipmentMaintenanceVo[];
|
|
|
} catch (e) {
|
|
|
recordList.value = [];
|
|
|
}
|
|
|
@@ -727,7 +899,7 @@ const handleAddRecord = () => {
|
|
|
maintainForm.equipmentId = last.equipmentId;
|
|
|
maintainForm.equipmentName = last.equipmentName;
|
|
|
maintainForm.equipmentCode = last.equipmentCode;
|
|
|
- maintainForm.maintenanceStatus = '待维护';
|
|
|
+ maintainForm.maintenanceStatus = '维护中';
|
|
|
maintainForm.planStartTime = '';
|
|
|
maintainForm.planEndTime = '';
|
|
|
maintainForm.actualStartTime = '';
|
|
|
@@ -735,6 +907,11 @@ const handleAddRecord = () => {
|
|
|
maintainForm.maintainerName = '';
|
|
|
maintainForm.siteName = '';
|
|
|
maintainForm.maintenanceContent = '';
|
|
|
+ maintainForm.nextMaintenanceDate = '';
|
|
|
+ maintainForm.maintenanceResult = '';
|
|
|
+ maintainForm.photoList = '[]';
|
|
|
+ clearMaintainPhotos();
|
|
|
+ maintainDialog.title = '新增设备维护';
|
|
|
maintainDialog.visible = true;
|
|
|
}
|
|
|
};
|