import Compressor from 'compressorjs'; ; export default OakComponent({ entity: 'extraFile', isList: true, projection: { id: 1, tag1: 1, tag2: 1, origin: 1, bucket: 1, objectId: 1, filename: 1, extra1: 1, extra2: 1, extension: 1, type: 1, entity: 1, entityId: 1, fileType: 1, sort: 1, isBridge: 1, uploadState: 1, size: 1, applicationId: 1, }, data: { // 根据 size 不同,计算的图片显示大小不同 itemSizePercentage: '', }, wechatMp: { externalClasses: ['oak-class', 'oak-item-class', 'oak-item-add-class'], }, filters: [ { filter() { const { tag1, tag2 } = this.props; const filter1 = {}; if (tag1) { Object.assign(filter1, { tag1 }); } if (tag2) { Object.assign(filter1, { tag2 }); } return filter1; }, }, ], properties: { bucket: '', autoUpload: false, maxNumber: 20, extension: [], //小程序独有 chooseMessageFile selectCount: 1, // 每次打开图片时,可选中的数量 小程序独有 sourceType: ['album', 'camera'], // 小程序独有 chooseMedia mediaType: ['image'], // 小程序独有 chooseMedia mode: 'aspectFit', // 图片显示模式 size: 3, // 每行可显示的个数 小程序独有 showUploadList: true, //web独有 showUploadProgress: false, // web独有 accept: 'image/*', // web独有 disablePreview: false, // 图片是否可预览 disableDelete: false, // 图片是否可删除 disableAdd: false, // 上传按钮隐藏 disableDownload: false, // 下载按钮隐藏 type: 'image', origin: null, tag1: '', tag2: '', entity: '', entityId: '', theme: 'image', enableCrop: false, //启用裁剪 enableCompross: false, //启用压缩 //图片裁剪 cropQuality: 1, //图片裁剪质量,范围:0 ~ 1 showRest: false, //显示重置按钮,重置缩放及旋转 showGrid: false, //显示裁切区域网格(九宫格) fillColor: 'white', //裁切图像填充色 rotationSlider: false, //图片旋转控制 aspectSlider: false, //裁切比率控制 zoomSlider: true, //图片缩放控制 resetText: '重置', //重置按钮文字 aspect: 1 / 1, //裁切区域宽高比,width / height minZoom: 1, //最小缩放倍数 maxZoom: 3, //最大缩放倍数 cropShape: 'rect', //裁切区域形状,'rect' 或 'round' cropperProps: {}, //recat-easy-crop的props modalTitle: '编辑图片', //弹窗标题 modalWidth: '40vw', //弹窗宽度 modalOk: '确定', //确定按钮文字 modalCancel: '取消', //取消按钮的文字 //图片压缩 strict: true, //当压缩后的图片尺寸大于原图尺寸时输出原图 checkOrientation: true, //读取图像的Exif方向值并自动旋转或翻转图像(仅限 JPEG 图像) retainExif: false, //压缩后保留图片的Exif信息 maxWidth: Infinity, //输出图片的最大宽度,值需大于0 maxHeight: Infinity, //输出图片的最大高度,值需大于0 minWidth: 0, //输出图片的最小宽度,值需大于0且不应大于maxWidth minHeight: 0, //输出图片的最小高度。值需大于0且不应大于maxHeight compressWidth: undefined, //输出图像的宽度。如果未指定,则将使用原始图像的宽度,若设置了height,则宽度将根据自然纵横比自动计算。 compressHeight: undefined, //输出图像的高度。如果未指定,则将使用原始图像的高度,若设置了width,则高度将根据自然纵横比自动计算。 resize: 'none', //仅在同时指定了width和height时生效 compressQuality: 0.8, //输出图像的质量。范围:0 ~ 1 mimeType: 'auto', //输出图片的 MIME 类型。默认情况下,将使用源图片文件的原始 MIME 类型。 convertTypes: ['image/png'], //文件类型包含在其中且文件大小超过该convertSize值的文件将被转换为 JPEG。 convertSize: Infinity, //文件类型包含在convertTypes中且文件大小超过此值的文件将转换为 JPEG,Infinity表示禁用该功能 }, features: ['extraFile'], formData({ data, features }) { let files = data ?.filter((ele) => !ele.$$deleteAt$$) .sort((ele1, ele2) => ele1.sort - ele2.sort); if (this.props.tag1) { files = files?.filter((ele) => ele?.tag1 === this.props.tag1); } if (this.props.tag2) { files = files?.filter((ele) => ele?.tag2 === this.props.tag2); } const files2 = files.map((ele) => { const url = features.extraFile.getUrl(ele); const thumbUrl = features.extraFile.getUrl(ele, 'thumbnail'); const fileState = features.extraFile.getFileState(ele.id); const fileName = features.extraFile.getFileName(ele); return { url, thumbUrl, fileName, fileState: fileState?.state, percentage: fileState?.percentage, ...ele, }; }); return { files: files2, }; }, methods: { async compressFile(file) { //https://github.com/fengyuanchen/compressorjs/blob/main/README.md const { strict, checkOrientation, retainExif, maxWidth, maxHeight, minWidth, minHeight, compressWidth: width, compressHeight: height, resize, compressQuality: quality, mimeType, convertTypes, convertSize } = this.props; // 构建压缩选项 const options = Object.fromEntries(Object.entries({ strict, checkOrientation, retainExif, maxWidth, maxHeight, minWidth, minHeight, width, height, resize, quality, mimeType, convertTypes, convertSize }).filter(([key, value]) => value !== undefined)); const fileSize = (file.size / 1024 / 1024).toFixed(1); console.log("压缩前:", fileSize, "MB"); console.log("压缩比例:", quality); console.log("压缩选项:", options); try { // 封装 Compressor 实例的 Promise const result = await new Promise((resolve, reject) => { new Compressor(file, { ...options, success: (compressedFile) => { console.log("压缩后:", (compressedFile.size / 1024 / 1024).toFixed(1), "MB"); if (compressedFile instanceof Blob) { //@ts-ignore compressedFile = new File([compressedFile], "f" + (compressedFile?.name).slice(-8), { type: compressedFile.type }); } resolve(compressedFile); }, error: (err) => { console.error("压缩错误:", err); reject(err); } }); }); return result; } catch (error) { console.error('处理文件压缩时出错:', error); return file; // 返回原始文件以防压缩失败 } } }, });