|
@@ -43,7 +43,31 @@
|
|
|
<el-table-column label="评分方式" prop="scoringMethod" min-width="150" />
|
|
<el-table-column label="评分方式" prop="scoringMethod" min-width="150" />
|
|
|
<el-table-column label="加减分项" prop="scoreType" min-width="120" />
|
|
<el-table-column label="加减分项" prop="scoreType" min-width="120" />
|
|
|
<el-table-column label="自评得分" prop="selfScore" min-width="120" />
|
|
<el-table-column label="自评得分" prop="selfScore" min-width="120" />
|
|
|
- <el-table-column label="资料说明" prop="materialDescription" min-width="200" />
|
|
|
|
|
|
|
+ <el-table-column label="资料说明" prop="materialDescription" min-width="200">
|
|
|
|
|
+ <template #default="scope">
|
|
|
|
|
+ <div
|
|
|
|
|
+ class="file-container--div"
|
|
|
|
|
+ v-for="item in parseAttachments(scope.row.materialDescription)"
|
|
|
|
|
+ :key="item.fileUrl"
|
|
|
|
|
+ >
|
|
|
|
|
+ <img
|
|
|
|
|
+ class="file-container--div__icon"
|
|
|
|
|
+ @click="previewOnline(item.fileUrl, item.fileType as keyof typeof FILE_TYPE_ICON)"
|
|
|
|
|
+ :src="FILE_TYPE_ICON[item.fileType]"
|
|
|
|
|
+ />
|
|
|
|
|
+ <span
|
|
|
|
|
+ class="file-container--div__name"
|
|
|
|
|
+ @click="previewOnline(item.fileUrl, item.fileType as keyof typeof FILE_TYPE_ICON)"
|
|
|
|
|
+ >{{ item.fileName }}</span
|
|
|
|
|
+ >
|
|
|
|
|
+ <img
|
|
|
|
|
+ class="file-container--div__download"
|
|
|
|
|
+ :src="DownloadIcon"
|
|
|
|
|
+ @click="downloadFile(item.fileUrl, item.fileName)"
|
|
|
|
|
+ />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
<el-table-column label="复核人姓名" prop="reviewUserName" min-width="120" />
|
|
<el-table-column label="复核人姓名" prop="reviewUserName" min-width="120" />
|
|
|
<el-table-column label="复核得分" prop="reviewScore" min-width="180">
|
|
<el-table-column label="复核得分" prop="reviewScore" min-width="180">
|
|
|
<template #default="scope">
|
|
<template #default="scope">
|
|
@@ -98,7 +122,6 @@
|
|
|
import { useRouter, useRoute } from 'vue-router';
|
|
import { useRouter, useRoute } from 'vue-router';
|
|
|
import { ElMessage } from 'element-plus';
|
|
import { ElMessage } from 'element-plus';
|
|
|
import type { FormInstance } from 'element-plus';
|
|
import type { FormInstance } from 'element-plus';
|
|
|
- import UploadFiles from '@/components/UploadFiles/UploadFiles.vue';
|
|
|
|
|
import {
|
|
import {
|
|
|
querySecurityExamineIssueDetail,
|
|
querySecurityExamineIssueDetail,
|
|
|
updateSecurityExamineIssueReviewSubmit,
|
|
updateSecurityExamineIssueReviewSubmit,
|
|
@@ -110,6 +133,11 @@
|
|
|
importSecurityExamineIssueDeptDetail,
|
|
importSecurityExamineIssueDeptDetail,
|
|
|
} from '@/api/evaluationSystem';
|
|
} from '@/api/evaluationSystem';
|
|
|
import type { FileItem } from '@/components/UploadFiles/types';
|
|
import type { FileItem } from '@/components/UploadFiles/types';
|
|
|
|
|
+ import { formatAttachmentList } from '@/components/UploadFiles/utils';
|
|
|
|
|
+ import DownloadIcon from '@/views/disaster/disaster-control/src/svg/download.svg';
|
|
|
|
|
+ import { downloadFile } from '@/views/disaster/utils';
|
|
|
|
|
+ import PreviewOnline from '@/views/disaster/components/PreviewOnline.vue';
|
|
|
|
|
+ import { FILE_TYPE_ICON } from '@/components/UploadFiles/constants';
|
|
|
|
|
|
|
|
const props = defineProps<{
|
|
const props = defineProps<{
|
|
|
id: number;
|
|
id: number;
|
|
@@ -313,6 +341,53 @@
|
|
|
}
|
|
}
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
+ // 预览
|
|
|
|
|
+ const previewOnlineRef = ref<InstanceType<typeof PreviewOnline>>();
|
|
|
|
|
+ const previewOnline = (url: string | undefined, type: keyof typeof FILE_TYPE_ICON) => {
|
|
|
|
|
+ if (url) {
|
|
|
|
|
+ previewOnlineRef.value?.open(url, type);
|
|
|
|
|
+ }
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ // 解析逗号分隔的URL字符串为文件列表(用于表格资料说明展示)
|
|
|
|
|
+ const parseAttachments = (
|
|
|
|
|
+ attachmentsStr: string | undefined,
|
|
|
|
|
+ ): Array<{
|
|
|
|
|
+ fileUrl: string;
|
|
|
|
|
+ fileName: string;
|
|
|
|
|
+ fileType: string;
|
|
|
|
|
+ }> => {
|
|
|
|
|
+ if (!attachmentsStr || !attachmentsStr.trim()) {
|
|
|
|
|
+ return [];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const urls = attachmentsStr
|
|
|
|
|
+ .split(',')
|
|
|
|
|
+ .map((url) => url.trim())
|
|
|
|
|
+ .filter((url) => url);
|
|
|
|
|
+
|
|
|
|
|
+ return urls.map((url) => {
|
|
|
|
|
+ const urlParts = url.split('/');
|
|
|
|
|
+ const fileName = urlParts[urlParts.length - 1] || '未知文件';
|
|
|
|
|
+
|
|
|
|
|
+ const extension = fileName.split('.').pop()?.toLowerCase() || '';
|
|
|
|
|
+ let fileType = 'pdf';
|
|
|
|
|
+ if (extension === 'doc' || extension === 'docx') {
|
|
|
|
|
+ fileType = 'word';
|
|
|
|
|
+ } else if (extension === 'xls' || extension === 'xlsx') {
|
|
|
|
|
+ fileType = 'excel';
|
|
|
|
|
+ } else if (extension === 'ppt' || extension === 'pptx') {
|
|
|
|
|
+ fileType = 'ppt';
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return {
|
|
|
|
|
+ fileUrl: url,
|
|
|
|
|
+ fileName,
|
|
|
|
|
+ fileType,
|
|
|
|
|
+ };
|
|
|
|
|
+ });
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
// 将逗号分隔的 URL 字符串转换为 FileItem[] 格式
|
|
// 将逗号分隔的 URL 字符串转换为 FileItem[] 格式
|
|
|
const parseAttachmentsToFileList = (attachmentsStr: string | undefined): FileItem[] => {
|
|
const parseAttachmentsToFileList = (attachmentsStr: string | undefined): FileItem[] => {
|
|
|
if (!attachmentsStr || !attachmentsStr.trim()) {
|
|
if (!attachmentsStr || !attachmentsStr.trim()) {
|
|
@@ -386,7 +461,8 @@
|
|
|
selfScore: score.selfScore || 0, // 自评得分
|
|
selfScore: score.selfScore || 0, // 自评得分
|
|
|
reviewUserName: score.reviewUserName || '-', // 复核人姓名(从详情顶层获取)
|
|
reviewUserName: score.reviewUserName || '-', // 复核人姓名(从详情顶层获取)
|
|
|
reviewScore: score.reviewScore || 0, // 复核得分
|
|
reviewScore: score.reviewScore || 0, // 复核得分
|
|
|
- materialDescription: score.attachments || '', // 资料说明(使用附件字段)
|
|
|
|
|
|
|
+ materialDescription: score.attachments || '', // 资料说明(使用附件字段,字符串)
|
|
|
|
|
+ attachmentFileList: parseAttachmentsToFileList(score.attachments || ''), // 资料说明对应的附件文件列表
|
|
|
isReviewInput: score.isReviewInput == true, // 是否显示复核得分输入框
|
|
isReviewInput: score.isReviewInput == true, // 是否显示复核得分输入框
|
|
|
}));
|
|
}));
|
|
|
} else {
|
|
} else {
|
|
@@ -407,18 +483,59 @@
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 使用详情原始数据,更新复核得分和isAdd字段
|
|
|
|
|
|
|
+ // 使用详情原始数据,更新复核得分、加减分项及资料说明附件
|
|
|
|
|
+ const updatedScores =
|
|
|
|
|
+ (await Promise.all(
|
|
|
|
|
+ (detailData.value.scores || []).map(async (score: any) => {
|
|
|
|
|
+ const item = evaluationItems.value.find((row) => row.id === score.id);
|
|
|
|
|
+
|
|
|
|
|
+ // 处理资料说明附件:将 UploadFiles 返回的文件列表转换为逗号分隔的 URL 字符串
|
|
|
|
|
+ let attachments = score.attachments || '';
|
|
|
|
|
+ if (item && Array.isArray(item.attachmentFileList)) {
|
|
|
|
|
+ const existingFiles: string[] = [];
|
|
|
|
|
+ const newFiles: any[] = [];
|
|
|
|
|
+
|
|
|
|
|
+ item.attachmentFileList.forEach((file: any) => {
|
|
|
|
|
+ if (file.fileUrl && !file.file) {
|
|
|
|
|
+ existingFiles.push(file.fileUrl);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ newFiles.push(file);
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ let uploadedUrls: string[] = [];
|
|
|
|
|
+ if (newFiles.length > 0) {
|
|
|
|
|
+ const uploadedFiles = await formatAttachmentList(newFiles);
|
|
|
|
|
+ uploadedUrls = uploadedFiles
|
|
|
|
|
+ .map((f: any) => f.fileUrl || f.url || '')
|
|
|
|
|
+ .filter((url: string) => url);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ attachments = [...existingFiles, ...uploadedUrls].filter((url) => url).join(',');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return {
|
|
|
|
|
+ ...score,
|
|
|
|
|
+ reviewScore: item ? Number(item.reviewScore) || 0 : score.reviewScore || 0,
|
|
|
|
|
+ isAdd: item
|
|
|
|
|
+ ? item.isAdd !== undefined
|
|
|
|
|
+ ? item.isAdd
|
|
|
|
|
+ : item.selfScore >= 0
|
|
|
|
|
+ ? 1
|
|
|
|
|
+ : 0
|
|
|
|
|
+ : score.isAdd !== undefined
|
|
|
|
|
+ ? score.isAdd
|
|
|
|
|
+ : score.selfScore >= 0
|
|
|
|
|
+ ? 1
|
|
|
|
|
+ : 0,
|
|
|
|
|
+ attachments,
|
|
|
|
|
+ };
|
|
|
|
|
+ }),
|
|
|
|
|
+ )) || [];
|
|
|
|
|
+
|
|
|
const submitData = {
|
|
const submitData = {
|
|
|
...detailData.value,
|
|
...detailData.value,
|
|
|
- scores: detailData.value.scores?.map((score: any) => {
|
|
|
|
|
- // 找到对应的复核得分和isAdd
|
|
|
|
|
- const item = evaluationItems.value.find((item) => item.id === score.id);
|
|
|
|
|
- return {
|
|
|
|
|
- ...score,
|
|
|
|
|
- reviewScore: item ? Number(item.reviewScore) || 0 : score.reviewScore || 0,
|
|
|
|
|
- isAdd: item ? (item.isAdd !== undefined ? item.isAdd : (item.selfScore >= 0 ? 1 : 0)) : (score.isAdd !== undefined ? score.isAdd : (score.selfScore >= 0 ? 1 : 0)),
|
|
|
|
|
- };
|
|
|
|
|
- }) || [],
|
|
|
|
|
|
|
+ scores: updatedScores,
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
if (isAudit.value) {
|
|
if (isAudit.value) {
|
|
@@ -480,6 +597,7 @@
|
|
|
|
|
|
|
|
<style scoped lang="scss">
|
|
<style scoped lang="scss">
|
|
|
@use '@/styles/page-details-layout.scss' as *;
|
|
@use '@/styles/page-details-layout.scss' as *;
|
|
|
|
|
+ @use '@/styles/basic-table-file.scss' as *;
|
|
|
|
|
|
|
|
.reject-alert {
|
|
.reject-alert {
|
|
|
margin-bottom: 20px;
|
|
margin-bottom: 20px;
|