409 lines
17 KiB
JavaScript
409 lines
17 KiB
JavaScript
import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
|
|
import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
|
|
import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties";
|
|
import _regeneratorRuntime from "@babel/runtime/helpers/esm/regeneratorRuntime";
|
|
import _asyncToGenerator from "@babel/runtime/helpers/esm/asyncToGenerator";
|
|
import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
|
|
var _excluded = ["onTableChange", "maxLength", "formItemProps", "recordCreatorProps", "rowKey", "controlled", "defaultValue", "onChange", "editableFormRef"],
|
|
_excluded2 = ["record", "position", "creatorButtonText", "newRecordType", "parentKey", "style"];
|
|
import { PlusOutlined } from '@ant-design/icons';
|
|
import ProForm, { ProFormDependency } from '@ant-design/pro-form';
|
|
import { useIntl } from '@ant-design/pro-provider';
|
|
import { isDeepEqualReact, runFunction, stringify, useRefFunction } from '@ant-design/pro-utils';
|
|
import { Button, Form } from 'antd';
|
|
import useMergedState from "rc-util/es/hooks/useMergedState";
|
|
import get from "rc-util/es/utils/get";
|
|
import set from "rc-util/es/utils/set";
|
|
import React, { useContext, useEffect, useImperativeHandle, useMemo, useRef } from 'react';
|
|
import ProTable from "../../Table";
|
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
import { Fragment as _Fragment } from "react/jsx-runtime";
|
|
var EditableTableActionContext = /*#__PURE__*/React.createContext(undefined);
|
|
|
|
/** 可编辑表格的按钮 */
|
|
function RecordCreator(props) {
|
|
var children = props.children,
|
|
record = props.record,
|
|
position = props.position,
|
|
newRecordType = props.newRecordType,
|
|
parentKey = props.parentKey;
|
|
var actionRef = useContext(EditableTableActionContext);
|
|
return /*#__PURE__*/React.cloneElement(children, _objectSpread(_objectSpread({}, children.props), {}, {
|
|
onClick: function () {
|
|
var _onClick = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(e) {
|
|
var _children$props$onCli, _children$props, _actionRef$current;
|
|
var isOk;
|
|
return _regeneratorRuntime().wrap(function _callee$(_context) {
|
|
while (1) switch (_context.prev = _context.next) {
|
|
case 0:
|
|
_context.next = 2;
|
|
return (_children$props$onCli = (_children$props = children.props).onClick) === null || _children$props$onCli === void 0 ? void 0 : _children$props$onCli.call(_children$props, e);
|
|
case 2:
|
|
isOk = _context.sent;
|
|
if (!(isOk === false)) {
|
|
_context.next = 5;
|
|
break;
|
|
}
|
|
return _context.abrupt("return");
|
|
case 5:
|
|
actionRef === null || actionRef === void 0 || (_actionRef$current = actionRef.current) === null || _actionRef$current === void 0 || _actionRef$current.addEditRecord(record, {
|
|
position: position,
|
|
newRecordType: newRecordType,
|
|
parentKey: parentKey
|
|
});
|
|
case 6:
|
|
case "end":
|
|
return _context.stop();
|
|
}
|
|
}, _callee);
|
|
}));
|
|
function onClick(_x) {
|
|
return _onClick.apply(this, arguments);
|
|
}
|
|
return onClick;
|
|
}()
|
|
}));
|
|
}
|
|
|
|
/**
|
|
* 可以直接放到 Form 中的可编辑表格
|
|
* A React component that is used to create a table.
|
|
* @param props
|
|
*/
|
|
function EditableTable(props) {
|
|
var _props$editable2, _props$editable4;
|
|
var intl = useIntl();
|
|
var onTableChange = props.onTableChange,
|
|
maxLength = props.maxLength,
|
|
formItemProps = props.formItemProps,
|
|
recordCreatorProps = props.recordCreatorProps,
|
|
rowKey = props.rowKey,
|
|
controlled = props.controlled,
|
|
defaultValue = props.defaultValue,
|
|
onChange = props.onChange,
|
|
editableFormRef = props.editableFormRef,
|
|
rest = _objectWithoutProperties(props, _excluded);
|
|
var preData = useRef(undefined);
|
|
var actionRef = useRef();
|
|
var formRef = useRef();
|
|
|
|
// 设置 ref
|
|
useImperativeHandle(rest.actionRef, function () {
|
|
return actionRef.current;
|
|
}, [actionRef.current]);
|
|
var _useMergedState = useMergedState(function () {
|
|
return props.value || defaultValue || [];
|
|
}, {
|
|
value: props.value,
|
|
onChange: props.onChange
|
|
}),
|
|
_useMergedState2 = _slicedToArray(_useMergedState, 2),
|
|
value = _useMergedState2[0],
|
|
setValue = _useMergedState2[1];
|
|
var getRowKey = React.useMemo(function () {
|
|
if (typeof rowKey === 'function') {
|
|
return rowKey;
|
|
}
|
|
return function (record, index) {
|
|
return record[rowKey] || index;
|
|
};
|
|
}, [rowKey]);
|
|
|
|
/**
|
|
* 根据不同的情况返回不同的 rowKey
|
|
* @param finlayRowKey
|
|
* @returns string | number
|
|
*/
|
|
var coverRowKey = useRefFunction(function (finlayRowKey) {
|
|
/**
|
|
* 如果是 prop.name 的模式,就需要把行号转化成具体的rowKey。
|
|
*/
|
|
if (typeof finlayRowKey === 'number' && !props.name) {
|
|
if (finlayRowKey >= value.length) return finlayRowKey;
|
|
var rowData = value && value[finlayRowKey];
|
|
return getRowKey === null || getRowKey === void 0 ? void 0 : getRowKey(rowData, finlayRowKey);
|
|
}
|
|
|
|
/**
|
|
* 如果是 prop.name 的模式,就直接返回行号
|
|
*/
|
|
if ((typeof finlayRowKey === 'string' || finlayRowKey >= value.length) && props.name) {
|
|
var _rowIndex = value.findIndex(function (item, index) {
|
|
var _getRowKey;
|
|
return (getRowKey === null || getRowKey === void 0 || (_getRowKey = getRowKey(item, index)) === null || _getRowKey === void 0 ? void 0 : _getRowKey.toString()) === (finlayRowKey === null || finlayRowKey === void 0 ? void 0 : finlayRowKey.toString());
|
|
});
|
|
if (_rowIndex !== -1) return _rowIndex;
|
|
}
|
|
return finlayRowKey;
|
|
});
|
|
|
|
// 设置 editableFormRef
|
|
useImperativeHandle(editableFormRef, function () {
|
|
/**
|
|
* 获取一行数据的
|
|
* @param rowIndex
|
|
* @returns T | undefined
|
|
*/
|
|
var getRowData = function getRowData(rowIndex) {
|
|
var _finlayRowKey$toStrin, _formRef$current;
|
|
if (rowIndex == undefined) {
|
|
throw new Error('rowIndex is required');
|
|
}
|
|
var finlayRowKey = coverRowKey(rowIndex);
|
|
var rowKeyName = [props.name, (_finlayRowKey$toStrin = finlayRowKey === null || finlayRowKey === void 0 ? void 0 : finlayRowKey.toString()) !== null && _finlayRowKey$toStrin !== void 0 ? _finlayRowKey$toStrin : ''].flat(1).filter(Boolean);
|
|
return (_formRef$current = formRef.current) === null || _formRef$current === void 0 ? void 0 : _formRef$current.getFieldValue(rowKeyName);
|
|
};
|
|
|
|
/**
|
|
* 获取整个 table 的数据
|
|
* @returns T[] | undefined
|
|
*/
|
|
var getRowsData = function getRowsData() {
|
|
var _formRef$current3;
|
|
var rowKeyName = [props.name].flat(1).filter(Boolean);
|
|
if (Array.isArray(rowKeyName) && rowKeyName.length === 0) {
|
|
var _formRef$current2;
|
|
var rowData = (_formRef$current2 = formRef.current) === null || _formRef$current2 === void 0 ? void 0 : _formRef$current2.getFieldsValue();
|
|
if (Array.isArray(rowData)) return rowData;
|
|
return Object.keys(rowData).map(function (key) {
|
|
return rowData[key];
|
|
});
|
|
}
|
|
return (_formRef$current3 = formRef.current) === null || _formRef$current3 === void 0 ? void 0 : _formRef$current3.getFieldValue(rowKeyName);
|
|
};
|
|
return _objectSpread(_objectSpread({}, formRef.current), {}, {
|
|
getRowData: getRowData,
|
|
getRowsData: getRowsData,
|
|
/**
|
|
* 设置一行的数据,会将数据进行简单的 merge
|
|
* @param rowIndex
|
|
* @param data
|
|
* @returns void
|
|
*/
|
|
setRowData: function setRowData(rowIndex, data) {
|
|
var _finlayRowKey$toStrin2, _formRef$current4;
|
|
if (rowIndex == undefined) {
|
|
throw new Error('rowIndex is required');
|
|
}
|
|
var finlayRowKey = coverRowKey(rowIndex);
|
|
var rowKeyName = [props.name, (_finlayRowKey$toStrin2 = finlayRowKey === null || finlayRowKey === void 0 ? void 0 : finlayRowKey.toString()) !== null && _finlayRowKey$toStrin2 !== void 0 ? _finlayRowKey$toStrin2 : ''].flat(1).filter(Boolean);
|
|
var newRowData = Object.assign({}, _objectSpread(_objectSpread({}, getRowData(rowIndex)), data || {}));
|
|
var updateValues = set({}, rowKeyName, newRowData);
|
|
(_formRef$current4 = formRef.current) === null || _formRef$current4 === void 0 || _formRef$current4.setFieldsValue(updateValues);
|
|
return true;
|
|
}
|
|
});
|
|
}, [coverRowKey, props.name, formRef.current]);
|
|
useEffect(function () {
|
|
if (!props.controlled) return;
|
|
(value || []).forEach(function (current, index) {
|
|
var _formRef$current5;
|
|
(_formRef$current5 = formRef.current) === null || _formRef$current5 === void 0 || _formRef$current5.setFieldsValue(_defineProperty({}, "".concat(getRowKey(current, index)), current));
|
|
}, {});
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, [stringify(value), props.controlled]);
|
|
useEffect(function () {
|
|
if (props.name) {
|
|
var _props$editable;
|
|
formRef.current = props === null || props === void 0 || (_props$editable = props.editable) === null || _props$editable === void 0 ? void 0 : _props$editable.form;
|
|
}
|
|
}, [(_props$editable2 = props.editable) === null || _props$editable2 === void 0 ? void 0 : _props$editable2.form, props.name]);
|
|
var _ref = recordCreatorProps || {},
|
|
record = _ref.record,
|
|
position = _ref.position,
|
|
creatorButtonText = _ref.creatorButtonText,
|
|
newRecordType = _ref.newRecordType,
|
|
parentKey = _ref.parentKey,
|
|
style = _ref.style,
|
|
restButtonProps = _objectWithoutProperties(_ref, _excluded2);
|
|
var isTop = position === 'top';
|
|
var creatorButtonDom = useMemo(function () {
|
|
if (typeof maxLength === 'number' && maxLength <= (value === null || value === void 0 ? void 0 : value.length)) {
|
|
return false;
|
|
}
|
|
return recordCreatorProps !== false && /*#__PURE__*/_jsx(RecordCreator, {
|
|
record: runFunction(record, value === null || value === void 0 ? void 0 : value.length, value) || {},
|
|
position: position,
|
|
parentKey: runFunction(parentKey, value === null || value === void 0 ? void 0 : value.length, value),
|
|
newRecordType: newRecordType,
|
|
children: /*#__PURE__*/_jsx(Button, _objectSpread(_objectSpread({
|
|
type: "dashed",
|
|
style: _objectSpread({
|
|
display: 'block',
|
|
margin: '10px 0',
|
|
width: '100%'
|
|
}, style),
|
|
icon: /*#__PURE__*/_jsx(PlusOutlined, {})
|
|
}, restButtonProps), {}, {
|
|
children: creatorButtonText || intl.getMessage('editableTable.action.add', '添加一行数据')
|
|
}))
|
|
});
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, [recordCreatorProps, maxLength, value === null || value === void 0 ? void 0 : value.length]);
|
|
var buttonRenderProps = useMemo(function () {
|
|
if (!creatorButtonDom) {
|
|
return {};
|
|
}
|
|
if (isTop) {
|
|
return {
|
|
components: {
|
|
header: {
|
|
wrapper: function wrapper(_ref2) {
|
|
var _rest$columns;
|
|
var className = _ref2.className,
|
|
children = _ref2.children;
|
|
return /*#__PURE__*/_jsxs("thead", {
|
|
className: className,
|
|
children: [children, /*#__PURE__*/_jsxs("tr", {
|
|
style: {
|
|
position: 'relative'
|
|
},
|
|
children: [/*#__PURE__*/_jsx("td", {
|
|
colSpan: 0,
|
|
style: {
|
|
visibility: 'hidden'
|
|
},
|
|
children: creatorButtonDom
|
|
}), /*#__PURE__*/_jsx("td", {
|
|
style: {
|
|
position: 'absolute',
|
|
left: 0,
|
|
width: '100%'
|
|
},
|
|
colSpan: (_rest$columns = rest.columns) === null || _rest$columns === void 0 ? void 0 : _rest$columns.length,
|
|
children: creatorButtonDom
|
|
})]
|
|
})]
|
|
});
|
|
}
|
|
}
|
|
}
|
|
};
|
|
}
|
|
return {
|
|
tableViewRender: function tableViewRender(_, dom) {
|
|
var _props$tableViewRende, _props$tableViewRende2;
|
|
return /*#__PURE__*/_jsxs(_Fragment, {
|
|
children: [(_props$tableViewRende = (_props$tableViewRende2 = props.tableViewRender) === null || _props$tableViewRende2 === void 0 ? void 0 : _props$tableViewRende2.call(props, _, dom)) !== null && _props$tableViewRende !== void 0 ? _props$tableViewRende : dom, creatorButtonDom]
|
|
});
|
|
}
|
|
};
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, [isTop, creatorButtonDom]);
|
|
var editableProps = _objectSpread({}, props.editable);
|
|
|
|
/**
|
|
* 防止闭包的onchange
|
|
*
|
|
* >>>>>>为了性能好辛苦
|
|
*/
|
|
var newOnValueChange = useRefFunction(function (r, dataSource) {
|
|
var _props$editable3, _props$editable3$onVa, _props$onValuesChange;
|
|
(_props$editable3 = props.editable) === null || _props$editable3 === void 0 || (_props$editable3$onVa = _props$editable3.onValuesChange) === null || _props$editable3$onVa === void 0 || _props$editable3$onVa.call(_props$editable3, r, dataSource);
|
|
(_props$onValuesChange = props.onValuesChange) === null || _props$onValuesChange === void 0 || _props$onValuesChange.call(props, dataSource, r);
|
|
if (props.controlled) {
|
|
var _props$onChange;
|
|
props === null || props === void 0 || (_props$onChange = props.onChange) === null || _props$onChange === void 0 || _props$onChange.call(props, dataSource);
|
|
}
|
|
});
|
|
if (props !== null && props !== void 0 && props.onValuesChange || (_props$editable4 = props.editable) !== null && _props$editable4 !== void 0 && _props$editable4.onValuesChange ||
|
|
// 受控模式需要触发 onchange
|
|
props.controlled && props !== null && props !== void 0 && props.onChange) {
|
|
editableProps.onValuesChange = newOnValueChange;
|
|
}
|
|
return /*#__PURE__*/_jsxs(_Fragment, {
|
|
children: [/*#__PURE__*/_jsx(EditableTableActionContext.Provider, {
|
|
value: actionRef,
|
|
children: /*#__PURE__*/_jsx(ProTable, _objectSpread(_objectSpread(_objectSpread({
|
|
search: false,
|
|
options: false,
|
|
pagination: false,
|
|
rowKey: rowKey,
|
|
revalidateOnFocus: false
|
|
}, rest), buttonRenderProps), {}, {
|
|
tableLayout: "fixed",
|
|
actionRef: actionRef,
|
|
onChange: onTableChange,
|
|
editable: _objectSpread(_objectSpread({}, editableProps), {}, {
|
|
formProps: _objectSpread({
|
|
formRef: formRef
|
|
}, editableProps.formProps)
|
|
}),
|
|
dataSource: value,
|
|
onDataSourceChange: function onDataSourceChange(dataSource) {
|
|
setValue(dataSource);
|
|
/**
|
|
* 如果是top,需要重新设置一下 form,不然会导致 id 相同数据混淆
|
|
*/
|
|
if (props.name && position === 'top') {
|
|
var _formRef$current6;
|
|
var newValue = set({}, [props.name].flat(1).filter(Boolean), dataSource);
|
|
(_formRef$current6 = formRef.current) === null || _formRef$current6 === void 0 || _formRef$current6.setFieldsValue(newValue);
|
|
}
|
|
}
|
|
}))
|
|
}), props.name ? /*#__PURE__*/_jsx(ProFormDependency, {
|
|
name: [props.name],
|
|
children: function children(changeValue) {
|
|
var _props$editable5, _props$editable5$onVa;
|
|
if (!preData.current) {
|
|
preData.current = value;
|
|
return null;
|
|
}
|
|
var list = get(changeValue, [props.name].flat(1));
|
|
var changeItem = list === null || list === void 0 ? void 0 : list.find(function (item, index) {
|
|
var _preData$current;
|
|
return !isDeepEqualReact(item, (_preData$current = preData.current) === null || _preData$current === void 0 ? void 0 : _preData$current[index]);
|
|
});
|
|
preData.current = value;
|
|
if (!changeItem) return null;
|
|
// 如果不存在 preData 说明是初始化,此时不需要触发 onValuesChange
|
|
props === null || props === void 0 || (_props$editable5 = props.editable) === null || _props$editable5 === void 0 || (_props$editable5$onVa = _props$editable5.onValuesChange) === null || _props$editable5$onVa === void 0 || _props$editable5$onVa.call(_props$editable5, changeItem, list);
|
|
return null;
|
|
}
|
|
}) : null]
|
|
});
|
|
}
|
|
|
|
/**
|
|
* 可以直接放到 Form 中的可编辑表格
|
|
* A React component that is used to create a table.
|
|
* @param props
|
|
*/
|
|
function FieldEditableTable(props) {
|
|
var form = ProForm.useFormInstance();
|
|
if (!props.name) return /*#__PURE__*/_jsx(EditableTable, _objectSpread({
|
|
tableLayout: "fixed",
|
|
scroll: {
|
|
x: 'max-content'
|
|
}
|
|
}, props));
|
|
return /*#__PURE__*/_jsx(Form.Item, _objectSpread(_objectSpread({
|
|
style: {
|
|
maxWidth: '100%'
|
|
},
|
|
shouldUpdate: function shouldUpdate(prev, next) {
|
|
var name = [props.name].flat(1);
|
|
try {
|
|
return JSON.stringify(get(prev, name)) !== JSON.stringify(get(next, name));
|
|
} catch (error) {
|
|
return true;
|
|
}
|
|
}
|
|
}, props === null || props === void 0 ? void 0 : props.formItemProps), {}, {
|
|
name: props.name,
|
|
children: /*#__PURE__*/_jsx(EditableTable, _objectSpread(_objectSpread({
|
|
tableLayout: "fixed",
|
|
scroll: {
|
|
x: 'max-content'
|
|
}
|
|
}, props), {}, {
|
|
editable: _objectSpread(_objectSpread({}, props.editable), {}, {
|
|
form: form
|
|
})
|
|
}))
|
|
}));
|
|
}
|
|
FieldEditableTable.RecordCreator = RecordCreator;
|
|
export default FieldEditableTable; |