|
@@ -23,7 +23,7 @@
|
|
|
<p class="info-line">
|
|
<p class="info-line">
|
|
|
工作台:<span class="info-value">{{ workbench.workStation }}</span>
|
|
工作台:<span class="info-value">{{ workbench.workStation }}</span>
|
|
|
</p>
|
|
</p>
|
|
|
- <p class="info-line hint-text">支持png/jpeg/jpg/webp</p>
|
|
|
|
|
|
|
+ <p class="info-line hint-text">支持png/jpeg/jpg/webp/heic/heif(heic/heif自动转webp)</p>
|
|
|
<van-button
|
|
<van-button
|
|
|
size="mini"
|
|
size="mini"
|
|
|
type="primary"
|
|
type="primary"
|
|
@@ -206,6 +206,7 @@ import {
|
|
|
import { getHeader, goBack } from '@/utils/android'
|
|
import { getHeader, goBack } from '@/utils/android'
|
|
|
import { detailImageUpload, returnedWorkbench } from '@/api/returned/index.ts'
|
|
import { detailImageUpload, returnedWorkbench } from '@/api/returned/index.ts'
|
|
|
import { compressImage } from '@/utils/imageCompression'
|
|
import { compressImage } from '@/utils/imageCompression'
|
|
|
|
|
+import { convertHeicHeifToWebp, isHeicOrHeif } from '@/utils/imageFormat'
|
|
|
import EditImage from '@/components/EditImage.vue'
|
|
import EditImage from '@/components/EditImage.vue'
|
|
|
|
|
|
|
|
const workbench = ref<Workbench>({ warehouseCode: '', workStation: '' })
|
|
const workbench = ref<Workbench>({ warehouseCode: '', workStation: '' })
|
|
@@ -261,17 +262,13 @@ function getWorkbench(): void {
|
|
|
})
|
|
})
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-const beforeReadImage = (file: File | File[]): any => {
|
|
|
|
|
|
|
+const beforeReadImage = async (file: File | File[]): Promise<UploadImage[] | false> => {
|
|
|
const files = Array.isArray(file) ? file : [file]
|
|
const files = Array.isArray(file) ? file : [file]
|
|
|
|
|
+ const normalizedFiles: File[] = []
|
|
|
|
|
+
|
|
|
for (const f of files) {
|
|
for (const f of files) {
|
|
|
- if (
|
|
|
|
|
- f.name.toLowerCase().endsWith('.heic') ||
|
|
|
|
|
- f.name.toLowerCase().endsWith('.heif')
|
|
|
|
|
- ) {
|
|
|
|
|
- showFailToast('不支持的图片格式')
|
|
|
|
|
- return false
|
|
|
|
|
- }
|
|
|
|
|
- const isImage = /^image\//.test(f.type)
|
|
|
|
|
|
|
+ const isHeicFile = isHeicOrHeif(f)
|
|
|
|
|
+ const isImage = /^image\//.test(f.type) || isHeicFile
|
|
|
if (!isImage) {
|
|
if (!isImage) {
|
|
|
showFailToast('仅支持图片文件')
|
|
showFailToast('仅支持图片文件')
|
|
|
return false
|
|
return false
|
|
@@ -280,10 +277,24 @@ const beforeReadImage = (file: File | File[]): any => {
|
|
|
showFailToast('图片大小不能超过15MB')
|
|
showFailToast('图片大小不能超过15MB')
|
|
|
return false
|
|
return false
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ if (isHeicFile) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const convertedFile = await convertHeicHeifToWebp(f)
|
|
|
|
|
+ normalizedFiles.push(convertedFile)
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ console.error('HEIC/HEIF 转换失败:', error)
|
|
|
|
|
+ showFailToast('HEIC/HEIF 转换失败,请使用 JPG/PNG/WEBP 格式')
|
|
|
|
|
+ return false
|
|
|
|
|
+ }
|
|
|
|
|
+ continue
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ normalizedFiles.push(f)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 返回增强的图片对象数组,包含状态信息
|
|
// 返回增强的图片对象数组,包含状态信息
|
|
|
- return files.map((f) => ({
|
|
|
|
|
|
|
+ return normalizedFiles.map((f) => ({
|
|
|
file: f, // 原始File对象
|
|
file: f, // 原始File对象
|
|
|
status: UPLOAD_STATUS.PENDING,
|
|
status: UPLOAD_STATUS.PENDING,
|
|
|
url: null,
|
|
url: null,
|
|
@@ -623,7 +634,10 @@ const changeFile = async (
|
|
|
const imageObj = imageList[index]
|
|
const imageObj = imageList[index]
|
|
|
|
|
|
|
|
// 将base64转换为File对象
|
|
// 将base64转换为File对象
|
|
|
- const editedFile = dataURLtoFile(editedDataURL, imageObj.file.name)
|
|
|
|
|
|
|
+ const editedFile = dataURLtoFile(
|
|
|
|
|
+ editedDataURL,
|
|
|
|
|
+ getFileNameByMime(imageObj.file.name, editedDataURL),
|
|
|
|
|
+ )
|
|
|
|
|
|
|
|
// 压缩图片(EditImage保存的是PNG,可能很大)
|
|
// 压缩图片(EditImage保存的是PNG,可能很大)
|
|
|
const compressedFile = await compressImage(editedFile)
|
|
const compressedFile = await compressImage(editedFile)
|
|
@@ -669,6 +683,18 @@ function dataURLtoFile(dataurl: string, filename: string): File {
|
|
|
}
|
|
}
|
|
|
return new File([u8arr], filename, { type: mime })
|
|
return new File([u8arr], filename, { type: mime })
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+function getFileNameByMime(fileName: string, dataUrl: string): string {
|
|
|
|
|
+ const mimeMatch = dataUrl.match(/^data:(.*?);/)
|
|
|
|
|
+ const mime = mimeMatch?.[1] || ''
|
|
|
|
|
+ const ext = mime.split('/')[1]
|
|
|
|
|
+ if (!ext) return fileName
|
|
|
|
|
+
|
|
|
|
|
+ const normalizedExt = ext.split('+')[0].toLowerCase()
|
|
|
|
|
+ const dotIndex = fileName.lastIndexOf('.')
|
|
|
|
|
+ if (dotIndex <= 0) return `${fileName}.${normalizedExt}`
|
|
|
|
|
+ return `${fileName.slice(0, dotIndex)}.${normalizedExt}`
|
|
|
|
|
+}
|
|
|
</script>
|
|
</script>
|
|
|
|
|
|
|
|
<style scoped lang="sass">
|
|
<style scoped lang="sass">
|