UNPKG

@alifd/next

Version:

A configurable component library for web built on React.

310 lines (309 loc) 16.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var tslib_1 = require("tslib"); var react_1 = tslib_1.__importDefault(require("react")); var prop_types_1 = tslib_1.__importDefault(require("prop-types")); var classnames_1 = tslib_1.__importDefault(require("classnames")); var react_lifecycles_compat_1 = require("react-lifecycles-compat"); var util_1 = require("../util"); var icon_1 = tslib_1.__importDefault(require("../icon")); var base_1 = tslib_1.__importDefault(require("./base")); var index_1 = tslib_1.__importDefault(require("./runtime/index")); var html5_uploader_1 = tslib_1.__importDefault(require("./runtime/html5-uploader")); var list_1 = tslib_1.__importDefault(require("./list")); var util_2 = require("./util"); var noop = util_1.func.noop; var Upload = /** @class */ (function (_super) { tslib_1.__extends(Upload, _super); function Upload(props) { var _this = _super.call(this, props) || this; _this.onSelect = function (files) { var _a = _this.props, autoUpload = _a.autoUpload, afterSelect = _a.afterSelect, onSelect = _a.onSelect, limit = _a.limit; // 总数 var total = _this.state.value.length + files.length; // 差额 var less = limit - _this.state.value.length; if (less <= 0) { // 差额不足 则不上传 return; } var fileList = files.map(function (file) { var objFile = (0, util_2.fileToObject)(file); objFile.state = 'selected'; return objFile; }); // 默认全量上传 var uploadFiles = fileList; var discardFiles = []; if (total > limit) { // 全量上传总数会超过 limit 但是 还有差额 uploadFiles = fileList.slice(0, less); discardFiles = fileList.slice(less); } var value = _this.state.value.concat(fileList); /* eslint-disable-next */ // @ts-expect-error 无法为“value”赋值,因为它是只读属性。 _this.state.value = value; if (autoUpload) { _this.uploadFiles(uploadFiles); } onSelect(uploadFiles, value); discardFiles.forEach(function (file) { // 丢弃的文件 var err = new Error(util_2.errorCode.EXCEED_LIMIT); err.code = util_2.errorCode.EXCEED_LIMIT; _this.onError(err, null, file); }); if (!autoUpload) { uploadFiles.forEach(function (file) { var isPassed = afterSelect(file); util_1.func.promiseCall(isPassed, util_1.func.noop, function (error) { _this.onError(error, null, file); }); }); _this.onChange(value, uploadFiles); } }; _this.onDrop = function (files) { _this.onSelect(files); _this.props.onDrop(files); }; // 替换掉队列里面的文件 _this.replaceWithNewFile = function (old, current) { var newFile = (0, util_2.fileToObject)(current); newFile.state = 'selected'; var matchKey = old.uid !== undefined ? 'uid' : 'name'; var fileList = _this.state.value; for (var i = 0; i < fileList.length; i++) { var item = fileList[i]; if (item[matchKey] === old[matchKey]) { fileList.splice(i, 1, newFile); break; } } _this.uploadFiles([newFile]); return newFile; }; _this.onProgress = function (e, file) { //@ts-expect-error 无法为“uploading”赋值,因为它是只读属性。 _this.state.uploading = true; var value = _this.state.value; var targetItem = (0, util_2.getFileItem)(file, value); if (!targetItem) { return; } Object.assign(targetItem, { state: 'uploading', percent: e.percent, }); _this.setState({ value: value, }); _this.props.onProgress(value, targetItem); }; _this.onSuccess = function (response, file) { var formatter = _this.props.formatter; if (formatter) { response = formatter(response, file); } try { if (typeof response === 'string') { response = JSON.parse(response); } } catch (e) { e.code = util_2.errorCode.RESPONSE_FAIL; return _this.onError(e, response, file); } if (response.success === false) { var err = new Error(response.message || util_2.errorCode.RESPONSE_FAIL); err.code = util_2.errorCode.RESPONSE_FAIL; return _this.onError(err, response, file); } var value = _this.state.value; var targetItem = (0, util_2.getFileItem)(file, value); if (!targetItem) { return; } Object.assign(targetItem, { state: 'done', response: response, url: response.url, downloadURL: response.downloadURL || response.url, // 下载地址 (可选) }); if (!_this.props.useDataURL) { targetItem.imgURL = response.imgURL || response.url; // 缩略图地址 (可选) } _this.updateUploadingState(); _this.onChange(value, targetItem); _this.props.onSuccess(targetItem, value); }; _this.onError = function (err, response, file) { var value = _this.state.value; var targetItem = (0, util_2.getFileItem)(file, value); if (!targetItem) { return; } Object.assign(targetItem, { state: 'error', error: err, response: response, }); _this.updateUploadingState(); _this.onChange(value, targetItem); _this.props.onError(targetItem, value); }; /** * 删除文件 */ _this.removeFile = function (file) { file.state = 'removed'; _this.uploaderRef.abort(file); // 删除组件时调用组件的 `abort` 方法中断上传 var fileList = _this.state.value; var targetItem = (0, util_2.getFileItem)(file, fileList); var index = fileList.indexOf(targetItem); if (index !== -1) { fileList.splice(index, 1); _this.onChange(fileList, targetItem); } }; _this.updateUploadingState = function () { var inProgress = _this.state.value.some(function (i) { return i.state === 'uploading'; }); if (!inProgress) { // @ts-expect-error 无法为“uploading”赋值,因为它是只读属性。 _this.state.uploading = false; } }; /** * 取消上传 */ _this.abort = function (file) { var fileList = _this.state.value; var targetItem = (0, util_2.getFileItem)(file, fileList); var index = fileList.indexOf(targetItem); if (index !== -1) { fileList.splice(index, 1); _this.onChange(fileList, targetItem); } _this.uploaderRef.abort(file); // 取消上传时调用组件的 `abort` 方法中断上传 }; _this.onChange = function (value, file) { _this.setState({ value: value, }); _this.props.onChange(value, file); }; var value; if ('value' in props) { value = props.value; } else { value = props.defaultValue; } _this.state = { value: !Array.isArray(value) ? [] : value, uploading: false, }; return _this; } Upload.getDerivedStateFromProps = function (nextProps, prevState) { // 上传中不允许做受控修改 if ('value' in nextProps && nextProps.value !== prevState.value && !prevState.uploading) { return { value: !Array.isArray(nextProps.value) ? [] : nextProps.value, }; } return null; }; /** * 对外暴露 API, 添加文件 */ Upload.prototype.selectFiles = function (files) { var filesArr = files.length ? Array.prototype.slice.call(files) : [files]; this.onSelect(filesArr); }; Upload.prototype.uploadFiles = function (files) { // NOTE: drag 上传,当鼠标松开的时候回执行 onDrop,但此时 onChange 还没出发所以 value=[], 必须提前标识上传中 // @ts-expect-error 无法为“uploading”赋值,因为它是只读属性。 this.state.uploading = true; var fileList = files .filter(function (file) { if (file.state === 'selected' || file.state === 'error') { file.state = 'uploading'; return true; } return false; }) .map(function (file) { return file.originFileObj; }); fileList.length && this.uploaderRef.startUpload(fileList); }; /** * 对外暴露 api,控制文件上传 */ Upload.prototype.startUpload = function () { this.uploadFiles(this.state.value); }; Upload.prototype.replaceFiles = function (old, current) { var targetItem = (0, util_2.getFileItem)(old, this.state.value); if (!targetItem) { return; } current.uid = old.uid; targetItem.originFileObj = current; }; Upload.prototype.isUploading = function () { return this.state.uploading; }; Upload.prototype.render = function () { var _a, _b, _c, _d; var _e = this.props, listType = _e.listType, prefix = _e.prefix, dragable = _e.dragable, shape = _e.shape, className = _e.className, style = _e.style, useDataURL = _e.useDataURL, disabled = _e.disabled, limit = _e.limit, closable = _e.closable, beforeUpload = _e.beforeUpload, readonly = _e.readonly, onRemove = _e.onRemove, onCancel = _e.onCancel, onPreview = _e.onPreview, list = _e.list, extraRender = _e.extraRender, progressProps = _e.progressProps, rtl = _e.rtl, isPreview = _e.isPreview, renderPreview = _e.renderPreview, name = _e.name, _f = _e.fileKeyName, fileKeyName = _f === void 0 ? name : _f, fileNameRender = _e.fileNameRender, actionRender = _e.actionRender, previewOnFileName = _e.previewOnFileName, itemRender = _e.itemRender, others = tslib_1.__rest(_e, ["listType", "prefix", "dragable", "shape", "className", "style", "useDataURL", "disabled", "limit", "closable", "beforeUpload", "readonly", "onRemove", "onCancel", "onPreview", "list", "extraRender", "progressProps", "rtl", "isPreview", "renderPreview", "name", "fileKeyName", "fileNameRender", "actionRender", "previewOnFileName", "itemRender"]); var cls = (0, classnames_1.default)((_a = {}, _a["".concat(prefix, "upload")] = true, _a["".concat(prefix, "upload-dragable")] = dragable, _a["".concat(prefix, "disabled")] = disabled, _a["".concat(prefix, "readonly")] = readonly, _a[className] = className, _a)); var isExceedLimit = this.state.value.length >= limit; var innerCls = (0, classnames_1.default)((_b = {}, _b["".concat(prefix, "upload-inner")] = true, _b["".concat(prefix, "hidden")] = isExceedLimit, _b)); var children = this.props.children; if (shape === 'card') { var cardCls = (0, classnames_1.default)((_c = {}, _c["".concat(prefix, "upload-card")] = true, _c["".concat(prefix, "disabled")] = disabled, _c)); children = (react_1.default.createElement("div", { className: cardCls }, react_1.default.createElement(icon_1.default, { size: "large", type: "add", className: "".concat(prefix, "upload-add-icon") }), react_1.default.createElement("div", { tabIndex: 0, role: "button", className: "".concat(prefix, "upload-text") }, children))); } if (isPreview) { if (typeof renderPreview === 'function') { var previewCls = (0, classnames_1.default)((_d = {}, _d["".concat(prefix, "form-preview")] = true, _d[className] = !!className, _d)); return (react_1.default.createElement("div", { style: style, className: previewCls }, renderPreview(this.state.value, this.props))); } if (listType) { return (react_1.default.createElement(list_1.default, { isPreview: true, listType: listType, style: style, className: className, value: this.state.value, onPreview: onPreview })); } return null; } // disabled 状态下把 remove 函数替换成禁止 remove 的函数 var onRemoveFunc = disabled ? util_1.func.prevent : onRemove; var otherAttributes = util_1.obj.pickAttrsWith(this.props, 'data-'); return (react_1.default.createElement("div", tslib_1.__assign({ className: cls, style: style }, otherAttributes), react_1.default.createElement(index_1.default, tslib_1.__assign({}, others, { name: fileKeyName, beforeUpload: beforeUpload, dragable: dragable, disabled: disabled || isExceedLimit, className: innerCls, onSelect: this.onSelect, onDrop: this.onDrop, onProgress: this.onProgress, onSuccess: this.onSuccess, onError: this.onError, ref: this.saveUploaderRef }), children), (listType && listType !== 'none') || list ? (react_1.default.createElement(list_1.default, { useDataURL: useDataURL, fileNameRender: fileNameRender, actionRender: actionRender, uploader: this, listType: listType, value: this.state.value, closable: closable, onRemove: onRemoveFunc, progressProps: progressProps, onCancel: onCancel, onPreview: onPreview, extraRender: extraRender, rtl: rtl, previewOnFileName: previewOnFileName, itemRender: itemRender })) : null)); }; Upload.displayName = 'Upload'; Upload.propTypes = tslib_1.__assign(tslib_1.__assign(tslib_1.__assign({}, html5_uploader_1.default.propTypes), list_1.default.propTypes), { prefix: prop_types_1.default.string.isRequired, action: prop_types_1.default.string, value: prop_types_1.default.array, defaultValue: prop_types_1.default.array, shape: prop_types_1.default.oneOf(['card']), listType: prop_types_1.default.oneOf(['text', 'image', 'card', 'none']), list: prop_types_1.default.any, name: prop_types_1.default.string, data: prop_types_1.default.oneOfType([prop_types_1.default.object, prop_types_1.default.func]), formatter: prop_types_1.default.func, limit: prop_types_1.default.number, timeout: prop_types_1.default.number, dragable: prop_types_1.default.bool, closable: prop_types_1.default.bool, useDataURL: prop_types_1.default.bool, disabled: prop_types_1.default.bool, onSelect: prop_types_1.default.func, onProgress: prop_types_1.default.func, onChange: prop_types_1.default.func, onSuccess: prop_types_1.default.func, afterSelect: prop_types_1.default.func, onRemove: prop_types_1.default.func, onError: prop_types_1.default.func, beforeUpload: prop_types_1.default.func, onDrop: prop_types_1.default.func, className: prop_types_1.default.string, style: prop_types_1.default.object, children: prop_types_1.default.node, autoUpload: prop_types_1.default.bool, request: prop_types_1.default.func, progressProps: prop_types_1.default.object, rtl: prop_types_1.default.bool, isPreview: prop_types_1.default.bool, renderPreview: prop_types_1.default.func, fileKeyName: prop_types_1.default.string, fileNameRender: prop_types_1.default.func, actionRender: prop_types_1.default.func, previewOnFileName: prop_types_1.default.bool }); Upload.defaultProps = tslib_1.__assign(tslib_1.__assign({}, html5_uploader_1.default.defaultProps), { prefix: 'next-', limit: Infinity, autoUpload: true, closable: true, onSelect: noop, onProgress: noop, onChange: noop, onSuccess: noop, onRemove: noop, onError: noop, onDrop: noop, beforeUpload: noop, afterSelect: noop, previewOnFileName: false }); return Upload; }(base_1.default)); exports.default = (0, react_lifecycles_compat_1.polyfill)(Upload);