oak-general-business/es/components/extraFile/crop/index.js

179 lines
7.7 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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中且文件大小超过此值的文件将转换为 JPEGInfinity表示禁用该功能
},
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; // 返回原始文件以防压缩失败
}
}
},
});