|
@@ -63,24 +63,31 @@
|
|
|
<div class="col">
|
|
<div class="col">
|
|
|
<div class="label">上传附件:</div>
|
|
<div class="label">上传附件:</div>
|
|
|
<div class="value value--attachment">
|
|
<div class="value value--attachment">
|
|
|
- <div class="attachment-list">
|
|
|
|
|
|
|
+ <template v-if="attachmentFileList.length">
|
|
|
<div
|
|
<div
|
|
|
- v-for="(item, index) in attachmentList"
|
|
|
|
|
- :key="index"
|
|
|
|
|
- class="attachment-item"
|
|
|
|
|
|
|
+ class="file-container--div"
|
|
|
|
|
+ v-for="item in attachmentFileList"
|
|
|
|
|
+ :key="item.fileUrl || item.fileName"
|
|
|
>
|
|
>
|
|
|
- <span class="attachment-item--name">{{ item.fileName || item.fileNameOrUrl }}</span>
|
|
|
|
|
- <el-button
|
|
|
|
|
- v-if="item.fileUrl || item.url"
|
|
|
|
|
- type="primary"
|
|
|
|
|
- link
|
|
|
|
|
- @click="handlePreview(item)"
|
|
|
|
|
|
|
+ <img
|
|
|
|
|
+ class="file-container--div__icon"
|
|
|
|
|
+ :src="FILE_TYPE_ICON[item.fileType]"
|
|
|
|
|
+ @click="previewOnline(item.fileUrl, item.fileType)"
|
|
|
|
|
+ />
|
|
|
|
|
+ <span
|
|
|
|
|
+ class="file-container--div__name"
|
|
|
|
|
+ @click="previewOnline(item.fileUrl, item.fileType)"
|
|
|
>
|
|
>
|
|
|
- 预览
|
|
|
|
|
- </el-button>
|
|
|
|
|
|
|
+ {{ item.fileName }}
|
|
|
|
|
+ </span>
|
|
|
|
|
+ <img
|
|
|
|
|
+ class="file-container--div__download"
|
|
|
|
|
+ :src="DownloadIcon"
|
|
|
|
|
+ @click="downloadFile(item.fileUrl, item.fileName)"
|
|
|
|
|
+ />
|
|
|
</div>
|
|
</div>
|
|
|
- </div>
|
|
|
|
|
- <span v-if="!attachmentList.length" class="empty-text">-</span>
|
|
|
|
|
|
|
+ </template>
|
|
|
|
|
+ <span v-else class="empty-text">-</span>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
@@ -125,6 +132,9 @@
|
|
|
import { Document } from '@element-plus/icons-vue';
|
|
import { Document } from '@element-plus/icons-vue';
|
|
|
import PreviewOnline from '@/views/disaster/components/PreviewOnline.vue';
|
|
import PreviewOnline from '@/views/disaster/components/PreviewOnline.vue';
|
|
|
import { getDrawLessonsAdminDetail, approveDrawLessons } from '@/api/drawLessons';
|
|
import { getDrawLessonsAdminDetail, approveDrawLessons } from '@/api/drawLessons';
|
|
|
|
|
+ import { FILE_TYPE_ICON } from '@/components/UploadFiles/constants';
|
|
|
|
|
+ import DownloadIcon from '@/views/disaster/disaster-control/src/svg/download.svg';
|
|
|
|
|
+ import { downloadFile } from '@/views/disaster/utils';
|
|
|
|
|
|
|
|
const router = useRouter();
|
|
const router = useRouter();
|
|
|
const route = useRoute();
|
|
const route = useRoute();
|
|
@@ -150,17 +160,44 @@
|
|
|
const submitting = ref(false);
|
|
const submitting = ref(false);
|
|
|
const previewOnlineRef = ref<InstanceType<typeof PreviewOnline>>();
|
|
const previewOnlineRef = ref<InstanceType<typeof PreviewOnline>>();
|
|
|
|
|
|
|
|
- const attachmentList = computed(() => {
|
|
|
|
|
|
|
+ const attachmentFileList = computed(() => {
|
|
|
const d = detailData.value;
|
|
const d = detailData.value;
|
|
|
if (!d) return [];
|
|
if (!d) return [];
|
|
|
- if (Array.isArray(d.attachmentList) && d.attachmentList.length) return d.attachmentList;
|
|
|
|
|
|
|
+ const normalize = (items: Array<{ fileUrl?: string; url?: string; fileName?: string; fileNameOrUrl?: string }>) => {
|
|
|
|
|
+ return items.map((raw, index) => {
|
|
|
|
|
+ const url = raw.fileUrl || raw.url || raw.fileNameOrUrl || '';
|
|
|
|
|
+ const nameFromData = raw.fileName || raw.fileNameOrUrl;
|
|
|
|
|
+ const fileName = nameFromData || (url ? url.split('/').pop() || `附件${index + 1}` : `附件${index + 1}`);
|
|
|
|
|
+ const ext = fileName.split('.').pop()?.toLowerCase() || '';
|
|
|
|
|
+ let fileType: 'pdf' | 'word' | 'excel' | 'ppt' = 'pdf';
|
|
|
|
|
+ if (ext === 'doc' || ext === 'docx') fileType = 'word';
|
|
|
|
|
+ else if (ext === 'xls' || ext === 'xlsx') fileType = 'excel';
|
|
|
|
|
+ else if (ext === 'ppt' || ext === 'pptx') fileType = 'ppt';
|
|
|
|
|
+ return {
|
|
|
|
|
+ fileUrl: url,
|
|
|
|
|
+ fileName,
|
|
|
|
|
+ fileType,
|
|
|
|
|
+ };
|
|
|
|
|
+ });
|
|
|
|
|
+ };
|
|
|
|
|
+ if (Array.isArray(d.attachmentList) && d.attachmentList.length) {
|
|
|
|
|
+ return normalize(d.attachmentList);
|
|
|
|
|
+ }
|
|
|
if (!d.attachments) return [];
|
|
if (!d.attachments) return [];
|
|
|
try {
|
|
try {
|
|
|
const parsed = JSON.parse(d.attachments);
|
|
const parsed = JSON.parse(d.attachments);
|
|
|
- return Array.isArray(parsed) ? parsed : [];
|
|
|
|
|
|
|
+ if (Array.isArray(parsed) && parsed.length) {
|
|
|
|
|
+ return normalize(parsed as Array<{ fileUrl?: string; url?: string; fileName?: string; fileNameOrUrl?: string }>);
|
|
|
|
|
+ }
|
|
|
} catch {
|
|
} catch {
|
|
|
- return d.attachments.split(',').filter(Boolean).map((s) => ({ fileNameOrUrl: s.trim(), fileUrl: s.trim() }));
|
|
|
|
|
|
|
+ const list = d.attachments
|
|
|
|
|
+ .split(',')
|
|
|
|
|
+ .map((s) => s.trim())
|
|
|
|
|
+ .filter(Boolean)
|
|
|
|
|
+ .map((s) => ({ fileNameOrUrl: s, fileUrl: s }));
|
|
|
|
|
+ if (list.length) return normalize(list);
|
|
|
}
|
|
}
|
|
|
|
|
+ return [];
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
const getDetail = async () => {
|
|
const getDetail = async () => {
|
|
@@ -191,9 +228,8 @@
|
|
|
}
|
|
}
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- const handlePreview = (item: { fileUrl?: string; url?: string }) => {
|
|
|
|
|
- const url = item.fileUrl || item.url;
|
|
|
|
|
- if (url) previewOnlineRef.value?.open(url, 'pdf');
|
|
|
|
|
|
|
+ const previewOnline = (url: string | undefined, type: string) => {
|
|
|
|
|
+ if (url) previewOnlineRef.value?.open(url, type);
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
const handleReject = () => {
|
|
const handleReject = () => {
|
|
@@ -253,6 +289,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/page-main-layout.scss' as *;
|
|
@use '@/styles/page-main-layout.scss' as *;
|
|
|
|
|
+ @use '@/styles/basic-table-file.scss' as *;
|
|
|
|
|
|
|
|
.detail-content {
|
|
.detail-content {
|
|
|
display: flex;
|
|
display: flex;
|
|
@@ -357,32 +394,6 @@
|
|
|
flex-wrap: wrap;
|
|
flex-wrap: wrap;
|
|
|
align-items: flex-start;
|
|
align-items: flex-start;
|
|
|
|
|
|
|
|
- .attachment-list {
|
|
|
|
|
- display: grid;
|
|
|
|
|
- grid-template-columns: 1fr 1fr;
|
|
|
|
|
- gap: 12px 24px;
|
|
|
|
|
- width: 100%;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- .attachment-item {
|
|
|
|
|
- display: flex;
|
|
|
|
|
- align-items: center;
|
|
|
|
|
- gap: 8px;
|
|
|
|
|
- font-size: 14px;
|
|
|
|
|
-
|
|
|
|
|
- .attachment-item--name {
|
|
|
|
|
- color: #333;
|
|
|
|
|
- flex: 1;
|
|
|
|
|
- min-width: 0;
|
|
|
|
|
- overflow: hidden;
|
|
|
|
|
- text-overflow: ellipsis;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- .el-button--primary.is-link {
|
|
|
|
|
- flex-shrink: 0;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
.empty-text {
|
|
.empty-text {
|
|
|
color: #999;
|
|
color: #999;
|
|
|
}
|
|
}
|