/* * @Author: 赵伟 * @Date: 2024-06-26 10:05:52 * @Description: Table Cell 自定义 render */ import { isEmpty } from '@/utils'; import { formatDate } from '@/utils/date'; import { Tooltip, TooltipProps, Typography } from 'antd'; import dayjs from 'dayjs'; import React from 'react'; import { formatEnum, type EnumOptions } from './format'; export enum TableCellValueType { /** 序号 */ Index = 'Index', /** 文本 */ Text = 'Text', /** 日期 */ Date = 'Date', /** 数组 */ Array = 'Array', /** 链接 */ Link = 'Link', /** 枚举 */ Enum = 'Enum', /** 自定义 */ Custom = 'Custom', } export type TableCellValueOptions = { /** 页数,类型为 Index 时有效 */ page?: number; /** 分页大小,类型为 Index 时有效 */ pageSize?: number; /** 取数组对象的哪个属性值,类型为 Array 时有效 */ property?: string; /** 日期格式,类型为 Date 时有效*/ dateFormat?: string; /** 链接点击回调,类型为 Link 时有效 */ onClick?: (record: T, e: React.MouseEvent) => void; /** 枚举选项,类型为 Enum 时有效*/ options?: EnumOptions[]; /** 自定义函数,类型为 Custom 时有效*/ format?: ( value: any | undefined | null, record?: T, index?: number, ) => React.ReactNode | undefined | null; /** 省略时是否可以复制 */ copyable?: boolean; }; type TableCellFormatter = (value: any | undefined | null) => string | undefined | null; /** * 日期转换函数 * @param {string | undefined} dateFormat - 日期格式 * @returns {TableCellFormatter} Table cell 渲染函数 */ function formatDateText(dateFormat?: string): TableCellFormatter { return (value: any | undefined | null): ReturnType => { if (value === undefined || value === null || value === '') { return null; } if (!dayjs(value).isValid()) { return null; } return formatDate(value, dateFormat); }; } /** * 数组转换函数,将数组元素转换为字符串,用逗号分隔 * @param {string} property - 如果数组元素是对象,那么取数组元素的某个属性 * @returns {TableCellFormatter} Table cell 渲染函数 */ function formatArray(property?: string): TableCellFormatter { return (value: any | undefined | null): ReturnType => { if ( value === undefined || value === null || Array.isArray(value) === false || value.length === 0 ) { return null; } const list = property && typeof value[0] === 'object' ? value.map((item) => item[property]) : value; return list.join(','); }; } /** * Table cell render 函数 * @param ellipsis - 是否省略 * @param type - 类型 * @param options - 选项 * @returns Ant Design Table 的 render */ function tableCellRender( ellipsis: boolean | TooltipProps | 'auto' = false, type: TableCellValueType = TableCellValueType.Text, options?: TableCellValueOptions, ) { 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; break; case TableCellValueType.Text: case TableCellValueType.Link: text = value; break; case TableCellValueType.Date: text = formatDateText(options?.dateFormat)(value); break; case TableCellValueType.Array: text = formatArray(options?.property)(value); break; case TableCellValueType.Enum: if (options?.options) { text = formatEnum(options.options)(value); } break; case TableCellValueType.Custom: text = options?.format?.(value, record, index); break; default: break; } if (ellipsis === 'auto' && text) { return renderCell(type, text, 'auto', record, options); } else if (ellipsis && text) { const tooltipProps = typeof ellipsis === 'object' ? ellipsis : {}; const { overlayStyle, ...rest } = tooltipProps; return ( {renderCell(type, text, true, record, options)} ); } else { return renderCell(type, text, false, record, options); } }; } function renderCell( type: TableCellValueType, text: any | undefined | null, ellipsis: boolean | 'auto', record: T, options?: TableCellValueOptions, ) { return type === TableCellValueType.Link ? renderLink(text, ellipsis, record, options) : renderText(text, ellipsis, options); } function renderLink( text: any | undefined | null, ellipsis: boolean | 'auto', record: T, options?: TableCellValueOptions, ) { const { onClick } = options ?? {}; return ( onClick?.(record, e)}> {renderText(text, ellipsis, options)} ); } function renderText( text: any | undefined | null, ellipsis: boolean | 'auto', options?: TableCellValueOptions, ) { const { copyable } = options ?? {}; if (ellipsis === 'auto') { return ( {!isEmpty(text) ? text : '--'} ); } return ( {!isEmpty(text) ? text : '--'} ); } export default tableCellRender;