|
|
@@ -30,20 +30,11 @@
|
|
|
<el-button link type="primary" @click="previewOnline(file.fileUrl, file.fileType)"
|
|
|
>预览</el-button
|
|
|
>
|
|
|
- <!-- <el-button link type="primary" @click.stop="downloadFile(file.fileUrl, file.fileName)"
|
|
|
- >下载</el-button
|
|
|
- > -->
|
|
|
+ <el-button link type="primary" @click.stop="downloadFile(file.fileUrl, file.fileName)"
|
|
|
+ >下载</el-button>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
- <!-- <UploadFiles
|
|
|
- label="上传文件"
|
|
|
- :maxCount="1"
|
|
|
- :file-list="ruleFormData.attachmentUrl"
|
|
|
- :disabled="isViewMode"
|
|
|
- :allow-all-file-types="true"
|
|
|
- @upload-success="handleUploadSuccess"
|
|
|
- /> -->
|
|
|
</template>
|
|
|
<template #content>
|
|
|
<div class="editor-container">
|
|
|
@@ -58,6 +49,31 @@
|
|
|
/>
|
|
|
</div>
|
|
|
</template>
|
|
|
+ <template #imageUrls>
|
|
|
+ <el-upload
|
|
|
+ class="image-uploader"
|
|
|
+ ref="courseImgRef"
|
|
|
+ action="#"
|
|
|
+ :file-list="imageList"
|
|
|
+ :disabled="isViewMode"
|
|
|
+ :auto-upload="false"
|
|
|
+ accept="image/*"
|
|
|
+ :on-change="handleImageUploadChange"
|
|
|
+ :on-remove="handlePictureCardDelete"
|
|
|
+ :on-preview="handlePictureCardPreview"
|
|
|
+ :before-upload="validateImage"
|
|
|
+ list-type="picture-card">
|
|
|
+ <el-icon>
|
|
|
+ <Plus />
|
|
|
+ </el-icon>
|
|
|
+ <template #tip>
|
|
|
+ <div class="el-upload__tip"> 支持格式:.jpg .png .jpeg,单个文件不能超过300k</div>
|
|
|
+ </template>
|
|
|
+ </el-upload>
|
|
|
+ <el-dialog v-model="dialogVisible">
|
|
|
+ <img w-full :src="dialogImageUrl" alt="Preview Image" style="width: 100%;" />
|
|
|
+ </el-dialog>
|
|
|
+ </template>
|
|
|
</BasicForm>
|
|
|
<PreviewOnline ref="previewOnlineRef" />
|
|
|
</main>
|
|
|
@@ -73,6 +89,7 @@
|
|
|
import { computed, onMounted, ref, shallowRef, onBeforeUnmount } from 'vue';
|
|
|
import { useRoute, useRouter } from 'vue-router';
|
|
|
import { ElMessage } from 'element-plus';
|
|
|
+ import {Plus} from "@element-plus/icons-vue";
|
|
|
import BasicForm from '@/components/BasicForm.vue';
|
|
|
import UploadFiles from '@/components/UploadFiles/UploadFiles.vue';
|
|
|
import { Editor, Toolbar } from '@wangeditor/editor-for-vue';
|
|
|
@@ -87,7 +104,9 @@
|
|
|
import type { FileItem } from '@/components/UploadFiles/types';
|
|
|
import { formatAttachmentList } from '@/components/UploadFiles/utils';
|
|
|
import PreviewOnline from '@/views/disaster/components/PreviewOnline.vue';
|
|
|
-
|
|
|
+ import { uploadFileApi, UPLOAD_BIZ_TYPE } from '@/api/minio';
|
|
|
+ import { downloadFile } from '@/views/disaster/utils';
|
|
|
+
|
|
|
const router = useRouter();
|
|
|
const route = useRoute();
|
|
|
|
|
|
@@ -124,7 +143,7 @@
|
|
|
});
|
|
|
|
|
|
const basicFormRef = ref<InstanceType<typeof BasicForm>>();
|
|
|
-
|
|
|
+ const imageList = ref<FileItem[]>([]);
|
|
|
// 富文本编辑器
|
|
|
const editorRef = shallowRef();
|
|
|
const editorConfig = computed(() => ({
|
|
|
@@ -146,7 +165,6 @@
|
|
|
const handleUploadSuccess = (files: FileItem[]) => {
|
|
|
ruleFormData.attachmentUrl = files;
|
|
|
};
|
|
|
-
|
|
|
const parseAttachmentUrls = (attachmentUrl?: string): string[] => {
|
|
|
if (!attachmentUrl || !attachmentUrl.trim()) {
|
|
|
return [];
|
|
|
@@ -171,6 +189,88 @@
|
|
|
.filter((url) => url);
|
|
|
};
|
|
|
|
|
|
+ // 上传文件
|
|
|
+ const formatAttachment = async (data: any) => {
|
|
|
+ if (!data) return data;
|
|
|
+ const uuid = Math.random().toString(36).substring(2, 9);
|
|
|
+ const timestamp = Date.now().toString();
|
|
|
+ const random = Math.random().toString(36).substring(2, 4);
|
|
|
+ const fileName = data.name;
|
|
|
+ const res = await uploadFileApi({
|
|
|
+ bizType: UPLOAD_BIZ_TYPE.ATTACHMENT,
|
|
|
+ fileName: `${uuid}-${timestamp}-${random}`,
|
|
|
+ file: data,
|
|
|
+ });
|
|
|
+ return res;
|
|
|
+};
|
|
|
+ // 上传图片
|
|
|
+ const handleImageUploadChange = async (file: any, fileLists: any) => {
|
|
|
+ if(file.raw){
|
|
|
+ try {
|
|
|
+ const res = await formatAttachment(file.raw);
|
|
|
+
|
|
|
+ const targetFile = fileLists.find(f => f.uid === file.uid);
|
|
|
+ if (targetFile) {
|
|
|
+ targetFile.url = res.url;
|
|
|
+ targetFile.contentType = res.contentType
|
|
|
+ }
|
|
|
+ imageList.value = fileLists;
|
|
|
+ ruleFormData.imageUrls = JSON.stringify(fileLists);
|
|
|
+ ElMessage.success('上传成功');
|
|
|
+ } catch (error) {
|
|
|
+ ElMessage.error('上传失败,请重试');
|
|
|
+ // 上传失败时,可以从 fileLists 中移除该文件
|
|
|
+ imageList.value = fileLists.filter(f => f.uid !== file.uid);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ };
|
|
|
+ // 删除图片
|
|
|
+ const handlePictureCardDelete = (file, fileLists)=>{
|
|
|
+ imageList.value = fileLists.filter(f => f.uid !== file.uid);
|
|
|
+ ruleFormData.imageUrls = JSON.stringify(imageList.value);
|
|
|
+ }
|
|
|
+// 图片预览
|
|
|
+ const dialogVisible = ref(false);
|
|
|
+ const dialogImageUrl = ref('');
|
|
|
+ const handlePictureCardPreview = (file: any) => {
|
|
|
+ dialogImageUrl.value = file.url;
|
|
|
+ dialogVisible.value = true;
|
|
|
+ };
|
|
|
+
|
|
|
+// 图片格式校验
|
|
|
+ const validateImage = (file) => {
|
|
|
+ const validMIME = [
|
|
|
+ 'image/jpeg',
|
|
|
+ 'image/png',
|
|
|
+ 'image/gif',
|
|
|
+ 'image/bmp',
|
|
|
+ 'image/webp',
|
|
|
+ 'image/svg+xml',
|
|
|
+ 'image/tiff',
|
|
|
+ 'image/heic',
|
|
|
+ 'image/heif',
|
|
|
+ 'image/avif',
|
|
|
+ ];
|
|
|
+
|
|
|
+ if (!validMIME.includes(file.type)) {
|
|
|
+ ElMessage.error('仅支持图片文件(JPEG/PNG/GIF/BMP/WEBP/SVG/TIFF/HEIC/AVIF等)');
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!validMIME.includes(file.type)) {
|
|
|
+ ElMessage.error('仅支持JPG/PNG格式图片');
|
|
|
+ return false; // 阻止上传
|
|
|
+ }
|
|
|
+
|
|
|
+ // 可选:添加文件大小限制
|
|
|
+ const maxSize = 1 * 1024 * 1024; // 4MB
|
|
|
+ if (file.size > maxSize) {
|
|
|
+ ElMessage.error('图片大小不能超过1MB');
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ return true; // 验证通过
|
|
|
+ };
|
|
|
// 将逗号分隔的URL字符串转换为FileItem数组
|
|
|
const convertFileUrlToFileItems = (fileUrl: string): FileItem[] => {
|
|
|
if (!fileUrl || !fileUrl.trim()) {
|
|
|
@@ -222,6 +322,8 @@
|
|
|
ruleFormData.description = res.description || '';
|
|
|
ruleFormData.attachmentUrl = JSON.parse(res.attachmentUrl || res.fileUrl || '');
|
|
|
ruleFormData.status = res.status ?? 1;
|
|
|
+ ruleFormData.imageUrls = JSON.parse(res.imageUrls || '');
|
|
|
+ imageList.value = JSON.parse(res.imageUrls || '') || [];
|
|
|
}
|
|
|
cloneRuleFormData();
|
|
|
} catch (e) {
|
|
|
@@ -252,6 +354,7 @@
|
|
|
categoryName: ruleFormData.categoryName,
|
|
|
description: ruleFormData.description,
|
|
|
attachmentUrl: JSON.stringify(uploadedFileList),
|
|
|
+ imageUrls: ruleFormData.imageUrls
|
|
|
};
|
|
|
if (isCreateMode.value) {
|
|
|
await saveSafetyPublicityBoardPage(basePayload);
|