linkmore-design
Version:
🌈 🚀lm组件库。🚀
1,569 lines (1,537 loc) • 51.6 kB
JavaScript
"use strict";
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = exports.Summary = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _sortable = require("@dnd-kit/sortable");
var _ahooks = require("ahooks");
var _classnames = _interopRequireDefault(require("classnames"));
var _immer = require("immer");
var _lodash = require("lodash");
var _react = _interopRequireWildcard(require("react"));
var _reactResizable = require("react-resizable");
var _toFixed = require("./toFixed");
var _configProvider = _interopRequireDefault(require("../config-provider"));
var _empty = _interopRequireDefault(require("../empty"));
var _table = _interopRequireDefault(require("../table"));
var _useRowSelectControllableValue = _interopRequireDefault(require("./hooks/useRowSelectControllableValue"));
var _CalcExpression = _interopRequireDefault(require("./components/CalcExpression"));
var _sheelTableCell = _interopRequireDefault(require("./components/sheelTableCell"));
var _DndContainer = _interopRequireDefault(require("./components/DndContainer"));
var _DraggableContainer = _interopRequireDefault(require("./components/rowSort/DraggableContainer"));
var _Dragger = _interopRequireDefault(require("./components/rowSort/Dragger"));
var _sortableItem = _interopRequireDefault(require("./components/rowSort/sortableItem"));
var _util = require("./util");
var _resetConfig = _interopRequireDefault(require("./resetConfig"));
var _HeaderCol = _interopRequireDefault(require("./components/HeaderCol"));
var _HeaderRow = _interopRequireDefault(require("./components/HeaderRow"));
var _headRowSortWarp = _interopRequireDefault(require("./components/headRowSortWarp"));
var _useDndItems = _interopRequireDefault(require("./hooks/useDndItems"));
var _useGroupDataSource = _interopRequireDefault(require("./hooks/useGroupDataSource"));
var _virTual = require("./virTual");
var _index = require("./common/index");
/** 表表列排序组件 */
/** 表格行排序组件 */
const {
Summary
} = _table.default;
exports.Summary = Summary;
const {
ConfigContext
} = _configProvider.default;
const isEmpty = obj => Object.keys(obj || {})?.length === 0;
const defaultParsePaste = str => {
return str.split(/\r\n|\n|\r/).map(row => row.split('\t'));
};
const decimalLists = ['amount', 'price', 'number'];
const ResetTable = /*#__PURE__*/(0, _react.forwardRef)((props, ref) => {
const {
changeSize,
columns: customizeColumns,
dataSource: customizeDataSource,
autoSize,
rowClick,
onDoubleClick,
checkConfig,
summary,
pagination,
hiddenPage,
loading,
virtual = false,
colSortOpen = false,
resizeable = false,
customCheck,
components,
rowSelection,
columnsState,
onChange,
filterChange,
/** 默认类型一定要手动选择一个之后,点击整行才会选中,select模式则是点击整行就选中 */
tableRowType = 'default',
size = 'default',
/** 打开excel模式 */
openSheet = false,
/** 打开sheet的编辑模式 */
editSheet = false,
dataChange,
// 分组
openColGroup,
colGroupTitle,
openRowGroup,
rowGroupTitle,
groupWidth,
groupRowKeys: customizeGroupRowKeys,
groupColKeys: customizeGroupColKeys,
onGroupChange = () => {},
onExpressionChange,
rowStyle,
/** 开启表头拖动排序 */
headerColSort,
/** 表头排序后返回事件,返回最新的columns的 */
colChange,
/** 开启行排序 */
sortOpen = false,
/** 行排序返回事件,返回最新的 */
rowSortEnd,
emptyProps,
/** 是否点击时出现边框 */
showClickBorder = false,
/** 点击选择行发生变化时触发 */
selectRowChange,
/** 敏感列keys */
roleFiledKeys = [],
columnsValueDecimal = {
amount: 2
},
columnsMinWidth = 56,
rowClassName,
...resetProps
} = props;
if (!Array.isArray(customizeColumns) || !customizeColumns.length) {
return null;
}
const {
rowKey = 'id'
} = resetProps;
const {
locale
} = _react.default.useContext(ConfigContext);
const transformRowClick = data => rowClick?.(data.selectedRows || data);
// const [useSelectedRows, setSelectedRows] = useState({ selectedRows: [] }) // 复选中的值
const [useSelectedRows, setSelectedRows] = (0, _useRowSelectControllableValue.default)({
value: {
selectedRows: rowSelection?.selectedRows || rowSelection?.selectedRowKeys || []
},
onChange: rowClick ? transformRowClick : undefined
});
const [useActiveKey, setActiveKey] = (0, _react.useState)(''); // 行选中
const tableWarpRef = (0, _react.useRef)(null);
const tableRef = (0, _react.useRef)(null);
/** 记录最原始数据 */
const dataSourceRef = (0, _react.useRef)(null);
dataSourceRef.current = customizeDataSource;
const columnsRef = (0, _react.useRef)(null);
columnsRef.current = customizeColumns;
/** 右键的ref */
const contentMenuRef = (0, _react.useRef)(null);
/** 当前展开的列 */
const [expandedRowKeys, setExpandedRowKeys] = (0, _react.useState)([]);
const deepDataSourceRef = (0, _react.useRef)([]);
const deepColumnsRef = (0, _react.useRef)([]);
//
const copyAllData = (0, _react.useRef)(null);
//
const update = (0, _ahooks.useUpdate)();
/** 最后一个点击的行 */
const [lastClickRow, setLastClickRow] = (0, _react.useState)(null);
(0, _react.useEffect)(() => {
if (showClickBorder && selectRowChange) {
const item = dataSourceRef.current?.find(item => item[rowKey] === lastClickRow);
selectRowChange?.(item || lastClickRow);
}
}, [lastClickRow]);
const {
dndColumns,
items,
groupRowKeys,
groupColKeys,
updateItems
} = (0, _useDndItems.default)({
columns: customizeColumns,
openColGroup,
openRowGroup,
colSortOpen,
filterChange,
customizeGroupRowKeys,
customizeGroupColKeys
});
onGroupChange && onGroupChange(groupRowKeys, groupColKeys);
/** 行分组 */
const [groupDataSource] = (0, _useGroupDataSource.default)({
groupRowKeys,
customizeDataSource,
columnsRef
});
/** 列分组 */
const {
columns,
dataSource
} = (0, _react.useMemo)(() => {
if (!groupColKeys?.length) {
return {
dataSource: groupDataSource,
columns: dndColumns
};
}
return (0, _util.transformWithColGroup)(dndColumns, groupDataSource, groupColKeys, groupRowKeys);
}, [dndColumns, groupDataSource, groupColKeys, groupRowKeys]);
(0, _react.useEffect)(() => {
setExpandedRowKeys([]);
deepDataSourceRef.current = [];
deepColumnsRef.current = [];
}, [groupRowKeys, groupColKeys]);
/** sheel数据的表格 */
const [sheelStataus, setSheelStatus] = (0, _react.useState)({
// 记录框选的行列坐标信息
start: {},
end: {},
// 是否在框选
selecting: false,
forceEdit: false,
// 是否在编辑中
editing: {},
clear: {},
// 记录右下角小方块的拖动信息
commiting: {}
});
const shellStatusRef = (0, _react.useRef)({
start: {},
end: {},
selecting: false,
forceEdit: false,
editing: {},
clear: {},
commiting: {}
});
const [selectIng, setSelectIng] = (0, _react.useState)(false);
const [editIng, setEditIng] = (0, _react.useState)(false);
const [commitIng, setCommitIng] = (0, _react.useState)(false);
/** 右键菜单是否显示 */
const [contextMenuStatus, setContextMenuStatus] = (0, _react.useState)(false);
/** 右键按钮的位置 */
const [style, setStyle] = (0, _react.useState)({
position: 'fixed',
left: 300,
top: 200
});
// 列设置
const [columnsStateMap, setColumnsStateMap] = (0, _react.useState)(false);
// 行分组数据铺平, 在框选时获取数据使用
(0, _react.useEffect)(() => {
const source = [];
const deepChildren = arr => {
arr?.forEach(item => {
source.push((0, _lodash.omit)(item, 'children'));
// 展开
if (item?.children && expandedRowKeys.includes(item.key)) {
deepChildren(item?.children);
}
});
};
deepChildren(dataSource);
deepDataSourceRef.current = source;
}, [dataSource, expandedRowKeys]);
// 列分组数据铺平,在框选时获取数据使用
(0, _react.useEffect)(() => {
const source = [];
const deepChildren = arr => {
arr?.forEach(item => {
if (item.children && item.children.length) {
deepChildren(item.children);
} else {
source.push(item);
}
});
};
deepChildren(columns);
deepColumnsRef.current = source;
}, [columns, groupColKeys]);
const [useColumns, setColumns] = (0, _react.useState)(columns);
(0, _react.useEffect)(() => {
setColumns(columns);
}, [columns]);
const onSortEnd = (active, over) => {
const cloneArr = [...dataSourceRef.current];
const oldIndex = cloneArr.findIndex(v => v[rowKey] === active);
const newIndex = cloneArr.findIndex(v => v[rowKey] === over);
rowSortEnd?.((0, _sortable.arrayMove)(cloneArr, oldIndex, newIndex));
};
const DraggableContainer = props => /*#__PURE__*/_react.default.createElement(_DraggableContainer.default, (0, _extends2.default)({}, props, {
virtual: true,
options: dataSourceRef.current,
rowKey: rowKey,
onSortEnd: onSortEnd,
tableWidth: tableWarpRef?.current?.getBoundingClientRect()?.width,
columns: columnsRef.current || resultColumns,
keys: dataSourceRef.current?.map(item => item[rowKey])
}));
const DraggableBodyRow = props => {
return /*#__PURE__*/_react.default.createElement(_sortableItem.default, (0, _extends2.default)({
virtual: true
}, props));
};
const sortDefaultColumnItem = {
title: '排序',
dataIndex: 'sort',
width: 54,
maxWidth: 54,
fixed: 'left',
order: -2,
className: 'drag-visible',
render: (_, record) => /*#__PURE__*/_react.default.createElement(_Dragger.default, {
id: record?.[rowKey] || record?.id
})
};
/** 列宽拖动时速度 */
const handleResize = index => (e, {
size
}) => {
let i = index;
const nextColumns = [...useColumns];
nextColumns.forEach((item, index) => {
if (index <= i && item.show === false) {
i += 1;
}
});
nextColumns[i] = {
...nextColumns[i],
width: size.width
};
setColumns(nextColumns);
};
/** 列宽拖动结束事件 */
const endResize = () => {
setTimeout(() => {
filterChange?.(useColumns);
});
};
/** 表格sheet化事件中心START */
const isSelected = (i, j) => {
const {
start,
end,
editing,
commiting
} = shellStatusRef.current;
const maxi = Math.max(start?.i, end.i);
const mini = Math.min(start?.i, end.i);
const maxj = Math.max(start?.j, end.j);
const minj = Math.min(start?.j, end.j);
const isSelected = (0, _util.checkIsSelectd)(i, j, start, end);
return {
/** 是否选中 */
isSelected,
/** 是否尾行 */
isEnd: i === maxi && j >= minj && j <= maxj,
/** 是否尾列 */
isRightEnd: j === maxj && i >= mini && i <= maxi,
/** 是否在编辑中 */
isEditing: editing?.i === i && editing?.j === j,
/** 是否有效拉伸 */
isVaildCommit: isEmpty(commiting) ? false : isSelected && !(0, _util.checkIsSelectd)(i, j, commiting?.start, commiting?.end),
/** 是否选中只读框 */
// TODO
selectedReadonly: true
};
};
/** 获取框选的数据 */
const getSelectDatas = (start, end) => {
return (0, _util.range)(start.i, end.i).map(i => (0, _util.range)(start.j, end.j).map(j => {
const columnKey = groupColKeys?.length ? deepColumnsRef.current[j].dataIndex : columns[j]?.dataIndex;
const dataItem = groupRowKeys?.length ? deepDataSourceRef.current[i] : dataSource[i];
const cell = dataItem?.[columnKey];
if (columns[j]?.render) {
return columns[j]?.render?.(cell, dataItem, i);
}
return cell;
}).join('\t')).join('\n');
};
/** 复制选中内容 */
const handleCopy = e => {
e?.preventDefault();
const {
start,
end
} = shellStatusRef.current;
const text = copyAllData.current || getSelectDatas(start, end);
if (window.clipboardData && window.clipboardData.setData) {
window.clipboardData.setData('Text', text);
document.removeEventListener('copy', handleCopy);
} else if (e.clipboardData?.setData) {
e.clipboardData.setData('text/plain', text);
document.removeEventListener('copy', handleCopy);
} else if (!copyAllData.current) {
document?.execCommand('copy');
if (contextMenuStatus) {
setContextMenuStatus(false);
}
}
copyAllData.current = null;
};
/** 复制所有数据 */
const handleCopyAll = e => {
e?.preventDefault();
const source = dataSourceRef.current;
const columns = columnsRef.current;
const text = source.map((rItem, i) => columns.map((cItem, j) => {
const columnKey = columns[j]?.dataIndex;
const dataItem = dataSource[i];
const cell = dataItem?.[columnKey];
if (columns[j]?.render) {
return columns[j]?.render?.(cell, dataItem, i);
}
return cell;
}).join('\t')).join('\n');
copyAllData.current = text;
document?.execCommand('copy');
setContextMenuStatus(false);
};
const onMouseOver = (i, j) => {
if (isEmpty(shellStatusRef?.current?.commiting)) {
if (shellStatusRef?.current?.selecting && isEmpty(shellStatusRef?.current?.editing)) {
shellStatusRef.current = {
...shellStatusRef.current,
end: {
i,
j
}
};
setSheelStatus({
...sheelStataus,
end: {
i,
j
}
});
}
} else if (!isEmpty(shellStatusRef?.current?.commiting || {}) && (0, _util.checkStatus)(i, j, shellStatusRef?.current?.commiting)?.isVaildCommit) {
if ((0, _util.isSelectCrossRowGroup)(i, shellStatusRef, deepDataSourceRef)) {
return;
}
if ((0, _util.isSelectCrossInvalidCol)(i, j, shellStatusRef, deepDataSourceRef, deepColumnsRef)) {
return;
}
shellStatusRef.current = {
...shellStatusRef.current,
end: {
i,
j
}
};
setSheelStatus({
...sheelStataus,
end: {
i,
j
}
});
}
};
// 通过表格的行列索引,获取对应的原始数据的item信息
const getSourceItemInfo = (trIndex, tdIndex) => {
const innerColumns = groupColKeys?.length ? deepColumnsRef.current : columns;
const columnsKeysList = innerColumns.map(item => item.dataIndex);
let key = columnsKeysList[tdIndex];
let index;
const nil = {
index: -1,
key: undefined
};
if (key === undefined) {
return nil;
}
// 列分组的情况下
if (groupColKeys?.length) {
if (groupRowKeys?.length && deepDataSourceRef?.current?.[trIndex]._group) {
return nil;
}
index = (0, _util.getDataSourceIndex)({
key,
dataSource
});
const arr = key.split('_');
key = arr[arr.length - 2];
} else if (groupRowKeys.length) {
index = deepDataSourceRef.current[trIndex].__index;
} else {
index = trIndex;
}
return {
index,
key
};
};
/** sheel 表格 鼠标松开 */
/** TODO: 在分组的情况,需要排除_group行的数据转换,以及要进行对子级的覆盖 */
const sheelOnMouseUp = () => {
if (!isEmpty(shellStatusRef.current?.commiting)) {
const {
start,
end,
commiting
} = shellStatusRef.current;
//
const innerColumns = groupColKeys?.length ? deepColumnsRef.current : columns;
const innerDataSource = groupRowKeys?.length ? deepDataSourceRef.current : dataSource;
//
const columnsKeysList = innerColumns.map(item => item.dataIndex);
// 行文本
const rowtext = (0, _util.getSelectionRowText)({
selection: commiting,
columnsKeysList,
dataSource: innerDataSource
});
// 列文本
const coltext = (0, _util.getSelectionColText)({
selection: commiting,
columns: innerColumns,
dataSource: innerDataSource
});
/** 选择范围 例如:i:[0,1], j:[1,2] */
const selectedRange = {
i: (0, _util.range)(start.i, end.i),
j: (0, _util.range)(start.j, end.j)
};
/** 提交范围 */
const commitRange = {
i: (0, _util.range)(commiting?.start?.i, commiting?.end?.i),
j: (0, _util.range)(commiting?.start?.j, commiting?.end?.j)
};
// obj 为新增的范围
let obj = {
i: [],
j: []
};
let type = '';
if ((0, _lodash.difference)(selectedRange.i, commitRange.i)?.length) {
obj = {
i: (0, _lodash.difference)(selectedRange.i, commitRange.i),
j: selectedRange.j
};
type = 'row';
} else if ((0, _lodash.difference)(selectedRange.j, commitRange.j)?.length) {
obj = {
i: selectedRange.i,
j: (0, _lodash.difference)(selectedRange.j, commitRange.j)
};
type = 'col';
}
const data = (0, _lodash.cloneDeep)(dataSourceRef.current);
obj.i?.forEach((tri, index) => {
obj.j?.forEach(tdj => {
if (isSelected(tri, tdj)?.isSelected) {
// 只读列无法修改其内容
if (deepColumnsRef?.current?.[tdj]?.readOnly) {
return;
}
const {
index: sourceIndex,
key
} = getSourceItemInfo(tri, tdj);
if (sourceIndex < 0 || sourceIndex >= data.length) {
return;
}
// 行替换
if (type === 'row') {
data[sourceIndex][key] = rowtext[index % rowtext.length]?.[tdj];
} else {
// 列替换
data[sourceIndex][key] = coltext[index % coltext.length]?.[tdj % coltext[index % coltext.length].length];
}
}
});
});
if (editSheet) {
dataChange?.(data);
}
setSheelStatus({
...sheelStataus,
selecting: false,
commiting: {}
});
shellStatusRef.current = {
...shellStatusRef.current,
selecting: false,
commiting: {}
};
setCommitIng(false);
} else {
setSheelStatus({
...sheelStataus,
selecting: false
});
shellStatusRef.current = {
...shellStatusRef.current,
selecting: false
};
}
document.removeEventListener('mouseup', sheelOnMouseUp);
};
/** 剪切内容 */
const handleCut = e => {
if (isEmpty(shellStatusRef.current?.editing)) {
e.preventDefault();
handleCopy(e);
/** 暂时先不隐藏 */
// const { start, end } = shellStatusRef.current
// clearSelectedCells(start, end)
}
};
/** 内容粘贴 */
/** TODO: 在分组的情况,需要排除_group行的数据转换 */
const handlePaste = e => {
if (isEmpty(shellStatusRef.current?.editing)) {
let {
start,
end
} = shellStatusRef.current;
start = {
i: Math.min(start.i, end.i),
j: Math.min(start.j, end.j)
};
end = {
i: Math.max(start.i, end.i),
j: Math.max(start.j, end.j)
};
const parse = defaultParsePaste;
let pasteData = [];
if (window.clipboardData && window.clipboardData.getData) {
// IE
pasteData = parse(window.clipboardData.getData('Text'));
} else if (e.clipboardData && e.clipboardData.getData) {
pasteData = parse(e.clipboardData.getData('text/plain'));
}
// in order of preference
const resultEnd = [];
pasteData?.forEach((row, i) => {
row?.forEach((value, j) => {
resultEnd.push({
i: start.i + i,
j: start.j + j,
value
});
});
});
const res = (0, _immer.produce)(dataSourceRef.current, draft => {
resultEnd?.forEach(item => {
if (isSelected(item.i, item.j)?.isSelected) {
const {
index,
key
} = getSourceItemInfo(item.i, item.j);
if (index < 0 || index >= draft.length) {
return;
}
draft[index][key] = item.value;
}
});
});
/** 只有开通了编辑权限之后才可以 */
if (editSheet) {
dataChange?.(res);
}
}
// 修复重复问题
document.removeEventListener('paste', handlePaste);
document.removeEventListener('copy', handleCopy);
document.removeEventListener('cut', handleCut);
};
const pageClick = e => {
// if (this.props.disablePageClick) return;
const element = tableWarpRef.current;
if (!element?.contains(e.target)) {
shellStatusRef.current = {
start: {},
end: {},
selecting: false,
forceEdit: false,
editing: {},
clear: {},
commiting: {}
};
setSelectIng(false);
document.removeEventListener('mousedown', pageClick);
document.removeEventListener('mouseup', sheelOnMouseUp);
document.removeEventListener('cut', handleCut);
document.removeEventListener('copy', handleCopy);
document.removeEventListener('paste', handlePaste);
}
/** 关闭右键 */
const contentElement = contentMenuRef.current;
if (!contentElement?.contains(e.target)) {
setContextMenuStatus(false);
}
};
/** sheel 表格 鼠标点击 */
/**
* i 行
* j 列
* e 点击元素
* commitStatus boolena 是否点击了快速选择
*/
const sheelMouseDown = (i, j, e, commitStatus) => {
const isNowEditingSameCell = !isEmpty(shellStatusRef.current?.editing) && shellStatusRef.current?.editing.i === i && shellStatusRef.current?.editing.j === j;
const editing = isEmpty(shellStatusRef.current?.editing) || shellStatusRef.current?.editing.i !== i || shellStatusRef.current?.editing.j !== j ? {} : shellStatusRef.current?.editing;
shellStatusRef.current = {
selecting: !isNowEditingSameCell,
start: e?.shiftKey || commitStatus ? shellStatusRef.current?.start : {
i,
j
},
end: {
i,
j
},
editing,
forceEdit: !!isNowEditingSameCell,
commiting: commitStatus ? {
start: shellStatusRef.current?.start,
end: {
i,
j
}
} : {}
};
setSelectIng(!isNowEditingSameCell);
if (commitStatus) {
setCommitIng(true);
}
if (isEmpty(shellStatusRef.current?.editing)) {
setEditIng(false);
}
document.addEventListener('mouseup', sheelOnMouseUp);
document.addEventListener('mousedown', pageClick);
document.addEventListener('cut', handleCut);
document.addEventListener('copy', handleCopy);
document.addEventListener('paste', handlePaste);
};
/** 鼠标右键点击事件 */
const onContextMenu = (evt, i, j) => {
evt.preventDefault();
const {
start,
end
} = shellStatusRef.current;
/** 如果表格当前没有选择,则把当前的右击的td块默认选中 */
if (isEmpty(start) && isEmpty(end)) {
sheelMouseDown(i, j, evt);
}
if (!(0, _util.checkIsSelectd)(i, j, start, end)) {
sheelMouseDown(i, j, evt);
}
setContextMenuStatus(true);
// 获得点击的位置
let {
clientX,
clientY
} = evt;
// 文档显示区的宽度
const screenW = window.innerWidth;
const screenH = window.innerHeight;
// 右键菜单的宽度
// const rightClickRefW = rightClickRef.current.offsetWidth;
// const rightClickRefH = rightClickRef.current.offsetHeight;
const rightClickRefW = 200;
const rightClickRefH = 200;
// right为true,说明鼠标点击的位置到浏览器的右边界的宽度可以放下contextmenu。
// 否则,菜单放到左边。
const right = screenW - clientX > rightClickRefW;
const top = screenH - clientY > rightClickRefH;
// 赋值右键菜单离鼠标一些距离
clientX = right ? clientX + 6 : clientX - rightClickRefW - 6;
clientY = top ? clientY + 6 : clientY - rightClickRefH - 6;
setStyle({
...style,
left: clientX,
top: clientY
});
};
const onSheelDoubleClick = (i, j, col) => {
if (editSheet) {
if (!col.readOnly) {
shellStatusRef.current = {
...shellStatusRef.current,
editing: {
i,
j
},
forceEdit: true,
clear: {}
};
setEditIng(true);
}
}
};
const dataSourceChange = (i, j, value) => {
const {
index,
key
} = getSourceItemInfo(i, j);
if (index < 0 || index >= dataSourceRef.current.length) {
return;
}
// 表格中的行数 转化为 对应的数据源索引
const res = (0, _immer.produce)(dataSourceRef.current, draft => {
draft[index][key] = value;
});
dataChange?.(res);
shellStatusRef.current = {
...shellStatusRef.current,
editing: {},
forceEdit: false,
clear: {}
};
};
(0, _react.useEffect)(() => {
return () => {
document.removeEventListener('mousedown', pageClick);
document.removeEventListener('mouseup', sheelOnMouseUp);
document.removeEventListener('cut', handleCut);
document.removeEventListener('copy', handleCopy);
document.removeEventListener('paste', handlePaste);
};
}, []);
/** 表格sheet化事件中心END */
const resetColumns = (0, _react.useCallback)(() => {
const roleHideKeys = roleFiledKeys?.filter(item => item.type === 0)?.map(item => item.key) || [];
let colIndex = 0;
const traverseColumns = columns => {
for (let i = 0; i < columns.length; i += 1) {
const col = columns[i];
const mergeColDecimal = {
number: null,
price: null,
amount: 2,
...(columnsValueDecimal || {})
};
const {
decimalType
} = col;
const hasDecimal = decimalLists?.includes(decimalType);
const align = col.align || (hasDecimal ? 'right' : 'left');
col.align = align;
col.render = col.render ? col.render : hasDecimal && !!mergeColDecimal[decimalType] ? text => /*#__PURE__*/_react.default.createElement("span", {
style: {
textAlign: 'right'
}
}, (0, _toFixed.toFixedNumber)(text, mergeColDecimal[decimalType])) : null;
if (col.show === false || roleHideKeys.includes(col.roleKey || col.dataIndex)) {
columns.splice(i, 1);
i -= 1;
} else if (col.children && col.children.length) {
traverseColumns(col.children);
} else {
// $_ 开头表示私有属性
col.$_colIndex = colIndex;
// eslint-disable-next-line no-loop-func
col.onHeaderCell = column => {
return resizeable ? {
width: column.width,
dataIndex: column.dataIndex,
onResize: handleResize(i),
onResizeStop: endResize,
minWidth: column.minWidth
} : {
width: column.width,
dataIndex: column.dataIndex
};
};
if (openSheet) {
col.onCell = (record, rowIndex) => {
return {
record,
rowKey,
col,
colIndex: col.$_colIndex,
selectIng,
editIng,
commitIng,
rowIndex,
onMouseDown: sheelMouseDown,
onMouseOver,
onContextMenu,
isSelected,
onDoubleClick: onSheelDoubleClick,
dataSourceChange
};
};
} else if (openRowGroup) {
col.onCell = record => {
return {
record,
col,
onChangeRecord: (dfs, dataIndex, value, isUpdate) => {
dfs(dataSource, dataIndex, value);
isUpdate && update();
},
onExpressionChange
};
};
}
colIndex += 1;
}
}
};
let innerColumns = (0, _lodash.cloneDeep)(useColumns.filter(item => item.show !== false));
if (groupRowKeys?.length) {
/** 如果是进行了行分组,则会生成一列dataIndex为Group的Col, 如果需要修改此处,请备注原因 */
innerColumns = [{
type: 'name',
title: '分组',
dataIndex: '_group',
key: '_group',
width: groupWidth || 100,
fixed: 'left'
}, ...innerColumns];
}
traverseColumns(innerColumns, null);
return sortOpen ? [sortDefaultColumnItem, ...innerColumns] : innerColumns;
}, [useColumns, sortOpen, selectIng, dataSource, groupRowKeys, commitIng, roleFiledKeys]);
// 行点击事件
const onRecord = record => {
const {
trigger,
highlight
} = Object.assign(_resetConfig.default.checkConfig, checkConfig);
if (highlight) {
setActiveKey(record[rowKey]);
}
setLastClickRow(record[rowKey]);
if (trigger === 'row') {
const {
selectedRows
} = useSelectedRows;
if (showClickBorder) {
/** 如果是点击出现框的,则不变 */
setSelectedRows({
selectedRows
});
} else if (tableRowType === 'default' && selectedRows.length < 2) {
/** TODO: 点击行时默认开启单选模式 */
setSelectedRows({
selectedRows: [(0, _lodash.isObject)(selectedRows[0]) || !selectedRows.length ? record : record[rowKey]]
});
} else if (tableRowType === 'select' || tableRowType === 'default' && selectedRows.length) {
if (rowSelection?.type === 'radio') {
setSelectedRows({
selectedRows: [(0, _lodash.isObject)(selectedRows[0]) || !selectedRows.length ? record : record[rowKey]]
});
} else {
const selectIndex = selectedRows?.findIndex(v => (0, _lodash.isObject)(v) ? v[rowKey] === record[rowKey] : v === record[rowKey]);
selectIndex >= 0 ? selectedRows.splice(selectIndex, 1) : selectedRows.push((0, _lodash.isObject)(selectedRows[0]) || !selectedRows.length ? record : record[rowKey]);
setSelectedRows({
selectedRows: (0, _lodash.cloneDeep)(selectedRows)
});
}
}
} else {
rowClick?.(record);
}
};
const restRowClassName = (0, _react.useCallback)((record, index) => {
const customRowClassName = rowClassName?.(record, index) || '';
return (0, _classnames.default)(customRowClassName, record[rowKey] === useActiveKey && 'row-active', record[rowKey] === lastClickRow && !!showClickBorder && 'row-clicking');
}, [rowClassName, rowKey, useActiveKey, lastClickRow, showClickBorder]);
// 复选框配置
const config = (0, _react.useMemo)(() => {
let autoSizeHeight = autoSize.height;
if (autoSizeHeight === '100%' && (openRowGroup || openColGroup)) {
autoSizeHeight = 'calc(100% - 100px)';
}
return {
defaultSize: 'small',
tableLayout: 'fixed',
rowKey,
debounceTime: 300,
revalidateOnFocus: false,
options: {
setting: false,
density: false,
fullScreen: false,
reload: false
},
columnsState: {
value: columnsStateMap,
onChange: k => {
setColumnsStateMap(k);
}
},
search: false,
tableAlertRender: false,
checkConfig,
// components: vComponents,
scroll: resetProps.autoSizer || resetProps.scroll ? {
y: autoSizeHeight,
...resetProps.scroll,
...(resizeable ? {
x: '100%'
} : {})
} : resizeable ? {
x: '100%'
} : null,
pagination: !hiddenPage && {
showSizeChanger: true,
showQuickJumper: true,
showTotal: total => locale?.locale === 'en' ? `total ${total} Page` : `共 ${total} 条`,
locale: locale?.locale === 'en' ? locale?.Pagination || {} : {
items_per_page: '条/页',
jump_to: '前往',
page: '页'
},
size: 'small',
...pagination
},
rowSelection: rowSelection === false ? undefined : {
fixed: true,
type: 'checkbox',
columnWidth: 36,
selectedRowKeys: useSelectedRows.selectedRows.map(v => (0, _lodash.isObject)(v) ? v[rowKey] : v),
/** 如果开启了行分组,则需要把checkStrictly关闭,变成受控模式 */
checkStrictly: !groupRowKeys?.length,
onChange: !rowSelection?.selectedRows ? (selectedRowKeys, selectedRows) => {
setSelectedRows({
selectedRows
});
// rowClick?.(selectedRows)
} : undefined,
onSelectAll: rowSelection?.selectedRows ? (selected, selectedRows, changeRows) => {
const changeRowKeys = changeRows?.map(item => item[rowKey]);
const reulstSelect = selected ? (0, _lodash.uniqBy)([...rowSelection.selectedRows, ...changeRows], rowKey) : rowSelection.selectedRows.filter(item => !changeRowKeys.includes(item[rowKey]));
setSelectedRows({
selectedRows: reulstSelect
});
// rowClick?.(reulstSelect)
} : undefined,
onSelect: rowSelection?.selectedRows ? (record, selected) => {
const reulstSelect = rowSelection.type === 'radio' ? [record] : selected ? (0, _lodash.uniqBy)([...rowSelection.selectedRows, record], rowKey) : rowSelection.selectedRows.filter(item => item[rowKey] !== record[rowKey]);
setSelectedRows({
selectedRows: reulstSelect
});
// rowClick?.(reulstSelect)
} : undefined,
...rowSelection
},
onRow: record => ({
onClick: () => {
onRecord(record);
},
onDoubleClick: () => {
onDoubleClick?.(record);
},
...(resetProps.onRow || {})
}),
rowClassName: restRowClassName,
columns: resetColumns(),
size,
...resetProps
};
}, [useColumns, useSelectedRows, columnsStateMap, restRowClassName, resetProps, autoSize.height, resizeable]);
const resultColumns = (0, _react.useMemo)(() => {
const result = useColumns.map((item, index) => {
return {
...item,
colSort: columnsStateMap?.[item.dataIndex]?.order === undefined ? index : columnsStateMap?.[item.dataIndex]?.order || index,
fixed: columnsStateMap?.[item.dataIndex]?.fixed || item.fixed || undefined,
show: columnsStateMap?.[item.dataIndex]?.show !== false
};
}).filter(item => !!item.show);
result.sort((a, b) => {
return (a.fixed === 'left' ? a.colSort : a.fixed === 'right' ? 500 + a.colSort : a.colSort + 50) - (b.fixed === 'left' ? b.colSort : b.fixed === 'right' ? 500 + b.colSort : b.colSort + 50);
});
return result;
}, [columnsStateMap, useColumns]);
(0, _react.useEffect)(() => {
const obj = {
...columnsState
};
columns?.forEach(item => {
/** 目前支持三种 */
const {
order,
show,
fixed
} = obj[item.dataIndex || item.key] || {};
obj[item.dataIndex || item.key] = {
fixed: fixed || item.fixed,
show: show === false ? false : item.show || true,
order: order || item.order
};
});
setColumnsStateMap(obj);
}, [columnsState]);
// 将节点方法给外部使用
_react.default.useImperativeHandle(ref, () => ({
changeSize,
getCheckboxRecords: () => useSelectedRows.selectedRows,
// 用于按钮触发事件
clearSelect: () => {
setSelectedRows({
selectedRows: []
});
// rowClick?.([])
},
customSetCheckboxRecords: value => {
setSelectedRows({
selectedRows: value
});
// rowClick?.(value)
},
checkboxRecords: useSelectedRows.selectedRows,
columns: useColumns.map(item => {
return (0, _lodash.omit)(item, ['render', 'sorter', 'onFilter', 'filters']);
})
}));
const onTableChange = (pagination, filters, sorter, extra) => {
const resultColumns = useColumns.map(item => {
const obj = {
...item,
sortOrder: false
};
obj.filteredValue = filters[obj.dataIndex] || [];
if (Array.isArray(sorter)) {
const checkSort = sorter.find(s => s.field === obj.dataIndex);
if (checkSort) {
obj.sortOrder = checkSort.order;
}
} else if (sorter?.field === obj.dataIndex) {
obj.sortOrder = sorter.order;
}
return obj;
});
setColumns(resultColumns);
filterChange?.(resultColumns);
onChange?.(pagination, filters, sorter, extra);
};
/** 排序的表头 */
const ResizableTitle = props => {
const {
onResize = () => {},
width,
dataIndex,
onResizeStop,
...restProps
} = props;
const style = customizeDataSource.length === 0 ? {
width: `${width}px`,
position: 'relative',
left: 'auto',
right: 'auto'
} : {};
if (!width) {
return headerColSort ? /*#__PURE__*/_react.default.createElement(_HeaderRow.default, (0, _extends2.default)({
column: column
}, props, restProps, {
style: {
...restProps.style,
...style
},
rowSort: headerColSort,
openRowGroup: openRowGroup,
openColGroup: openColGroup
})) : /*#__PURE__*/_react.default.createElement("th", restProps);
}
const column = (0, _index.treeFind)(columns, node => {
return node.dataIndex === dataIndex;
});
if (!column || groupRowKeys.includes(dataIndex)) {
return /*#__PURE__*/_react.default.createElement("th", (0, _extends2.default)({}, restProps, {
style: {
...restProps.style,
...style
}
}));
}
return /*#__PURE__*/_react.default.createElement(_reactResizable.Resizable, {
width: width,
height: 0,
handle: /*#__PURE__*/_react.default.createElement("span", {
className: "react-resizable-handle",
onClick: e => {
e.stopPropagation();
}
}),
axis: "x",
minConstraints: [props?.minWidth || columnsMinWidth || 56, 10],
onResize: onResize,
onResizeStop: onResizeStop,
draggableOpts: {
enableUserSelectHack: false
}
}, headerColSort ? /*#__PURE__*/_react.default.createElement(_HeaderRow.default, (0, _extends2.default)({
column: column
}, props, restProps, {
style: {
...restProps.style,
...style
},
rowSort: headerColSort,
openRowGroup: openRowGroup,
openColGroup: openColGroup
})) : /*#__PURE__*/_react.default.createElement("th", (0, _extends2.default)({}, restProps, {
style: {
...restProps.style,
...style
}
}), /*#__PURE__*/_react.default.createElement(_HeaderCol.default, (0, _extends2.default)({
column: column
}, props, {
rowSort: headerColSort,
openRowGroup: openRowGroup,
openColGroup: openColGroup
}))));
};
const colDraggableContainer = (0, _react.useCallback)(({
...props
}) => {
const {
children
} = props;
return /*#__PURE__*/_react.default.createElement("tr", null, children);
}, [columns]);
// 重写表格
const tableComponents = (0, _react.useMemo)(() => {
const {
body = {},
header = {}
} = components || {};
let table = null;
if (virtual) {
table = function InnerVirtualTable(props) {
return /*#__PURE__*/_react.default.createElement(_virTual.VirtualTable, (0, _extends2.default)({}, props, {
isEmpty: !customizeDataSource.length,
emptyProps: emptyProps
}));
};
}
let headerRow = null;
if (openRowGroup || openColGroup) {
headerRow = colDraggableContainer;
}
let headerCell = null;
if (openRowGroup || openColGroup || resizeable || headerColSort) {
headerCell = ResizableTitle;
}
let bodyCell = null;
if (openSheet) {
bodyCell = _sheelTableCell.default;
} else if (openRowGroup) {
bodyCell = _CalcExpression.default;
}
return {
table,
header: {
row: headerRow,
cell: headerCell,
...header
},
body: {
wrapper: sortOpen ? DraggableContainer : virtual ? _virTual.VirtualWrapper : null,
row: sortOpen ? DraggableBodyRow : virtual ? _virTual.VirtualRow : null,
cell: bodyCell,
...body
}
};
}, [sortOpen, resizeable, components, colSortOpen, customizeDataSource, columns, openRowGroup, headerColSort]);
(0, _react.useEffect)(() => {
if (autoSize && autoSize.height !== '100%') {
const dom = document.querySelector('.lm_protable .ant-table-body');
if (dom) {
dom.style.height = `${autoSize.height}px`;
}
}
}, [autoSize]);
return /*#__PURE__*/_react.default.createElement("div", {
style: {
height: '100%',
width: '100%'
},
ref: tableWarpRef
}, /*#__PURE__*/_react.default.createElement(_configProvider.default
// locale={locale}
, {
renderEmpty: loading ? () => null : emptyProps ? () => /*#__PURE__*/_react.default.createElement(_empty.default, emptyProps, emptyProps?.footer || null) : () => /*#__PURE__*/_react.default.createElement(_empty.default, {
title: null,
image: "nodata",
description: null
}, emptyProps?.footer || null)
}, headerColSort ? /*#__PURE__*/_react.default.createElement(_headRowSortWarp.default, {
items: resultColumns,
updateItems: data => colChange?.(data)
}, /*#__PURE__*/_react.default.createElement(_table.default, (0, _extends2.default)({
ref: tableRef
}, config, {
loading: loading,
dataSource: dataSource,
components: tableComponents,
onChange: onTableChange,
expandable: resetProps?.expandable || {
onExpand: () => {
shellStatusRef.current = {
start: {},
end: {},
selecting: false,
forceEdit: false,
editing: {},
clear: {},
commiting: {}
};
},
expandedRowKeys,
onExpandedRowsChange: expandedRows => setExpandedRowKeys(expandedRows)
},
className: (0, _classnames.default)('lm_protable', resizeable && 'lm_resizeable', resetProps?.autoSizer && 'lm_autosize_table', (!hiddenPage || !!customCheck) && resetProps?.autoSizer && 'lm_page_info_table'),
summary: pageData => summary && summary(pageData, resultColumns, resetColumns()),
onRow: () => {
return {
style: rowStyle || {}
};
}
}))) : openRowGroup || openColGroup || colSortOpen ? /*#__PURE__*/_react.default.createElement(_DndContainer.default, {
items: items,
updateItems: updateItems,
rowGroupTitle: rowGroupTitle,
colGroupTitle: colGroupTitle,
filterColumns: (columnsRef.current || []).filter(item => item.rowGroup || item.colGroup)
}, /*#__PURE__*/_react.default.createElement(_table.default, (0, _extends2.default)({
ref: tableRef
}, config, {
loading: loading,
dataSource: dataSource,
components: tableComponents,
onChange: onTableChange,
expandable: resetProps?.expandable || {
onExpand: () => {
shellStatusRef.current = {
start: {},
end: {},
selecting: false,
forceEdit: false,
editing: {},
clear: {},
commiting: {}
};
},
expandedRowKeys,
onExpandedRowsChange: expandedRows => setExpandedRowKeys(expandedRows)
},
className: (0, _classnames.default)('lm_protable', resizeable && 'lm_resizeable', resetProps?.autoSizer && 'lm_autosize_table', (!hiddenPage || !!customCheck) && resetProps?.autoSizer && 'lm_page_info_table'),
summary: pageData => summary && summary(pageData, resultColumns, resetColumns()),
onRow: () => {
return {
style: rowStyle || {}
};
}
}))) : /*#__PURE__*/_react.default.createElement(_table.default, (0, _extends2.default)({}, config, {
ref: tableRef,
loading: loading,
dataSource: dataSource,
components: tableComponents,
onChange: onTableChange,
expandable: resetProps?.expandable || {
onExpand: () => {
shellStatusRef.current = {
start: {},
end: {},
selecting: false,
forceEdit: false,
editing: {},
clear: {},
commiting: {}
};
},
expandedRowKeys,
onExpandedRowsChange: expandedRows => setExpandedRowKeys(expandedRows)
},
className: (0, _classnames.default)('lm_protable', resizeable && 'lm_resizeable', resetProps?.autoSizer && 'lm_autosize_table', (!hiddenPage || !!customCheck) && resetProps?.autoSizer && 'lm_page_info_table'),
summary: pageData => summary && summary(pageData, resultColumns, resetColumns())
}))), !!customCheck && useSelectedRows?.selectedRows?.length > 1 && /*#__PURE__*/_react.default.createElement("div", {
className: "lm_customCheck"
}, customCheck), contextMenuStatus && /*#__PURE__*/_react.default.createElement("div", {
ref: contentMenuRef,
className: "WeChatContactsAvatarTools",
style: style
}, /*#__PURE__*/_react.default.createElement("div", {
className: "rightClickItems",
onClick: handleCopy
}, "\u590D\u5236"), /*#__PURE__*/_react.default.createElement("div", {
className: "rightClickItems",
onClick: handleCopyAll
}, "\u590D\u5236\u5168\u90E8")));
});
// 监听大小: 这里的高度是整个表格的高度,表体需要减去列头和分页的高度
/** 1: 使用scroll.x y 来控制宽高 默认都是100% */
const ResizeSize = /*#__PURE__*/(0, _react.forwardRef)((props, ref) => {
const {
autoSizer = false,
openRowGroup,
openColGroup,
groupHeight,
footer,
footerHeight,
summary,
summaryCustomFormrt
} = props;
const [tableSize, setTableSize] = (0, _react.useState)({
width: '100%',
height: '100%'
});
const defaultRef = ref || (0, _react.useRef)(null);
const tableWarpRef = (0, _react.useRef)(null);
const resizeRef = (0, _react.useRef)(null);
const clsName = (0, _classnames.default)(footer && 'lm_protable_with_footer');
const columnsSummer = (0, _react.useMemo)(() => {
if ((0, _lodash.isFunction)(summary)) {
return summary;
} else if ((0, _lodash.isObject)(summary)) {
return (pageData, columns, newColumns = []) => {
const {
expandable,
rowSelection
} = props;
const summaryColumns = (0, _lodash.compact)([expandable ? {
dataIndex: '_expandable'
} : null, rowSelection ? {
dataIndex: '_rowSelection'
} : null, ...newColumns]);
const resultCol = (0, _util.getLeafNodes)(summaryColumns);
return /*#__PURE__*/_react.default.createElement(_table.default.Summary, {
fixed: true
}, /*#__PURE__*/_react.default.createElement(_table.default.Summary.Row, null, resultCol.map(item => {
return /*#__PURE__*/_react.default.createElement(_table.default.Summary.Cell, {
align: item.align || 'left',
key: item?.dataIndex
}, (0, _lodash.isFunction)(summary[item.dataIndex]) ? summary[item.dataIndex]?.(pageData, item.dataIndex) : (0, _lodash.isBoolean)(summary[item.dataIndex]) ? summaryCustomFormrt ? summaryCustomFormrt(pageData, item.dataIndex) : (pageData || [])?.reduce((a, b) => {
return a + Number(b[item.dataIndex] || 0);
}, 0) :
// : sumBy(pageData, item?.dataIndex)
summary[item.dataIndex] ? summary[item.dataIndex] : '');
})));
};
}
return summary;
}, [summary]);
if (!autoSizer) {
return /*#__PURE__*/_react.default.createElement("div", {
ref: tableWarpRef,
className: clsName,
id: "lm_protable_warp no_auto_sizer",
style: {
width: '100%',
height: '100%'
}
}, /*#__PURE__*/_react.default.createElement(ResetTable, (0, _extends2.default)({
ref: defaultRef
}, props, {
summary: columnsSummer,
autoSize: {
height: '100%',
width: '100%'
}
})));
}
const resetHeight = (0, _react.useMemo)(() => {
const {
height
} = tableSize;
if (typeof height === 'string') {
return height;
}
// 头部高度
let h = height - (props.size === 'middle' ? 48 : 40);
if (!props.hiddenPage || props.customCheck) {
h -= 64;
}
if (props.columns.some(v => v.children)) {
h -= 32;
}
// 行列分组的高度
if (openRowGroup || openColGroup) {
h -= groupHeight || 102;
}
if (footer) {
h -= footerHeight || 54;
}
// safe area
if (h < 0) {
h = 0;
}
return h;
}, [props.hiddenPage, props.customCheck, props.columns, tableSize, footer, footerHeight, groupHeight]);
const changeSize = () => {
if (!tableWarpRef.current) {
return;
}
const value = props.summary ? 48 : 0;
const {
width = '100%',
height = '100%'
} = tableWarpRef.current.getBoundingClientRect() || {};
setTableSize({
width,
height: typeof height === 'string' ? `calc(${height} - ${value}px)` : height - value
});
};
const throttleSize = (0, _react.useCallback)(() => {
const {
width
} = tableSize;
return /*#__PURE__*/_react.default.createElement(ResetTable, (0, _extends2.default)({
ref: defaultRef
}, props, {
summary: columnsSummer,
changeSize: changeSize,
autoSize: {
height: resetHeight,
width
}
}));
}, [tableSize, props]);
const handResize = (0, _lodash.throttle)(changeSize, 600);
(0, _react.useEffect)(() => {
const {
summary
} = props;
setTimeout(() => {
if (!tableWarpRef.current) {
return;
}
const {
width = '100%',
height = '100%'
} = tableWarpRef.current.getBoundingClientRect();
const value = summary ? 48 : 0;
setTableSize({
width,
height: typeof height === 'string' ? `calc(${height} - ${value}px)` : height - value
});
}, 100);
resizeRef.current = window.addEventListener('resize', handResize);
return () => {
window.removeEventListener('resize', handResize);
};
}, []);
return /*#__PURE__*/_react.default.createElement("div", {
className: clsName,
ref: tableWarpRef,
id: "lm_protable_warp",
style: {
width: '100%',
height: '100%'
}
}, throttleSize());
});
var _default = /*#__PURE__*/(0, _react.memo)(ResizeSize);
exports.default = _default;