linkmore-design
Version:
🌈 🚀lm组件库。🚀
508 lines (488 loc) • 19.5 kB
JavaScript
import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
import _asyncToGenerator from "@babel/runtime/helpers/esm/asyncToGenerator";
import _regeneratorRuntime from "@babel/runtime/regenerator";
import { useMemoizedFn } from 'ahooks';
import OSS from 'ali-oss';
import { useCallback, useRef } from 'react';
import message from "../../message";
var useCoreOptions = function useCoreOptions(_ref) {
var state = _ref.state,
dispatch = _ref.dispatch,
props = _ref.props;
var uid = props.uid,
onChange = props.onChange,
type = props.type,
fileSize = props.fileSize,
fileSizeType = props.fileSizeType,
fileAreaSize = props.fileAreaSize,
enabledOss = props.enabledOss,
enableCrop = props.enableCrop,
ossConfig = props.ossConfig,
multiple = props.multiple,
locale = props.locale;
var fileUploadLen = useRef(null); // 上传的文件数量
var doneFileUploadLen = useRef([]); // 已完成上传的文件
/* 获取两个对象是否存在指定值相等
* 取用户定义的列字段,如果读取不到则取'fileName'对比
*/
var getHasEqual = useCallback(function (obj1, obj2) {
var extend = [uid, 'fileName'];
var flag = false;
extend.forEach(function (v) {
if (!flag && obj1[v] && obj2[v]) {
flag = obj1[v] === obj2[v];
}
});
return flag;
}, [uid]);
// 从对象中读取存在的指定属性
var getFileHasValue = useCallback(function (obj) {
if (!obj) return '';
var extend = [uid, 'fileName'];
var val = '';
extend.forEach(function (v) {
if (!val && obj[v]) val = obj[v];
});
return val;
}, [uid]);
// 获取当前的文件列表
var getFileList = useCallback(function () {
return props.fileList || state.fileList;
}, [props.fileList, state.fileList]);
// 获取上传状态
var getUploadStatus = useCallback(function () {
var uploading = typeof state.percent === 'number';
return {
uploading: uploading
};
}, [state.percent]);
// 获取文件字段值
var getFileFields = useCallback(function (fileParams) {
var fileNames = props.fileNames;
var obj = {};
Object.entries(fileNames).forEach(function (v) {
var itemKey = v[0];
var itemValue = v[1];
if (fileParams[itemKey]) {
obj[itemKey] = fileParams[itemValue];
}
});
return obj;
}, [props]);
// 获取是否达到最大上传数量
var getIsMaxCount = useCallback(function () {
var maxCount = props.maxCount,
limit = props.limit;
var flag = false;
var num = maxCount || limit;
if (num && typeof num === 'number') {
flag = !(getFileList().length < num);
}
return flag;
}, [getFileList, props]);
// 上传成功事件: File, fileParams
var uploadSuccess = useCallback( /*#__PURE__*/function () {
var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(file, params, ossCallBack) {
var _props$onSuccess, _props$onCallBack;
var fileList, res;
return _regeneratorRuntime.wrap(function _callee$(_context) {
while (1) switch (_context.prev = _context.next) {
case 0:
fileList = Array.isArray(params) ? [].concat(_toConsumableArray(getFileList()), _toConsumableArray(params)) : [].concat(_toConsumableArray(getFileList()), [params]);
dispatch({
type: 'changeFileList',
fileList: fileList
});
dispatch({
type: 'changePercent',
percent: null
});
// 上传事件:抛出 file: 文件 filelist: 文件列表 event: 上传进度信息
(_props$onSuccess = props.onSuccess) === null || _props$onSuccess === void 0 ? void 0 : _props$onSuccess.call(props, {
file: file,
fileList: fileList
});
onChange === null || onChange === void 0 ? void 0 : onChange({
file: file,
fileList: fileList
});
doneFileUploadLen.current = [];
_context.next = 8;
return ossCallBack === null || ossCallBack === void 0 ? void 0 : ossCallBack(Array.isArray(params) ? params : [params]);
case 8:
res = _context.sent;
(_props$onCallBack = props.onCallBack) === null || _props$onCallBack === void 0 ? void 0 : _props$onCallBack.call(props, res, {
file: file,
fileList: fileList
});
case 10:
case "end":
return _context.stop();
}
}, _callee);
}));
return function (_x, _x2, _x3) {
return _ref2.apply(this, arguments);
};
}(), [getFileList, props.onSuccess, props.onCallBack, onChange, dispatch, doneFileUploadLen.current]);
// 上传进度事件
var uploadProgress = useCallback(function (file, _ref3) {
var _props$onProgress;
var progress = _ref3.progress,
checkPoint = _ref3.checkPoint,
result = _ref3.result;
var params = {
file: file,
fileList: getFileList(),
event: {
progress: progress,
checkPoint: checkPoint,
result: result,
status: typeof progress !== 'number' ? 'done' : 'uploading'
}
};
(_props$onProgress = props.onProgress) === null || _props$onProgress === void 0 ? void 0 : _props$onProgress.call(props, params);
onChange === null || onChange === void 0 ? void 0 : onChange(params);
dispatch({
type: 'changePercent',
percent: Number((progress * 100).toFixed(2))
});
}, [getFileList, props.onProgress, onChange, dispatch]);
// 上传失败事件
var uploadError = useCallback(function (_ref4) {
var error = _ref4.error,
file = _ref4.file;
props.onError ? props.onError({
error: error,
file: file,
fileList: getFileList()
}) : message.warning(locale.fileUploadError, 1.5);
onChange === null || onChange === void 0 ? void 0 : onChange({
file: file,
fileList: getFileList(),
event: {
status: 'error'
}
});
doneFileUploadLen.current = [];
}, [props.onError, getFileList, onChange, doneFileUploadLen.current, locale]);
// 上传至ali-oss
var uploadOss = useCallback( /*#__PURE__*/function () {
var _ref5 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2(file) {
var _ossConfig, _ossConfig$dir, filePath, shortlink, _ossConfig$region, region, accessKeyId, accessKeySecret, stsToken, _ossConfig$bucket, bucket, ossCallBack, client, timestamp, pattern, tripFileName, suffixIndex, realFileName, fileName, pathName, url, params;
return _regeneratorRuntime.wrap(function _callee2$(_context2) {
while (1) switch (_context2.prev = _context2.next) {
case 0:
_context2.prev = 0;
_ossConfig = ossConfig(), _ossConfig$dir = _ossConfig.dir, filePath = _ossConfig$dir === void 0 ? '/BizFile/4595/Supplier/' : _ossConfig$dir, shortlink = _ossConfig.shortlink, _ossConfig$region = _ossConfig.region, region = _ossConfig$region === void 0 ? 'oss-cn-hangzhou' : _ossConfig$region, accessKeyId = _ossConfig.accessKeyId, accessKeySecret = _ossConfig.accessKeySecret, stsToken = _ossConfig.stsToken, _ossConfig$bucket = _ossConfig.bucket, bucket = _ossConfig$bucket === void 0 ? 'linkmore-scm-test' : _ossConfig$bucket, ossCallBack = _ossConfig.ossCallBack;
client = new OSS({
region: region,
accessKeyId: accessKeyId,
accessKeySecret: accessKeySecret,
stsToken: stsToken,
bucket: bucket
});
timestamp = Date.now();
pattern = /[!@#$%^&*()_+{}:“<>?,;'[\]\\|`~]+/g; // 删除特殊字符
tripFileName = file.name.replace(pattern, '');
suffixIndex = tripFileName.lastIndexOf('.');
realFileName = tripFileName.slice(0, Math.min(100, suffixIndex)) + tripFileName.slice(suffixIndex);
fileName = "".concat(timestamp, "-").concat(realFileName);
pathName = filePath.slice(-1) === '/' ? "".concat(filePath).concat(fileName) : "".concat(filePath, "/").concat(fileName);
url = "".concat(shortlink).concat(pathName) || '';
_context2.next = 13;
return client.multipartUpload(pathName, file, {
// 获取分片上传进度、断点和返回值。
progress: function progress(_progress, checkPoint, result) {
return !multiple && uploadProgress(file, {
progress: _progress,
checkPoint: checkPoint,
result: result
});
},
parallel: 4,
// 并发上传分片数量
partSize: 1024 * 1024 // 分片大小
// 会导致部分图片无法上传
// headers: { 'Content-Disposition': `attachment; filename=${realFileName}` },
});
case 13:
params = props.fileConfig({
file: file,
timestamp: timestamp,
fileName: fileName,
filePath: filePath,
shortlink: shortlink,
url: url,
realFileName: realFileName
});
if (!multiple) {
uploadSuccess(file, params, ossCallBack);
}
if (multiple) {
doneFileUploadLen.current = [].concat(_toConsumableArray(doneFileUploadLen.current), [params]);
if (fileUploadLen.current === doneFileUploadLen.current.length) {
uploadSuccess(null, doneFileUploadLen.current, ossCallBack);
}
}
_context2.next = 21;
break;
case 18:
_context2.prev = 18;
_context2.t0 = _context2["catch"](0);
uploadError({
error: _context2.t0,
file: file
});
case 21:
case "end":
return _context2.stop();
}
}, _callee2, null, [[0, 18]]);
}));
return function (_x4) {
return _ref5.apply(this, arguments);
};
}(), [multiple, ossConfig, uploadProgress, props.fileConfig, uploadSuccess, uploadError, fileUploadLen.current, doneFileUploadLen.current]);
// 自定义使用外部上传
var customUpload = useCallback(function (file) {
var _props$fileUpload;
(_props$fileUpload = props.fileUpload) === null || _props$fileUpload === void 0 ? void 0 : _props$fileUpload.call(props, {
file: file,
value: getFileList(),
onChange: uploadSuccess
});
}, [props.fileUpload, getFileList, uploadSuccess]);
// 调用上传方法: 执行 uploadOss && customUpload事件
var uploadFile = useCallback(function (file) {
enabledOss && uploadOss(file);
customUpload(file);
}, [enabledOss, uploadOss, customUpload]);
// 检测完成, 执行外部 `beforeUpload` 事件
var checkOver = useCallback( /*#__PURE__*/function () {
var _ref6 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee3(file) {
var res, newFile;
return _regeneratorRuntime.wrap(function _callee3$(_context3) {
while (1) switch (_context3.prev = _context3.next) {
case 0:
if (props !== null && props !== void 0 && props.beforeUpload) {
_context3.next = 3;
break;
}
uploadFile(file);
return _context3.abrupt("return");
case 3:
res = props.beforeUpload(file, getFileList()); // Promise
if (!(res !== null && res !== void 0 && res.then)) {
_context3.next = 16;
break;
}
_context3.prev = 5;
_context3.next = 8;
return res;
case 8:
newFile = _context3.sent;
uploadFile(newFile);
_context3.next = 15;
break;
case 12:
_context3.prev = 12;
_context3.t0 = _context3["catch"](5);
console.log('上传失败!');
case 15:
return _context3.abrupt("return");
case 16:
if (res) {
_context3.next = 18;
break;
}
return _context3.abrupt("return");
case 18:
// () => true
uploadFile(file);
case 19:
case "end":
return _context3.stop();
}
}, _callee3, null, [[5, 12]]);
}));
return function (_x5) {
return _ref6.apply(this, arguments);
};
}(), [props.beforeUpload, getFileList, uploadFile]);
// 单个文件异步校验
var fileCheckAsync = useCallback(function (file) {
return new Promise(function (resolve, reject) {
// 文件类型校验是否通过 | 存在通配符或符合规定类型
var isCheckType = type.includes('*') || type.includes(file.name.replace(/.*\./, '').toLowerCase());
// 大小校验是否通过
var isCheckSize = file.size / 1024 / (fileSizeType.toLowerCase().includes('m') ? 1024 : 1) <= fileSize;
if (!isCheckType) {
var content = type.join('、');
reject(new Error("".concat(locale.fileTypeMessageBefore).concat(content).concat(locale.fileTypeMessageAfter)));
}
if (!isCheckSize) {
reject(new Error("".concat(locale.fileSizeMessage).concat(fileSize).concat(fileSizeType, "\uFF01")));
}
// 是否需要校验图片宽高
if (fileAreaSize) {
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function (evt) {
var res = evt.target.result;
var imageObj = new Image();
imageObj.src = res;
imageObj.onload = function () {
var maxWidth = fileAreaSize.maxWidth,
maxHeight = fileAreaSize.maxHeight;
var isCheckAreaSizeMaxWidth = !maxWidth || imageObj.width <= maxWidth;
var isCheckAreaSizeMaxHeight = !maxHeight || imageObj.height <= maxHeight;
if (!isCheckAreaSizeMaxWidth || !isCheckAreaSizeMaxHeight) {
reject(new Error(locale.fileSizeLimitMessage));
} else {
resolve(file);
}
};
};
} else {
resolve(file);
}
});
}, [type, fileSize, fileSizeType, fileAreaSize, locale]);
// 文件循环校验,返回校验后的文件数组
var filesLoopCheck = useCallback(function (files) {
return Promise.all(files === null || files === void 0 ? void 0 : files.map(fileCheckAsync));
}, [fileCheckAsync]);
/*
* 上传前: 先校验 => 全部校验通过后开始上传
* 事件执行顺序:
* beforeUpload => filesLoopCheck => checkOver
* => uploadFile => uploadOss && customUpload
* => uploadProgress => uploadSuccess || uploadError
* => Props.onChange && (Props.onSuccess || Props.onError)
*/
var beforeUpload = useCallback( /*#__PURE__*/function () {
var _ref7 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee4(e) {
var files, res;
return _regeneratorRuntime.wrap(function _callee4$(_context4) {
while (1) switch (_context4.prev = _context4.next) {
case 0:
files = Array.from(e.target ? e.target.files : e);
_context4.prev = 1;
_context4.next = 4;
return filesLoopCheck(files);
case 4:
res = _context4.sent;
fileUploadLen.current = res.length;
// 仅单文件上传时可剪裁
if (enableCrop) {
dispatch({
type: 'changeCropFile',
cropFile: res[0]
});
} else {
// 校验完成开始执行上传
res.forEach(checkOver);
}
_context4.next = 13;
break;
case 9:
_context4.prev = 9;
_context4.t0 = _context4["catch"](1);
console.log('文件校验未通过!', _context4.t0.message);
message.warning(_context4.t0.message, 1.5);
case 13:
case "end":
return _context4.stop();
}
}, _callee4, null, [[1, 9]]);
}));
return function (_x6) {
return _ref7.apply(this, arguments);
};
}(), [filesLoopCheck, enableCrop, checkOver, fileUploadLen.current]);
// 删除事件
var remove = useCallback( /*#__PURE__*/function () {
var _ref8 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee5(file) {
var _props$onRemove;
var res, _getFileList, fileList;
return _regeneratorRuntime.wrap(function _callee5$(_context5) {
while (1) switch (_context5.prev = _context5.next) {
case 0:
_context5.next = 2;
return (_props$onRemove = props.onRemove) === null || _props$onRemove === void 0 ? void 0 : _props$onRemove.call(props, file);
case 2:
res = _context5.sent;
if (res) {
fileList = (_getFileList = getFileList()) === null || _getFileList === void 0 ? void 0 : _getFileList.filter(function (v) {
return !getHasEqual(v, file);
});
dispatch({
type: 'changeFileList',
fileList: fileList
});
onChange === null || onChange === void 0 ? void 0 : onChange({
file: file,
fileList: fileList
});
}
case 4:
case "end":
return _context5.stop();
}
}, _callee5);
}));
return function (_x7) {
return _ref8.apply(this, arguments);
};
}(), [props.onRemove, getFileList, onChange, dispatch, getHasEqual]);
// 点击文件链接或预览图标时的回调
var preview = useMemoizedFn(function (file) {
var _props$onPreview;
(_props$onPreview = props.onPreview) === null || _props$onPreview === void 0 ? void 0 : _props$onPreview.call(props, file, getFileList());
});
// 点击下载文件时的回调
var download = useCallback(function (file) {
var _props$onDownload;
(_props$onDownload = props.onDownload) === null || _props$onDownload === void 0 ? void 0 : _props$onDownload.call(props, file);
}, [props.onDownload]);
// 拖拽移动事件
var move = useCallback(function (active, over, fileList) {
var _props$onMove;
(_props$onMove = props.onMove) === null || _props$onMove === void 0 ? void 0 : _props$onMove.call(props, active, over, fileList);
onChange === null || onChange === void 0 ? void 0 : onChange({
file: active,
fileList: fileList
});
dispatch({
type: 'changeFileList',
fileList: fileList
});
}, [props.onMove, onChange, dispatch]);
var CoreMethods = {
getIsMaxCount: getIsMaxCount,
// 获取是否达到最大上传数量
getFileHasValue: getFileHasValue,
getFileFields: getFileFields,
beforeUpload: beforeUpload,
checkOver: checkOver,
getUploadStatus: getUploadStatus,
remove: remove,
preview: preview,
download: download,
move: move
};
var RefMethods = {
getState: function getState() {
return state;
},
getFileList: getFileList,
// 获取文件列表
uploadFile: uploadFile
};
return {
CoreMethods: CoreMethods,
RefMethods: RefMethods
};
};
export default useCoreOptions;