|
- /*
- * @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<T> = {
- /** 页数,类型为 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<TableCellFormatter> => {
- 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<TableCellFormatter> => {
- 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<T>(
- ellipsis: boolean | TooltipProps | 'auto' = false,
- 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;
- 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 (
- <Tooltip {...rest} overlayStyle={{ maxWidth: 400, ...overlayStyle }} title={text}>
- {renderCell(type, text, true, record, options)}
- </Tooltip>
- );
- } else {
- return renderCell(type, text, false, record, options);
- }
- };
- }
-
- function renderCell<T>(
- type: TableCellValueType,
- text: any | undefined | null,
- ellipsis: boolean | 'auto',
- record: T,
- options?: TableCellValueOptions<T>,
- ) {
- return type === TableCellValueType.Link
- ? renderLink(text, ellipsis, record, options)
- : renderText(text, ellipsis, options);
- }
-
- function renderLink<T>(
- text: any | undefined | null,
- ellipsis: boolean | 'auto',
- record: T,
- options?: TableCellValueOptions<T>,
- ) {
- const { onClick } = options ?? {};
- return (
- <a className="kf-table-row-link" onClick={(e) => onClick?.(record, e)}>
- {renderText(text, ellipsis, options)}
- </a>
- );
- }
-
- 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 }}
- 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>
- );
- }
-
- export default tableCellRender;
|