top-block-game-frontend/src/components/Table/index.tsx

273 lines
7.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { useMemo, useCallback, useState, useRef } from 'react';
import {
Button,
message,
Modal,
Space,
Divider,
AlertProps,
Alert,
Typography,
Tooltip,
} from 'antd';
import { PlusOutlined } from '@ant-design/icons';
import ProTable, { ProColumns, ActionType, ProTableProps } from '@ant-design/pro-table';
import { Access, useAccess } from 'umi';
export interface toolBarActionsItem {
type: 'add' | 'batchDelete';
permission?: string;
text?: string;
onConfirm: (val?: string[]) => void;
}
export interface PropsType extends ProTableProps<any, any> {
toolBarActions?: toolBarActionsItem[];
alertProps?: AlertProps;
indexColumn?: boolean | ProColumns<any, 'text'>;
}
type Record<K extends keyof any, T> = {
[P in K]: T;
};
const Table = <T extends Record<string, any>>(props: PropsType) => {
const access = useAccess();
const {
columns: columnsProps = [],
search: searchProps = {},
pagination: paginationProps,
options = false,
toolBarRender: toolBarRenderProps,
toolBarActions,
actionRef: actionRefProps,
rowSelection: rowSelectionProps,
toolbar: toolbarProps,
alertProps,
indexColumn,
} = props;
const defaultRef = useRef<ActionType>();
const actionRef: any = actionRefProps || defaultRef;
const [selectedRows, setSelectedRows] = useState<React.Key[]>([]);
// 暂时有批量删除的话替换rowSelection后续有发现问题再改
const rowSelection = useMemo(() => {
if (toolBarActions && toolBarActions.findIndex((item) => item.type === 'batchDelete') > -1) {
return {
selectedRowKeys: selectedRows,
onChange: setSelectedRows,
preserveSelectedRowKeys: true,
};
}
return rowSelectionProps
? {
preserveSelectedRowKeys: true,
...rowSelectionProps,
}
: false;
}, [rowSelectionProps, toolBarActions, setSelectedRows, selectedRows]);
const indexColumnValue = useMemo(() => {
if (!indexColumn) return [];
const rankItem = [
{
title: '序号',
dataIndex: 'index',
width: 80,
align: 'center',
search: false,
render: (_: any, item: any, index: number) => {
// @ts-ignore
const { current, pageSize } = actionRef.current?.pageInfo;
return index + 1 + (current - 1) * pageSize;
},
...(typeof indexColumn === 'object' ? indexColumn : {}),
},
];
return rankItem;
}, [indexColumn, actionRef]);
const columns = useMemo(() => {
const newColumns = columnsProps.map((item) => {
const optionRender = (_: any, val: any, ...rest: any) => {
return (
<Space size={0} split={<Divider type="vertical" />}>
{(item.render && (item.render(_, val, ...rest) as []))?.map((item2) => {
return item2;
})}
</Space>
);
};
let { render } = item;
if (item.valueType === 'option') {
render = optionRender;
}
return {
...item,
fieldProps:
item.valueType === 'select'
? {
...item.fieldProps,
showSearch: (item.fieldProps as any)?.options?.length > 8,
}
: item.fieldProps,
render,
};
});
return indexColumnValue.concat(newColumns);
}, [columnsProps, indexColumnValue]);
// search属性
const search = useMemo(() => {
if (searchProps === false) {
return searchProps;
}
return {
...searchProps,
optionRender: ({ searchText, resetText }, { form }) => [
<Button
key="search"
type="primary"
onClick={() => {
form?.submit();
}}
>
{searchText}
</Button>,
<Button
key="rest"
onClick={() => {
form?.resetFields();
form?.submit();
props.onReset && props.onReset();
}}
>
{resetText}
</Button>,
],
};
}, [searchProps, columnsProps]);
const handleBatchDelete = (action: any) => {
if (selectedRows.length === 0) {
message.warn('请选择要操作的项');
return;
}
Modal.confirm({
title: '提示',
content: '是否确认删除?',
okText: '确认',
cancelText: '取消',
onOk: () => {
action(selectedRows);
},
});
};
// 渲染toolbarActions自定义按钮
const toolBarActionsRender = useCallback(() => {
const buttonList: any = [];
toolBarActions &&
toolBarActions.forEach((item) => {
if (item.type === 'add') {
buttonList.push(
<Access accessible={access.canShowButton(item.permission)}>
<Button
key="add"
type="primary"
onClick={() => {
item.onConfirm();
}}
>
<PlusOutlined />
{item.text || '添加'}
</Button>
</Access>,
);
} else if (item.type === 'batchDelete') {
buttonList.push(
<Access accessible={access.canShowButton(item.permission)}>
<Button
key="del"
danger
onClick={() => {
handleBatchDelete(item.onConfirm);
}}
>
{item.text || '批量删除'}
</Button>
</Access>,
);
}
});
return buttonList;
}, [toolBarActions, selectedRows]);
// 渲染toolbar
const toolBarRender = useCallback(
(
action,
rows: {
selectedRowKeys?: (string | number)[];
selectedRows?: T[];
},
) => {
let toolRender = toolBarRenderProps ? toolBarRenderProps(action, rows) : toolBarRenderProps;
if (toolBarActions) {
const buttonList: any = toolBarActionsRender();
toolRender = toolRender ? toolRender.concat(buttonList) : buttonList;
}
return toolRender;
},
[toolBarRenderProps, toolBarActions, toolBarActionsRender],
);
// 分页统一为10条
const pagination = useMemo(() => {
if (paginationProps === undefined) {
return { defaultCurrent: 1, defaultPageSize: 10, pageSize: 10, current: 1 };
}
return paginationProps;
}, [paginationProps]);
// 渲染tip用toolbar的filter
const toolbar = useMemo(() => {
if (alertProps) {
return {
...toolbarProps,
multipleLine: true,
filter: <Alert {...alertProps} />,
};
}
return toolbarProps;
}, [alertProps, toolbarProps]);
return (
<div className="ls-table">
<ProTable<T>
{...{
...props,
search,
pagination,
columns,
rowSelection,
options,
toolbar,
toolBarRender: toolBarRenderProps || toolBarActions ? toolBarRender : toolBarRenderProps,
actionRef,
onLoad: (res) => {
if (res.length === 0 && actionRef?.current.pageInfo.current !== 1) {
actionRef?.current.setPageInfo({
...actionRef?.current.pageInfo,
current: actionRef?.current.pageInfo.current - 1,
});
}
},
}}
/>
</div>
);
};
export type { ProColumns, ActionType, ProTableProps };
export default Table;