UNPKG

gui-one-nutui-react-taro

Version:

京东风格的轻量级移动端 React 组件库,支持一套代码生成 H5 和小程序

530 lines (529 loc) 22.2 kB
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray"; import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties"; import _slicedToArray from "@babel/runtime/helpers/slicedToArray"; import _createClass from "@babel/runtime/helpers/createClass"; import _classCallCheck from "@babel/runtime/helpers/classCallCheck"; import _defineProperty from "@babel/runtime/helpers/defineProperty"; var _excluded = ["children", "uploadIcon", "uploadIconSize", "name", "defaultFileList", "listType", "disabled", "url", "defaultImg", "headers", "timeout", "method", "xhrState", "data", "isPreview", "isDeletable", "maximum", "maximize", "className", "autoUpload", "sizeType", "sourceType", "onStart", "onRemove", "onChange", "onFileItemClick", "onProgress", "onSuccess", "onUpdate", "onFailure", "onOversize", "onBeforeUpload", "onBeforeXhrUpload", "onBeforeDelete"]; function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; } import React__default, { useState, useEffect, useImperativeHandle } from 'react'; import classNames from 'classnames'; import { I as Icon } from './icon.taro-1d0d4fb7.js'; import { B as Button } from './button.taro-4ce133b9.js'; import { P as Progress } from './progress.taro-623bc807.js'; import Taro from '@tarojs/taro'; import { c as cn } from './bem-893ad28d.js'; import { u as useConfig } from './configprovider.taro-6c7b3056.js'; import { C as ComponentDefaults } from './typings-1c5f2628.js'; var UploadOptions = /*#__PURE__*/_createClass(function UploadOptions() { _classCallCheck(this, UploadOptions); _defineProperty(this, "url", ''); _defineProperty(this, "name", 'file'); _defineProperty(this, "fileType", 'image'); _defineProperty(this, "formData", void 0); _defineProperty(this, "sourceFile", void 0); _defineProperty(this, "method", 'post'); _defineProperty(this, "xhrState", 200); _defineProperty(this, "timeout", 30 * 1000); _defineProperty(this, "headers", {}); _defineProperty(this, "withCredentials", false); _defineProperty(this, "onStart", void 0); _defineProperty(this, "taroFilePath", void 0); _defineProperty(this, "onProgress", void 0); _defineProperty(this, "onSuccess", void 0); _defineProperty(this, "onFailure", void 0); _defineProperty(this, "beforeXhrUpload", void 0); }); var Upload = /*#__PURE__*/function () { function Upload(options) { _classCallCheck(this, Upload); _defineProperty(this, "options", void 0); this.options = options; } _createClass(Upload, [{ key: "upload", value: function upload() { var options = this.options; var xhr = new XMLHttpRequest(); xhr.timeout = options.timeout; if (xhr.upload) { var _options$onStart; xhr.upload.addEventListener('progress', function (e) { var _options$onProgress; (_options$onProgress = options.onProgress) === null || _options$onProgress === void 0 ? void 0 : _options$onProgress.call(options, e, options); }, false); xhr.onreadystatechange = function () { if (xhr.readyState === 4) { if (xhr.status === options.xhrState) { var _options$onSuccess; (_options$onSuccess = options.onSuccess) === null || _options$onSuccess === void 0 ? void 0 : _options$onSuccess.call(options, xhr.responseText, options); } else { var _options$onFailure; (_options$onFailure = options.onFailure) === null || _options$onFailure === void 0 ? void 0 : _options$onFailure.call(options, xhr.responseText, options); } } }; xhr.withCredentials = options.withCredentials; xhr.open(options.method, options.url, true); // headers for (var _i = 0, _Object$entries = Object.entries(options.headers); _i < _Object$entries.length; _i++) { var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2), key = _Object$entries$_i[0], value = _Object$entries$_i[1]; xhr.setRequestHeader(key, value); } (_options$onStart = options.onStart) === null || _options$onStart === void 0 ? void 0 : _options$onStart.call(options, options); if (options.beforeXhrUpload) { options.beforeXhrUpload(xhr, options); } else { xhr.send(options.formData); } } else { console.warn('浏览器不支持 XMLHttpRequest'); } } }, { key: "uploadTaro", value: function uploadTaro(uploadFile, env) { var options = this.options; if (env === 'WEB') { this.upload(); } else if (options.beforeXhrUpload) { options.beforeXhrUpload(uploadFile, options); } else { var _options$onStart2; var uploadTask = uploadFile({ url: options.url, filePath: options.taroFilePath, fileType: options.fileType, header: _objectSpread({ 'Content-Type': 'multipart/form-data' }, options.headers), formData: options.formData, name: options.name, success: function success(response) { if (options.xhrState == response.statusCode) { var _options$onSuccess2; (_options$onSuccess2 = options.onSuccess) === null || _options$onSuccess2 === void 0 ? void 0 : _options$onSuccess2.call(options, response, options); } else { var _options$onFailure2; (_options$onFailure2 = options.onFailure) === null || _options$onFailure2 === void 0 ? void 0 : _options$onFailure2.call(options, response, options); } }, fail: function fail(e) { var _options$onFailure3; (_options$onFailure3 = options.onFailure) === null || _options$onFailure3 === void 0 ? void 0 : _options$onFailure3.call(options, e, options); } }); (_options$onStart2 = options.onStart) === null || _options$onStart2 === void 0 ? void 0 : _options$onStart2.call(options, options); uploadTask.progress(function (res) { var _options$onProgress2; (_options$onProgress2 = options.onProgress) === null || _options$onProgress2 === void 0 ? void 0 : _options$onProgress2.call(options, res, options); // console.log('上传进度', res.progress); // console.log('已经上传的数据长度', res.totalBytesSent); // console.log('预期需要上传的数据总长度', res.totalBytesExpectedToSend); }); // uploadTask.abort(); // 取消上传任务 } } }]); return Upload; }(); var defaultProps = _objectSpread(_objectSpread({}, ComponentDefaults), {}, { url: '', maximum: 9, sizeType: ['original', 'compressed'], sourceType: ['album', 'camera'], uploadIcon: 'photograph', uploadIconSize: '', listType: 'picture', name: 'file', disabled: false, autoUpload: true, maximize: Number.MAX_VALUE, data: {}, headers: {}, method: 'post', defaultImg: '', xhrState: 200, timeout: 1000 * 30, isPreview: true, isDeletable: true, onBeforeDelete: function onBeforeDelete(file, files) { return true; } }); var FileItem = /*#__PURE__*/_createClass(function FileItem() { _classCallCheck(this, FileItem); _defineProperty(this, "status", 'ready'); _defineProperty(this, "message", '准备中..'); _defineProperty(this, "uid", new Date().getTime().toString()); _defineProperty(this, "name", void 0); _defineProperty(this, "url", void 0); _defineProperty(this, "type", void 0); _defineProperty(this, "path", void 0); _defineProperty(this, "percentage", 0); _defineProperty(this, "formData", {}); }); var InternalUploader = function InternalUploader(props, ref) { var _useConfig = useConfig(), locale = _useConfig.locale; var _defaultProps$props = _objectSpread(_objectSpread({}, defaultProps), props), children = _defaultProps$props.children, uploadIcon = _defaultProps$props.uploadIcon, uploadIconSize = _defaultProps$props.uploadIconSize, name = _defaultProps$props.name, defaultFileList = _defaultProps$props.defaultFileList, listType = _defaultProps$props.listType, disabled = _defaultProps$props.disabled, url = _defaultProps$props.url, defaultImg = _defaultProps$props.defaultImg, headers = _defaultProps$props.headers, timeout = _defaultProps$props.timeout, method = _defaultProps$props.method, xhrState = _defaultProps$props.xhrState, data = _defaultProps$props.data, isPreview = _defaultProps$props.isPreview, isDeletable = _defaultProps$props.isDeletable, maximum = _defaultProps$props.maximum, maximize = _defaultProps$props.maximize, className = _defaultProps$props.className, autoUpload = _defaultProps$props.autoUpload, sizeType = _defaultProps$props.sizeType, sourceType = _defaultProps$props.sourceType, onStart = _defaultProps$props.onStart, onRemove = _defaultProps$props.onRemove, onChange = _defaultProps$props.onChange, onFileItemClick = _defaultProps$props.onFileItemClick, onProgress = _defaultProps$props.onProgress, onSuccess = _defaultProps$props.onSuccess, onUpdate = _defaultProps$props.onUpdate, onFailure = _defaultProps$props.onFailure, onOversize = _defaultProps$props.onOversize, onBeforeUpload = _defaultProps$props.onBeforeUpload, onBeforeXhrUpload = _defaultProps$props.onBeforeXhrUpload, onBeforeDelete = _defaultProps$props.onBeforeDelete, restProps = _objectWithoutProperties(_defaultProps$props, _excluded); var _useState = useState([]), _useState2 = _slicedToArray(_useState, 2), fileList = _useState2[0], setFileList = _useState2[1]; var _useState3 = useState([]), _useState4 = _slicedToArray(_useState3, 2), uploadQueue = _useState4[0], setUploadQueue = _useState4[1]; useEffect(function () { if (defaultFileList) { setFileList(defaultFileList); } }, [defaultFileList]); var b = cn('uploader'); var classes = classNames(className, b('')); useImperativeHandle(ref, function () { return { submit: function submit() { Promise.all(uploadQueue).then(function (res) { res.forEach(function (i) { return i.uploadTaro(Taro.uploadFile, Taro.getEnv()); }); }); } }; }); var clearUploadQueue = function clearUploadQueue() { var index = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : -1; if (index > -1) { uploadQueue.splice(index, 1); setUploadQueue(uploadQueue); } else { setUploadQueue([]); } }; var chooseImage = function chooseImage() { if (disabled) { return; } Taro.chooseImage({ // 选择数量 count: maximum * 1 - fileList.length, // 可以指定是原图还是压缩图,默认二者都有 sizeType: sizeType, sourceType: sourceType, success: onChangeFn }); }; var executeUpload = function executeUpload(fileItem, index) { var uploadOption = new UploadOptions(); uploadOption.name = name; uploadOption.url = url; uploadOption.fileType = fileItem.type; uploadOption.formData = fileItem.formData; uploadOption.timeout = timeout * 1; uploadOption.method = method; uploadOption.xhrState = xhrState; uploadOption.headers = headers; uploadOption.taroFilePath = fileItem.path; uploadOption.beforeXhrUpload = onBeforeXhrUpload; uploadOption.onStart = function (option) { clearUploadQueue(index); setFileList(function (fileList) { fileList.map(function (item) { if (item.uid === fileItem.uid) { item.status = 'ready'; item.message = locale.uploader.readyUpload; } }); return _toConsumableArray(fileList); }); onStart && onStart(option); }; uploadOption.onProgress = function (e, option) { setFileList(function (fileList) { fileList.map(function (item) { if (item.uid === fileItem.uid) { item.status = 'uploading'; item.message = locale.uploader.uploading; item.percentage = e.progress; onProgress && onProgress({ e: e, option: option, percentage: item.percentage }); } }); return _toConsumableArray(fileList); }); }; uploadOption.onSuccess = function (responseText, option) { setFileList(function (fileList) { onUpdate && onUpdate(fileList); fileList.map(function (item) { if (item.uid === fileItem.uid) { item.status = 'success'; item.message = locale.uploader.success; } }); return _toConsumableArray(fileList); }); onSuccess && onSuccess({ responseText: responseText, option: option }); }; uploadOption.onFailure = function (responseText, option) { setFileList(function (fileList) { fileList.map(function (item) { if (item.uid === fileItem.uid) { item.status = 'error'; item.message = locale.uploader.error; } }); return _toConsumableArray(fileList); }); onFailure && onFailure({ responseText: responseText, option: option }); }; var task = new Upload(uploadOption); if (props.autoUpload) { task.uploadTaro(Taro.uploadFile, Taro.getEnv()); } else { uploadQueue.push(new Promise(function (resolve, reject) { resolve(task); })); setUploadQueue(uploadQueue); } }; var readFile = function readFile(files) { var imgReg = /\.(png|jpeg|jpg|webp|gif)$/i; files.forEach(function (file, index) { console.log('file', file); var fileType = file.type; var fileItem = new FileItem(); if (!fileType && imgReg.test(file.path)) { fileType = 'image'; } fileItem.path = file.path; fileItem.name = file.path; fileItem.status = 'ready'; fileItem.message = locale.uploader.readyUpload; fileItem.type = fileType; if (Taro.getEnv() == 'WEB') { var _file$originalFileObj, _file$originalFileObj2; var formData = new FormData(); for (var _i2 = 0, _Object$entries2 = Object.entries(data); _i2 < _Object$entries2.length; _i2++) { var _Object$entries2$_i = _slicedToArray(_Object$entries2[_i2], 2), key = _Object$entries2$_i[0], value = _Object$entries2$_i[1]; formData.append(key, value); } formData.append(name, file.originalFileObj); fileItem.name = (_file$originalFileObj = file.originalFileObj) === null || _file$originalFileObj === void 0 ? void 0 : _file$originalFileObj.name; fileItem.type = (_file$originalFileObj2 = file.originalFileObj) === null || _file$originalFileObj2 === void 0 ? void 0 : _file$originalFileObj2.type; fileItem.formData = formData; } else { fileItem.formData = data; } if (isPreview) { fileItem.url = file.path; } fileList.push(fileItem); setFileList(_toConsumableArray(fileList)); executeUpload(fileItem, index); }); }; var filterFiles = function filterFiles(files) { var maximum = props.maximum * 1; var maximize = props.maximize * 1; var oversizes = new Array(); var filterFile = files.filter(function (file) { if (file.size > maximize) { oversizes.push(file); return false; } return true; }); if (oversizes.length) { onOversize && onOversize(files); } var currentFileLength = filterFile.length + fileList.length; if (currentFileLength > maximum) { filterFile.splice(filterFile.length - (currentFileLength - maximum)); } return filterFile; }; var onDelete = function onDelete(file, index) { clearUploadQueue(index); if (onBeforeDelete && onBeforeDelete(file, fileList)) { fileList.splice(index, 1); onRemove && onRemove(file, fileList); setFileList(_toConsumableArray(fileList)); } else { console.log(locale.uploader.deleteWord); } }; var onChangeFn = function onChangeFn(res) { // 返回选定照片的本地文件路径列表,tempFilePath可以作为img标签的src属性显示图片 var tempFiles = res.tempFiles; if (onBeforeUpload) { onBeforeUpload(tempFiles).then(function (f) { var _files = filterFiles(f); readFile(_files); }); } else { var _files = filterFiles(tempFiles); readFile(_files); } onChange && onChange({ fileList: fileList }); }; var handleItemClick = function handleItemClick(file) { onFileItemClick && onFileItemClick(file); }; return React__default.createElement("div", _objectSpread({ className: classes }, restProps), children && React__default.createElement("div", { className: "nut-uploader__slot" }, React__default.createElement(React__default.Fragment, null, children, maximum > fileList.length && React__default.createElement(Button, { className: "nut-uploader__input", onClick: chooseImage }))), fileList.length !== 0 && fileList.map(function (item, index) { return React__default.createElement("div", { className: "nut-uploader__preview ".concat(listType), key: item.uid }, listType == 'picture' && !children && React__default.createElement("div", { className: "nut-uploader__preview-img" }, item.status === 'ready' ? React__default.createElement("div", { className: "nut-uploader__preview__progress" }, React__default.createElement("div", { className: "nut-uploader__preview__progress__msg" }, item.message)) : item.status !== 'success' && React__default.createElement("div", { className: "nut-uploader__preview__progress" }, React__default.createElement(Icon, { classPrefix: props.iconClassPrefix, fontClassName: props.iconFontClassName, color: "#fff", name: "".concat(item.status == 'error' ? 'failure' : 'loading') }), React__default.createElement("div", { className: "nut-uploader__preview__progress__msg" }, item.message)), isDeletable && React__default.createElement(Icon, { classPrefix: props.iconClassPrefix, fontClassName: props.iconFontClassName, color: "rgba(0,0,0,0.6)", className: "close", name: "failure", onClick: function onClick() { return onDelete(item, index); } }), item.type.includes('image') ? React__default.createElement(React__default.Fragment, null, item.url && React__default.createElement("img", { className: "nut-uploader__preview-img__c", src: item.url, onClick: function onClick() { return handleItemClick(item); } })) : React__default.createElement(React__default.Fragment, null, defaultImg ? React__default.createElement("img", { className: "nut-uploader__preview-img__c", src: defaultImg, onClick: function onClick() { return handleItemClick(item); } }) : React__default.createElement("div", { className: "nut-uploader__preview-img__file" }, React__default.createElement("div", { onClick: function onClick() { return handleItemClick(item); }, className: "nut-uploader__preview-img__file__name" }, React__default.createElement(Icon, { classPrefix: props.iconClassPrefix, fontClassName: props.iconFontClassName, color: "#808080", name: "link" }), "\xA0", item.name))), React__default.createElement("div", { className: "tips" }, item.name)), listType === 'list' && React__default.createElement("div", { className: "nut-uploader__preview-list" }, React__default.createElement("div", { className: "nut-uploader__preview-img__file__name ".concat(item.status), onClick: function onClick() { return handleItemClick(item); } }, React__default.createElement(Icon, { classPrefix: props.iconClassPrefix, fontClassName: props.iconFontClassName, name: "link" }), "\xA0", item.name), isDeletable && React__default.createElement(Icon, { classPrefix: props.iconClassPrefix, fontClassName: props.iconFontClassName, color: "#808080", className: "nut-uploader__preview-img__file__del", name: "del", onClick: function onClick() { return onDelete(item, index); } }), item.status === 'uploading' && React__default.createElement(Progress, { size: "small", percentage: item.percentage, strokeColor: "linear-gradient(270deg, rgba(18,126,255,1) 0%,rgba(32,147,255,1) 32.815625%,rgba(13,242,204,1) 100%)", showText: false }))); }), maximum > fileList.length && listType === 'picture' && !children && React__default.createElement("div", { className: "nut-uploader__upload ".concat(listType) }, React__default.createElement(Icon, { classPrefix: props.iconClassPrefix, fontClassName: props.iconFontClassName, size: uploadIconSize, color: "#808080", name: uploadIcon }), React__default.createElement(Button, { className: "nut-uploader__input", onClick: chooseImage }))); }; var Uploader = React__default.forwardRef(InternalUploader); Uploader.defaultProps = defaultProps; Uploader.displayName = 'NutUploader'; export { Uploader as U };