react-admin-kit
Version:
A react based UI components for admin system
154 lines (147 loc) • 5.65 kB
JavaScript
import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties";
var _excluded = ["multiple", "children", "onFinish", "errorHandle", "responseToFileList", "nameKey", "urlKey"];
import { Upload } from 'antd';
import { useContext, useEffect, useRef, useState } from 'react';
import { flushSync } from 'react-dom';
import { FormUploadContext } from "../SettingProvider/context";
import { myMergeOptions } from "../utils";
import Omit from 'omit.js';
/**
* 给 file 对象赋上默认的 status: done
* initialValues 和 setFieldsValue 两种情况下的 file 对象需要带上 status, 否则表单收集不到.
* beforeUpload 为 false 的 file 对象也会进到 fileList, 它的 status 为空, 所以表单不收集
* @param files
*/
import { jsx as _jsx } from "react/jsx-runtime";
function withDefaultStatus() {
var files = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
var $files = files || [];
return $files.map(function (file) {
if (!file.status) {
file.status = 'done';
}
return file;
});
}
function FormUpload(props) {
// 全局默认设置
var setting = useContext(FormUploadContext) || {};
var safeProps = Omit(props, ['value', 'onChange']);
var mergedProps = myMergeOptions(setting, safeProps || {},
// 默认值放在这里,能合并对象类属性
{});
var _mergedProps$multiple = mergedProps.multiple,
multiple = _mergedProps$multiple === void 0 ? true : _mergedProps$multiple,
children = mergedProps.children,
onFinish = mergedProps.onFinish,
errorHandle = mergedProps.errorHandle,
responseToFileList = mergedProps.responseToFileList,
_mergedProps$nameKey = mergedProps.nameKey,
nameKey = _mergedProps$nameKey === void 0 ? 'name' : _mergedProps$nameKey,
_mergedProps$urlKey = mergedProps.urlKey,
urlKey = _mergedProps$urlKey === void 0 ? 'url' : _mergedProps$urlKey,
rest = _objectWithoutProperties(mergedProps, _excluded);
var value = props.value,
onChange = props.onChange;
/**
* 如果先前的 value 有值 [{name: '', url: ''}], 通过 setFieldsValue 设成空数组[]后, value 会变成 [undefined]
*/
var $value = value ? value.filter(Boolean).map(function (val) {
return _objectSpread(_objectSpread({}, val), {}, {
name: val[nameKey],
url: val[urlKey]
});
}) : value;
// 是否有调用父组件的 onChange 函数
var emitChangeRef = useRef(null);
var firstTimeRef = useRef(true);
var _useState = useState(withDefaultStatus($value)),
_useState2 = _slicedToArray(_useState, 2),
innerFileList = _useState2[0],
setInnerFileList = _useState2[1];
var _useState3 = useState(false),
_useState4 = _slicedToArray(_useState3, 2),
uploading = _useState4[0],
setUploading = _useState4[1];
/**
* FormUpload 组件的设计是内部维护自己的文件列表, 然后监听外部 value 属性的变化, 来达到近似受控组件的效果.
* 为什么说近似, 是因为有一个例外, 当上传的文件列表中有上传错误的文件时, 通过 props.onChnage 传给外面的文件与内部的文件不一致.
* 传给外面的文件都是上传成功的, 而内部上包含错误文件的.
* 就是这个例外需要两边不同步, 通过一个 emitChangeRef 来标记并阻止他们同步.
*/
useEffect(function () {
// 忽略第一次
if (firstTimeRef.current) {
firstTimeRef.current = false;
return;
}
/**
* 监听 value, 外部和内部同步. (emitChange 阻止的除外)
*/
if (!emitChangeRef.current) {
setInnerFileList(withDefaultStatus($value));
}
emitChangeRef.current = false;
}, [value]);
var handleOnChange = function handleOnChange(info) {
setUploading(true);
var fileList = _toConsumableArray(info.fileList);
var $fileList = fileList.map(function (file) {
/**
* 将后端的返回合并进file对象
*/
if (file.response) {
var res = file.response;
var resObj = responseToFileList ? responseToFileList(res) : {};
return _objectSpread(_objectSpread({}, file), resObj);
}
return file;
});
if (info.file.status === 'error') {
if (errorHandle) {
errorHandle(info.file.response || {});
}
}
flushSync(function () {
return setInnerFileList($fileList);
});
// beforeUpload为false的文件也会进到onChange里
if ($fileList.every(function (file) {
return file.status !== 'uploading';
})) {
setUploading(false);
emitChangeRef.current = true;
var successFiles = $fileList.filter(function (file) {
return ['done', 'success'].includes(file.status);
});
if (onChange) {
onChange(successFiles);
}
if (onFinish) onFinish(successFiles);
}
};
var renderChildren = function renderChildren() {
if (children && typeof children === 'function') {
return children({
loading: uploading
});
}
return children;
};
return /*#__PURE__*/_jsx(Upload, _objectSpread(_objectSpread({
multiple: multiple,
fileList: innerFileList,
onChange: handleOnChange
}, rest), {}, {
children: renderChildren()
}));
}
export default FormUpload;
// 用于生成api文档
/* istanbul ignore next */
export var FormUploadType = function FormUploadType() {
return null;
};