diff --git a/CHANGELOG.md b/CHANGELOG.md index 11fdba899d2bef999b3ca42a4e19b10e78ba7499..2c21f36e221e49e485c5ce35e529e1d02f047df5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,13 @@ ## [Unreleased] +### Added + +- 新增是否显示移动端文件上传loading全局参数showUploadLoading配置 +- 新增支持图片压缩范围编辑器参数imgcompresslimit与全局参数ibiz.config.imgCompressConfig.limit +- 新增支持图片压缩质量编辑器参数imgcompressquality与全局参数ibiz.config.imgCompressConfig.quality +- 新增支持图片压缩最大宽度编辑器参数imgcompressmaxwidth与全局参数ibiz.config.imgCompressConfig.maxWidth + ## [0.7.41-alpha.14] - 2025-09-12 ### Added diff --git a/src/editor/upload/upload-editor.controller.ts b/src/editor/upload/upload-editor.controller.ts index 3d0ff4cf5229fcbdec613c2b8795d7f01ca9ebae..99dca45e8dc1b03f404e6e29d7615cd543bfb140 100644 --- a/src/editor/upload/upload-editor.controller.ts +++ b/src/editor/upload/upload-editor.controller.ts @@ -35,9 +35,53 @@ export class UploadEditorController extends EditorController { public exportParams?: IParams; /** - * 显示加载动画 + * @description 是否显示加载动画 + * @readonly + * @type {boolean} + * @memberof UploadEditorController + */ + get showLoading(): boolean { + if (this.editorParams.showloading) { + return Boolean(this.editorParams.showloading); + } + return ibiz.config.mob.showUploadLoading; + } + + /** + * @description 图片压缩范围(超过该范围进行压缩,单位kb) + * @readonly + * @memberof UploadEditorController + */ + get imgCompressLimit(): number { + if (this.editorParams.imgcompresslimit) { + return Number(this.editorParams.imgcompresslimit); + } + return ibiz.config.imgCompressConfig.limit; + } + + /** + * @description 图片压缩质量(0-1,为0时不压缩,默认为0) + * @readonly + * @memberof UploadEditorController */ - public showLoading: boolean = false; + get imgCompressQuality(): number { + if (this.editorParams.imgcompressquality) { + return Number(this.editorParams.imgcompressquality); + } + return ibiz.config.imgCompressConfig.quality; + } + + /** + * @description 压缩图片最大宽度,默认为1280px + * @readonly + * @memberof UploadEditorController + */ + get imgCompressMaxWidth(): number { + if (this.editorParams.imgcompressmaxwidth) { + return Number(this.editorParams.imgcompressmaxwidth); + } + return ibiz.config.imgCompressConfig.maxWidth; + } /** * 文件类型 @@ -111,14 +155,8 @@ export class UploadEditorController extends EditorController { this.multiple = false; } if (this.editorParams) { - const { - isDrag, - multiple, - accept, - uploadParams, - exportParams, - showloading, - } = this.editorParams; + const { isDrag, multiple, accept, uploadParams, exportParams } = + this.editorParams; if (isDrag) { this.isDrag = Boolean(isDrag); } @@ -128,9 +166,6 @@ export class UploadEditorController extends EditorController { if (accept) { this.accept = accept; } - if (showloading) { - this.showLoading = Boolean(showloading); - } if (uploadParams) { try { this.uploadParams = JSON.parse(uploadParams); diff --git a/src/editor/upload/use/use-van-upload.ts b/src/editor/upload/use/use-van-upload.ts index 97a1918692b5d1eaf5895298a552f1d9edfe6038..59cea166bf4ea86b2cdc2e5a74a8f5055d9493f2 100644 --- a/src/editor/upload/use/use-van-upload.ts +++ b/src/editor/upload/use/use-van-upload.ts @@ -195,11 +195,76 @@ export function useVanUpload( emitValue(); }; - const uploadFile = (file: IData) => { + /** + * 图片压缩 + * @param file 原始文件 + * @param maxW 最大宽度(默认 1280) + * @param quality 压缩质量 0~1(默认 0.8) + * @returns Promise 压缩后的新文件 + */ + const compressImg = ( + file: File, + maxW = 1280, + quality = 0.8, + ): Promise => { + return new Promise((resolve, reject) => { + const img = new Image(); + img.src = URL.createObjectURL(file); + img.onerror = (e: string | Event) => reject(e); + img.onload = () => { + const { width: w, height: h } = img; + + // 等比缩放 + const scale = w > h ? maxW / w : maxW / h; + const cw = scale < 1 ? Math.round(w * scale) : w; + const ch = scale < 1 ? Math.round(h * scale) : h; + + const canvas = document.createElement('canvas'); + canvas.width = cw; + canvas.height = ch; + const ctx = canvas.getContext('2d')!; + ctx.drawImage(img, 0, 0, cw, ch); + + canvas.toBlob( + blob => { + if (!blob) return reject(); + // 把 blob 转成新 File(保留原名、类型) + const newFile = new File([blob], file.name, { + type: 'image/jpeg', + lastModified: Date.now(), + }); + resolve(newFile); + }, + 'image/jpeg', + quality, + ); + }; + }); + }; + + const uploadFile = async (file: IData) => { + const size = file.file.size; + const sizeKB = size / 1024; + let curFile = file.file; + if ( + c.imgCompressQuality && + c.imgCompressLimit && + sizeKB > c.imgCompressLimit + ) { + try { + curFile = await compressImg( + curFile, + c.imgCompressMaxWidth, + c.imgCompressQuality, + ); + } catch { + ibiz.log.error(ibiz.i18n.t('editor.upload.compressError')); + } + } // 创建一个空对象实例 const formData = new FormData(); // 调用append()方法添加数据 - formData.append('file', file.file); + formData.append('file', curFile); return new Promise((resolve, reject) => { ibiz.net .axios({ diff --git a/src/locale/en/index.ts b/src/locale/en/index.ts index c7d3aadd8b30dbc4a3b752276bebbb95e466ea5c..2f0593cb36fba959e4b3c1c0c6e311c7de724455 100644 --- a/src/locale/en/index.ts +++ b/src/locale/en/index.ts @@ -210,6 +210,7 @@ export default { exportJsonFormatErr: 'The configuration of exportparams did not follow the standard JSON format', cancelUpload: 'Cancel Upload', + compressError: 'Image compression failed', }, emojiPicker: { addEmoji: 'Add emoji', diff --git a/src/locale/zh-CN/index.ts b/src/locale/zh-CN/index.ts index 40979e3a368aa282911a51d27404b03074c7807f..9fb6a29e38f445723cd1314444e48e51ac2df9fe 100644 --- a/src/locale/zh-CN/index.ts +++ b/src/locale/zh-CN/index.ts @@ -188,6 +188,7 @@ export default { uploadJsonFormatErr: '配置uploadparams没有按标准JSON格式', exportJsonFormatErr: '配置exportparams没有按标准JSON格式', cancelUpload: '取消上传', + compressError: '图片压缩失败', }, emojiPicker: { addEmoji: '添加表情',