zengjun преди 1 месец
родител
ревизия
b115553182
променени са 2 файла, в които са добавени 81 реда и са изтрити 21 реда
  1. 33 14
      src/utils/imageFormat.ts
  2. 48 7
      src/views/returned/register/index.vue

+ 33 - 14
src/utils/imageFormat.ts

@@ -22,21 +22,40 @@ function replaceExtension(fileName: string, extension: string): string {
 }
 
 export async function convertHeicHeifToWebp(file: File): Promise<File> {
-  const { default: heic2any } = await import('heic2any')
-  const result = await heic2any({
-    blob: file,
-    toType: 'image/webp',
-    quality: 0.92,
-  })
+  const type = (file.type || '').toLowerCase()
 
-  const blob = Array.isArray(result) ? result[0] : result
-  if (!(blob instanceof Blob)) {
-    throw new Error('HEIC/HEIF 转换失败')
+  // If the blob already has a browser-readable image MIME (and it's not a HEIC MIME),
+  // skip conversion and return the original file.
+  if (type && type.startsWith('image/') && !HEIC_MIME_TYPES.includes(type)) {
+    return file
   }
 
-  const targetFileName = replaceExtension(file.name, 'webp')
-  return new File([blob], targetFileName, {
-    type: 'image/webp',
-    lastModified: Date.now(),
-  })
+  const { default: heic2any } = await import('heic2any')
+  try {
+    const result = await heic2any({
+      blob: file,
+      toType: 'image/webp',
+      quality: 0.92,
+    })
+
+    const blob = Array.isArray(result) ? result[0] : result
+    if (!(blob instanceof Blob)) {
+      throw new Error('HEIC/HEIF 转换失败')
+    }
+
+    const targetFileName = replaceExtension(file.name, 'webp')
+    return new File([blob], targetFileName, {
+      type: 'image/webp',
+      lastModified: Date.now(),
+    })
+  } catch (err: any) {
+    // heic2any may throw when the provided blob is already browser-readable
+    // (e.g. it contains image/jpeg despite .heic extension). In that case,
+    // treat it as already-converted and return the original file.
+    const msg = String(err?.message || '')
+    if (err && (err.code === 1 || /already browser readable/i.test(msg))) {
+      return file
+    }
+    throw err instanceof Error ? err : new Error('HEIC/HEIF 转换失败')
+  }
 }

+ 48 - 7
src/views/returned/register/index.vue

@@ -262,7 +262,7 @@ function getWorkbench(): void {
     })
 }
 
-const beforeReadImage = async (file: File | File[]): Promise<UploadImage[] | false> => {
+const beforeReadImage = async (file: File | File[]): Promise<File[] | false> => {
   const files = Array.isArray(file) ? file : [file]
   const normalizedFiles: File[] = []
 
@@ -293,17 +293,58 @@ const beforeReadImage = async (file: File | File[]): Promise<UploadImage[] | fal
     normalizedFiles.push(f)
   }
 
-  // 返回增强的图片对象数组,包含状态信息
-  return normalizedFiles.map((f) => ({
-    file: f, // 原始File对象
+  // 返回原始 File 数组 给 van-uploader 进行默认处理,
+  // 我们会在 after-add watcher 中将其转换为 UploadImage 对象。
+  return normalizedFiles
+}
+
+// 将 van-uploader 添加的文件项规范化为 UploadImage 对象
+function toUploadImage(item: any): UploadImage {
+  // Vant 可能直接传入 File,也可能是 { file, url, status }
+  const fileObj: File = item?.file instanceof File ? item.file : item instanceof File ? item : null
+  const url = item?.url || (fileObj ? URL.createObjectURL(fileObj) : null)
+  return {
+    file: fileObj,
     status: UPLOAD_STATUS.PENDING,
-    url: null,
+    url: url,
     error: null,
     retryCount: 0,
-    originalFile: f, // 保留用于重传
-  }))
+    originalFile: fileObj,
+  }
 }
 
+// 监听 van-uploader 绑定的数组,自动将新加入的原始文件项转换为 UploadImage
+import { watch } from 'vue'
+watch(
+  outerImages,
+  (newVal, oldVal) => {
+    if (!Array.isArray(newVal)) return
+    // 如果数组项已经是 UploadImage(包含 status 字段),跳过
+    const needsNormalize = newVal.some((it: any) => !it || !('status' in it))
+    if (!needsNormalize) return
+
+    const normalized = newVal.map((it: any) => {
+      return 'status' in it ? it : toUploadImage(it)
+    })
+    outerImages.value = normalized
+  },
+  { deep: true },
+)
+
+watch(
+  innerImages,
+  (newVal, oldVal) => {
+    if (!Array.isArray(newVal)) return
+    const needsNormalize = newVal.some((it: any) => !it || !('status' in it))
+    if (!needsNormalize) return
+    const normalized = newVal.map((it: any) => {
+      return 'status' in it ? it : toUploadImage(it)
+    })
+    innerImages.value = normalized
+  },
+  { deep: true },
+)
+
 // 单张图片上传函数
 const uploadSingleImage = async (
   imageObj: UploadImage,