179 lines
7.7 KiB
JavaScript
179 lines
7.7 KiB
JavaScript
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; // 返回原始文件以防压缩失败
|
||
}
|
||
}
|
||
},
|
||
});
|