瀏覽代碼

feat:安全宣传栏增加图片上传字段,以及对应的功能

sunqijun 3 周之前
父節點
當前提交
0ff246234e

+ 117 - 14
src/views/production-safety/safety-culture/safetyPublicityBoardManagement/components/safetyPublicityBoardManagementDetail.vue

@@ -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);

+ 10 - 0
src/views/production-safety/safety-culture/safetyPublicityBoardManagement/configs/form.ts

@@ -37,6 +37,15 @@ export const ACADEMY_FILE_FORM_CONFIG: FormConfig[] = [
       style:'width:45%',
     },
   },
+  // 状态为什么要去掉,肯定是当成bug修复去掉了,不要质疑
+  {
+    prop: 'imageUrls',
+    label: '图片上传:',
+    slot: 'imageUrls',
+    componentProps: {
+      style:'width:45%',
+    },
+  },
 ];
 
 export const ACADEMY_FILE_FORM_DATA = {
@@ -46,6 +55,7 @@ export const ACADEMY_FILE_FORM_DATA = {
   fileFormat: '',
   status: 1,
   attachmentUrl: [] as FileItem[],
+  imageUrls:'',
 };
 
 export const ACADEMY_FILE_FORM_RULES = {

+ 1 - 0
src/views/production-safety/safety-culture/safetyPublicityBoardManagement/configs/tables.ts

@@ -33,6 +33,7 @@ export const INVENTORY_TABLE_COLUMNS: TableColumnProps[] = [
     prop: 'categoryName',
     align: 'left',
     minWidth: '120px',
+    showOverflowTooltip: true,
   },
   // {
   //   label: '资料描述',