ci4sManagement-cloud/react-ui/src/utils/table.tsx

223 lines
5.9 KiB
TypeScript
Raw Normal View History

2024-06-26 15:52:58 +08:00
/*
* @Author:
* @Date: 2024-06-26 10:05:52
2025-03-24 10:19:03 +08:00
* @Description: Table Cell render
2024-06-26 15:52:58 +08:00
*/
import { isEmpty } from '@/utils';
2024-06-26 15:52:58 +08:00
import { formatDate } from '@/utils/date';
import { Tooltip, TooltipProps, Typography } from 'antd';
2024-06-26 15:52:58 +08:00
import dayjs from 'dayjs';
2025-04-25 08:26:52 +08:00
import React from 'react';
import { formatEnum, type EnumOptions } from './format';
2024-06-26 15:52:58 +08:00
2024-10-17 10:52:45 +08:00
export enum TableCellValueType {
2025-03-31 10:49:34 +08:00
/** 序号 */
2024-10-17 10:52:45 +08:00
Index = 'Index',
2025-03-31 10:49:34 +08:00
/** 文本 */
2024-10-17 10:52:45 +08:00
Text = 'Text',
2025-03-31 10:49:34 +08:00
/** 日期 */
2024-10-17 10:52:45 +08:00
Date = 'Date',
2025-03-31 10:49:34 +08:00
/** 数组 */
2024-10-17 10:52:45 +08:00
Array = 'Array',
2025-03-31 10:49:34 +08:00
/** 链接 */
2024-10-17 10:52:45 +08:00
Link = 'Link',
2025-04-25 08:26:52 +08:00
/** 枚举 */
Enum = 'Enum',
2025-03-31 10:49:34 +08:00
/** 自定义 */
Custom = 'Custom',
2024-10-17 10:52:45 +08:00
}
2024-06-26 15:52:58 +08:00
2024-10-17 10:52:45 +08:00
export type TableCellValueOptions<T> = {
2025-03-31 10:49:34 +08:00
/** 页数,类型为 Index 时有效 */
page?: number;
/** 分页大小,类型为 Index 时有效 */
pageSize?: number;
/** 取数组对象的哪个属性值,类型为 Array 时有效 */
property?: string;
/** 日期格式,类型为 Date 时有效*/
dateFormat?: string;
/** 链接点击回调,类型为 Link 时有效 */
onClick?: (record: T, e: React.MouseEvent) => void;
2025-04-25 08:26:52 +08:00
/** 枚举选项,类型为 Enum 时有效*/
options?: EnumOptions[];
2025-03-31 10:49:34 +08:00
/** 自定义函数,类型为 Custom 时有效*/
2025-04-25 08:26:52 +08:00
format?: (
value: any | undefined | null,
record?: T,
index?: number,
) => React.ReactNode | undefined | null;
2025-03-31 10:49:34 +08:00
/** 省略时是否可以复制 */
copyable?: boolean;
2024-06-26 15:52:58 +08:00
};
2024-10-17 10:52:45 +08:00
type TableCellFormatter = (value: any | undefined | null) => string | undefined | null;
2025-03-31 10:49:34 +08:00
/**
*
* @param {string | undefined} dateFormat -
* @returns {TableCellFormatter} Table cell
*/
function formatDateText(dateFormat?: string): TableCellFormatter {
return (value: any | undefined | null): ReturnType<TableCellFormatter> => {
if (value === undefined || value === null || value === '') {
return null;
}
if (!dayjs(value).isValid()) {
return null;
}
return formatDate(value, dateFormat);
};
}
2024-06-26 15:52:58 +08:00
2024-10-17 10:52:45 +08:00
/**
*
2025-03-31 10:49:34 +08:00
* @param {string} property -
2024-10-17 10:52:45 +08:00
* @returns {TableCellFormatter} Table cell
*/
function formatArray(property?: string): TableCellFormatter {
return (value: any | undefined | null): ReturnType<TableCellFormatter> => {
2024-06-26 15:52:58 +08:00
if (
value === undefined ||
value === null ||
Array.isArray(value) === false ||
value.length === 0
) {
return null;
}
2024-10-17 10:52:45 +08:00
const list =
property && typeof value[0] === 'object' ? value.map((item) => item[property]) : value;
2024-06-26 15:52:58 +08:00
return list.join(',');
};
}
2025-03-31 10:49:34 +08:00
/**
* Table cell render
* @param ellipsis -
* @param type -
* @param options -
2025-04-11 16:18:10 +08:00
* @returns Ant Design Table render
2025-03-31 10:49:34 +08:00
*/
2024-10-17 10:52:45 +08:00
function tableCellRender<T>(
ellipsis: boolean | TooltipProps | 'auto' = false,
2024-10-17 10:52:45 +08:00
type: TableCellValueType = TableCellValueType.Text,
options?: TableCellValueOptions<T>,
) {
return (value: any | undefined | null, record: T, index: number) => {
let text = value;
switch (type) {
case TableCellValueType.Index:
text = (options?.page ?? 0) * (options?.pageSize ?? 0) + index + 1;
2024-10-17 10:52:45 +08:00
break;
case TableCellValueType.Text:
case TableCellValueType.Link:
text = value;
break;
case TableCellValueType.Date:
text = formatDateText(options?.dateFormat)(value);
2024-10-17 10:52:45 +08:00
break;
case TableCellValueType.Array:
text = formatArray(options?.property)(value);
break;
2025-04-25 08:26:52 +08:00
case TableCellValueType.Enum:
if (options?.options) {
text = formatEnum(options.options)(value);
}
break;
case TableCellValueType.Custom:
text = options?.format?.(value, record, index);
break;
2024-10-17 10:52:45 +08:00
default:
break;
}
if (ellipsis === 'auto' && text) {
2025-03-25 11:45:46 +08:00
return renderCell(type, text, 'auto', record, options);
} else if (ellipsis && text) {
const tooltipProps = typeof ellipsis === 'object' ? ellipsis : {};
const { overlayStyle, ...rest } = tooltipProps;
return (
<Tooltip {...rest} overlayStyle={{ maxWidth: 400, ...overlayStyle }} title={text}>
2025-03-25 11:45:46 +08:00
{renderCell(type, text, true, record, options)}
</Tooltip>
);
} else {
2025-03-25 11:45:46 +08:00
return renderCell(type, text, false, record, options);
}
2024-06-26 15:52:58 +08:00
};
}
2024-10-17 10:52:45 +08:00
function renderCell<T>(
type: TableCellValueType,
2024-10-17 10:52:45 +08:00
text: any | undefined | null,
ellipsis: boolean | 'auto',
2024-10-17 10:52:45 +08:00
record: T,
2025-03-25 11:45:46 +08:00
options?: TableCellValueOptions<T>,
2024-10-17 10:52:45 +08:00
) {
2025-03-10 17:01:25 +08:00
return type === TableCellValueType.Link
2025-03-25 11:45:46 +08:00
? renderLink(text, ellipsis, record, options)
: renderText(text, ellipsis, options);
2024-10-17 10:52:45 +08:00
}
function renderLink<T>(
text: any | undefined | null,
ellipsis: boolean | 'auto',
2024-10-17 10:52:45 +08:00
record: T,
2025-03-25 11:45:46 +08:00
options?: TableCellValueOptions<T>,
2024-10-17 10:52:45 +08:00
) {
2025-03-25 11:45:46 +08:00
const { onClick } = options ?? {};
2024-10-17 10:52:45 +08:00
return (
<a className="kf-table-row-link" onClick={(e) => onClick?.(record, e)}>
2025-03-25 11:45:46 +08:00
{renderText(text, ellipsis, options)}
2024-10-17 10:52:45 +08:00
</a>
);
}
2025-03-25 11:45:46 +08:00
function renderText<T>(
text: any | undefined | null,
ellipsis: boolean | 'auto',
options?: TableCellValueOptions<T>,
) {
const { copyable } = options ?? {};
if (ellipsis === 'auto') {
return (
<Typography.Paragraph
style={{ marginBottom: 0 }}
2025-03-25 11:45:46 +08:00
copyable={copyable}
ellipsis={{
tooltip: {
title: text,
destroyTooltipOnHide: true,
overlayStyle: { maxWidth: 400 },
},
}}
>
{!isEmpty(text) ? text : '--'}
</Typography.Paragraph>
);
}
return (
<span
style={
ellipsis
? {
whiteSpace: 'nowrap',
overflow: 'hidden',
textOverflow: 'ellipsis',
wordBreak: 'break-all',
display: 'inline-block',
maxWidth: '100%',
verticalAlign: 'middle',
}
: undefined
}
>
{!isEmpty(text) ? text : '--'}
</span>
);
}
2024-06-26 15:52:58 +08:00
export default tableCellRender;