| @@ -69,35 +69,30 @@ function ExperimentHistory({ fileUrl, isClassification }: ExperimentHistoryProps | |||||
| dataIndex: 'accuracy', | dataIndex: 'accuracy', | ||||
| key: 'accuracy', | key: 'accuracy', | ||||
| render: tableCellRender(true), | render: tableCellRender(true), | ||||
| ellipsis: { showTitle: false }, | |||||
| }, | }, | ||||
| { | { | ||||
| title: '耗时', | title: '耗时', | ||||
| dataIndex: 'duration', | dataIndex: 'duration', | ||||
| key: 'duration', | key: 'duration', | ||||
| render: tableCellRender(true), | render: tableCellRender(true), | ||||
| ellipsis: { showTitle: false }, | |||||
| }, | }, | ||||
| { | { | ||||
| title: '训练损失', | title: '训练损失', | ||||
| dataIndex: 'train_loss', | dataIndex: 'train_loss', | ||||
| key: 'train_loss', | key: 'train_loss', | ||||
| render: tableCellRender(true), | render: tableCellRender(true), | ||||
| ellipsis: { showTitle: false }, | |||||
| }, | }, | ||||
| { | { | ||||
| title: '特征处理', | title: '特征处理', | ||||
| dataIndex: 'feature', | dataIndex: 'feature', | ||||
| key: 'feature', | key: 'feature', | ||||
| render: tableCellRender(true), | render: tableCellRender(true), | ||||
| ellipsis: { showTitle: false }, | |||||
| }, | }, | ||||
| { | { | ||||
| title: '算法', | title: '算法', | ||||
| dataIndex: 'althorithm', | dataIndex: 'althorithm', | ||||
| key: 'althorithm', | key: 'althorithm', | ||||
| render: tableCellRender(true), | render: tableCellRender(true), | ||||
| ellipsis: { showTitle: false }, | |||||
| }, | }, | ||||
| { | { | ||||
| title: '状态', | title: '状态', | ||||
| @@ -261,7 +261,6 @@ function ExperimentList({ type }: ExperimentListProps) { | |||||
| dataIndex: config.descProperty, | dataIndex: config.descProperty, | ||||
| key: 'ml_description', | key: 'ml_description', | ||||
| render: tableCellRender(true), | render: tableCellRender(true), | ||||
| ellipsis: { showTitle: false }, | |||||
| }, | }, | ||||
| { | { | ||||
| @@ -269,8 +268,7 @@ function ExperimentList({ type }: ExperimentListProps) { | |||||
| dataIndex: 'update_time', | dataIndex: 'update_time', | ||||
| key: 'update_time', | key: 'update_time', | ||||
| width: '20%', | width: '20%', | ||||
| render: tableCellRender(true, TableCellValueType.Date), | |||||
| ellipsis: { showTitle: false }, | |||||
| render: tableCellRender(false, TableCellValueType.Date), | |||||
| }, | }, | ||||
| { | { | ||||
| title: '最近五次运行状态', | title: '最近五次运行状态', | ||||
| @@ -154,7 +154,6 @@ function ExperimentComparison() { | |||||
| fixed: 'left', | fixed: 'left', | ||||
| align: 'center', | align: 'center', | ||||
| render: tableCellRender(true, TableCellValueType.Array), | render: tableCellRender(true, TableCellValueType.Array), | ||||
| ellipsis: { showTitle: false }, | |||||
| }, | }, | ||||
| ], | ], | ||||
| }, | }, | ||||
| @@ -172,7 +171,6 @@ function ExperimentComparison() { | |||||
| width: 120, | width: 120, | ||||
| align: 'center', | align: 'center', | ||||
| render: tableCellRender(true), | render: tableCellRender(true), | ||||
| ellipsis: { showTitle: false }, | |||||
| sorter: (a, b) => tableSorter(a.params?.[name], b.params?.[name]), | sorter: (a, b) => tableSorter(a.params?.[name], b.params?.[name]), | ||||
| showSorterTooltip: false, | showSorterTooltip: false, | ||||
| })), | })), | ||||
| @@ -191,7 +189,6 @@ function ExperimentComparison() { | |||||
| width: 120, | width: 120, | ||||
| align: 'center', | align: 'center', | ||||
| render: tableCellRender(true), | render: tableCellRender(true), | ||||
| ellipsis: { showTitle: false }, | |||||
| sorter: (a, b) => tableSorter(a.metrics?.[name], b.metrics?.[name]), | sorter: (a, b) => tableSorter(a.metrics?.[name], b.metrics?.[name]), | ||||
| showSorterTooltip: false, | showSorterTooltip: false, | ||||
| })), | })), | ||||
| @@ -383,7 +383,7 @@ function Experiment() { | |||||
| title: '实验名称', | title: '实验名称', | ||||
| dataIndex: 'name', | dataIndex: 'name', | ||||
| key: 'name', | key: 'name', | ||||
| render: tableCellRender(), | |||||
| render: tableCellRender(false), | |||||
| width: '16%', | width: '16%', | ||||
| }, | }, | ||||
| { | { | ||||
| @@ -400,7 +400,6 @@ function Experiment() { | |||||
| dataIndex: 'description', | dataIndex: 'description', | ||||
| key: 'description', | key: 'description', | ||||
| render: tableCellRender(true), | render: tableCellRender(true), | ||||
| ellipsis: { showTitle: false }, | |||||
| }, | }, | ||||
| { | { | ||||
| title: '最近五次运行状态', | title: '最近五次运行状态', | ||||
| @@ -8,7 +8,7 @@ import { to } from '@/utils/promise'; | |||||
| import tableCellRender, { TableCellValueType } from '@/utils/table'; | import tableCellRender, { TableCellValueType } from '@/utils/table'; | ||||
| import { App, Button, Table, Tooltip, Tree, type TableProps, type TreeDataNode } from 'antd'; | import { App, Button, Table, Tooltip, Tree, type TableProps, type TreeDataNode } from 'antd'; | ||||
| import classNames from 'classnames'; | import classNames from 'classnames'; | ||||
| import { useState } from 'react'; | |||||
| import { useEffect, useState } from 'react'; | |||||
| import styles from './index.less'; | import styles from './index.less'; | ||||
| const { DirectoryTree } = Tree; | const { DirectoryTree } = Tree; | ||||
| @@ -22,13 +22,16 @@ function ExperimentHistory({ trialList = [] }: ExperimentHistoryProps) { | |||||
| const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]); | const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]); | ||||
| const { message } = App.useApp(); | const { message } = App.useApp(); | ||||
| const [tableData, setTableData] = useState<HyperParameterTrial[]>([]); | const [tableData, setTableData] = useState<HyperParameterTrial[]>([]); | ||||
| const [loading, setLoading] = useState(true); | |||||
| const [loading, setLoading] = useState(false); | |||||
| // 防止 Tabs 卡顿 | // 防止 Tabs 卡顿 | ||||
| setTimeout(() => { | |||||
| setTableData(trialList); | |||||
| setLoading(false); | |||||
| }, 100); | |||||
| useEffect(() => { | |||||
| setLoading(true); | |||||
| setTimeout(() => { | |||||
| setTableData(trialList); | |||||
| setLoading(false); | |||||
| }, 500); | |||||
| }, []); | |||||
| // 计算 column | // 计算 column | ||||
| const first: HyperParameterTrial | undefined = trialList[0]; | const first: HyperParameterTrial | undefined = trialList[0]; | ||||
| @@ -67,7 +70,6 @@ function ExperimentHistory({ trialList = [] }: ExperimentHistoryProps) { | |||||
| render: tableCellRender(false, TableCellValueType.Custom, { | render: tableCellRender(false, TableCellValueType.Custom, { | ||||
| format: (value = 0) => Number(value).toFixed(2), | format: (value = 0) => Number(value).toFixed(2), | ||||
| }), | }), | ||||
| ellipsis: { showTitle: false }, | |||||
| }, | }, | ||||
| { | { | ||||
| title: '状态', | title: '状态', | ||||
| @@ -95,8 +97,6 @@ function ExperimentHistory({ trialList = [] }: ExperimentHistoryProps) { | |||||
| width: 120, | width: 120, | ||||
| align: 'center', | align: 'center', | ||||
| render: tableCellRender(true), | render: tableCellRender(true), | ||||
| ellipsis: { showTitle: false }, | |||||
| showSorterTooltip: false, | |||||
| })), | })), | ||||
| }); | }); | ||||
| } | } | ||||
| @@ -118,8 +118,6 @@ function ExperimentHistory({ trialList = [] }: ExperimentHistoryProps) { | |||||
| width: 120, | width: 120, | ||||
| align: 'center', | align: 'center', | ||||
| render: tableCellRender(true), | render: tableCellRender(true), | ||||
| ellipsis: { showTitle: false }, | |||||
| showSorterTooltip: false, | |||||
| })), | })), | ||||
| }); | }); | ||||
| } | } | ||||
| @@ -43,16 +43,14 @@ function ParameterInfo({ info }: ParameterInfoProps) { | |||||
| dataIndex: 'name', | dataIndex: 'name', | ||||
| key: 'type', | key: 'type', | ||||
| width: '40%', | width: '40%', | ||||
| render: tableCellRender(true), | |||||
| ellipsis: { showTitle: false }, | |||||
| render: tableCellRender('auto'), | |||||
| }, | }, | ||||
| { | { | ||||
| title: '参数类型', | title: '参数类型', | ||||
| dataIndex: 'type', | dataIndex: 'type', | ||||
| key: 'type', | key: 'type', | ||||
| width: '20%', | width: '20%', | ||||
| render: tableCellRender(true), | |||||
| ellipsis: { showTitle: false }, | |||||
| render: tableCellRender(false), | |||||
| }, | }, | ||||
| { | { | ||||
| title: '取值范围', | title: '取值范围', | ||||
| @@ -64,7 +62,6 @@ function ParameterInfo({ info }: ParameterInfoProps) { | |||||
| return JSON.stringify(value); | return JSON.stringify(value); | ||||
| }, | }, | ||||
| }), | }), | ||||
| ellipsis: { showTitle: false }, | |||||
| }, | }, | ||||
| ]; | ]; | ||||
| @@ -81,7 +78,6 @@ function ParameterInfo({ info }: ParameterInfoProps) { | |||||
| key: name, | key: name, | ||||
| width: 150, | width: 150, | ||||
| render: tableCellRender(true), | render: tableCellRender(true), | ||||
| ellipsis: { showTitle: false }, | |||||
| }; | }; | ||||
| }) | }) | ||||
| : []; | : []; | ||||
| @@ -192,7 +192,6 @@ function MirrorList() { | |||||
| key: 'description', | key: 'description', | ||||
| width: '35%', | width: '35%', | ||||
| render: tableCellRender(true), | render: tableCellRender(true), | ||||
| ellipsis: { showTitle: false }, | |||||
| }, | }, | ||||
| { | { | ||||
| title: '创建时间', | title: '创建时间', | ||||
| @@ -184,7 +184,6 @@ function ModelMetrics({ resourceId, identifier, owner, version }: ModelMetricsPr | |||||
| width: 120, | width: 120, | ||||
| align: 'center', | align: 'center', | ||||
| render: tableCellRender(true), | render: tableCellRender(true), | ||||
| ellipsis: { showTitle: false }, | |||||
| sorter: (a, b) => tableSorter(a.params?.[name], b.params?.[name]), | sorter: (a, b) => tableSorter(a.params?.[name], b.params?.[name]), | ||||
| showSorterTooltip: false, | showSorterTooltip: false, | ||||
| })), | })), | ||||
| @@ -223,7 +222,6 @@ function ModelMetrics({ resourceId, identifier, owner, version }: ModelMetricsPr | |||||
| width: 120, | width: 120, | ||||
| align: 'center', | align: 'center', | ||||
| render: tableCellRender(true), | render: tableCellRender(true), | ||||
| ellipsis: { showTitle: false }, | |||||
| sorter: (a, b) => tableSorter(a.metrics?.[name], b.metrics?.[name]), | sorter: (a, b) => tableSorter(a.metrics?.[name], b.metrics?.[name]), | ||||
| showSorterTooltip: false, | showSorterTooltip: false, | ||||
| })), | })), | ||||
| @@ -285,7 +285,6 @@ function ServiceInfo() { | |||||
| key: 'model', | key: 'model', | ||||
| width: '20%', | width: '20%', | ||||
| render: tableCellRender(true), | render: tableCellRender(true), | ||||
| ellipsis: { showTitle: false }, | |||||
| }, | }, | ||||
| { | { | ||||
| title: '状态', | title: '状态', | ||||
| @@ -300,7 +299,6 @@ function ServiceInfo() { | |||||
| key: 'image', | key: 'image', | ||||
| width: '20%', | width: '20%', | ||||
| render: tableCellRender(true), | render: tableCellRender(true), | ||||
| ellipsis: { showTitle: false }, | |||||
| }, | }, | ||||
| { | { | ||||
| title: '副本数量', | title: '副本数量', | ||||
| @@ -317,7 +315,6 @@ function ServiceInfo() { | |||||
| render: tableCellRender(true, TableCellValueType.Custom, { | render: tableCellRender(true, TableCellValueType.Custom, { | ||||
| format: getResourceDescription, | format: getResourceDescription, | ||||
| }), | }), | ||||
| ellipsis: { showTitle: false }, | |||||
| }, | }, | ||||
| { | { | ||||
| title: '操作', | title: '操作', | ||||
| @@ -161,7 +161,6 @@ const Pipeline = () => { | |||||
| dataIndex: 'description', | dataIndex: 'description', | ||||
| key: 'description', | key: 'description', | ||||
| render: tableCellRender(true), | render: tableCellRender(true), | ||||
| ellipsis: { showTitle: false }, | |||||
| }, | }, | ||||
| { | { | ||||
| title: '创建时间', | title: '创建时间', | ||||
| @@ -6,7 +6,7 @@ | |||||
| import { isEmpty } from '@/utils'; | import { isEmpty } from '@/utils'; | ||||
| import { formatDate } from '@/utils/date'; | import { formatDate } from '@/utils/date'; | ||||
| import { Typography } from 'antd'; | |||||
| import { Tooltip, TooltipProps, Typography } from 'antd'; | |||||
| import dayjs from 'dayjs'; | import dayjs from 'dayjs'; | ||||
| export enum TableCellValueType { | export enum TableCellValueType { | ||||
| @@ -65,7 +65,7 @@ function formatArray(property?: string): TableCellFormatter { | |||||
| } | } | ||||
| function tableCellRender<T>( | function tableCellRender<T>( | ||||
| ellipsis: boolean = false, | |||||
| ellipsis: boolean | TooltipProps | 'auto' = false, | |||||
| type: TableCellValueType = TableCellValueType.Text, | type: TableCellValueType = TableCellValueType.Text, | ||||
| options?: TableCellValueOptions<T>, | options?: TableCellValueOptions<T>, | ||||
| ) { | ) { | ||||
| @@ -92,14 +92,26 @@ function tableCellRender<T>( | |||||
| break; | break; | ||||
| } | } | ||||
| return renderCell(text, ellipsis, type, record, options?.onClick); | |||||
| if (ellipsis === 'auto' && text) { | |||||
| return renderCell(type, text, 'auto', record, options?.onClick); | |||||
| } 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?.onClick)} | |||||
| </Tooltip> | |||||
| ); | |||||
| } else { | |||||
| return renderCell(type, text, false, record, options?.onClick); | |||||
| } | |||||
| }; | }; | ||||
| } | } | ||||
| function renderCell<T>( | function renderCell<T>( | ||||
| type: TableCellValueType, | |||||
| text: any | undefined | null, | text: any | undefined | null, | ||||
| ellipsis: boolean, | |||||
| type: TableCellValueType = TableCellValueType.Text, | |||||
| ellipsis: boolean | 'auto', | |||||
| record: T, | record: T, | ||||
| onClick?: (record: T, e: React.MouseEvent) => void, | onClick?: (record: T, e: React.MouseEvent) => void, | ||||
| ) { | ) { | ||||
| @@ -108,30 +120,9 @@ function renderCell<T>( | |||||
| : renderText(text, ellipsis); | : renderText(text, ellipsis); | ||||
| } | } | ||||
| function renderText(text: any | undefined | null, ellipsis: boolean) { | |||||
| return ( | |||||
| <Typography.Paragraph | |||||
| style={{ marginBottom: 0 }} | |||||
| ellipsis={ | |||||
| ellipsis && !isEmpty(text) | |||||
| ? { | |||||
| tooltip: { | |||||
| title: text, | |||||
| destroyTooltipOnHide: true, | |||||
| overlayStyle: { maxWidth: 400 }, | |||||
| }, | |||||
| } | |||||
| : false | |||||
| } | |||||
| > | |||||
| {!isEmpty(text) ? text : '--'} | |||||
| </Typography.Paragraph> | |||||
| ); | |||||
| } | |||||
| function renderLink<T>( | function renderLink<T>( | ||||
| text: any | undefined | null, | text: any | undefined | null, | ||||
| ellipsis: boolean, | |||||
| ellipsis: boolean | 'auto', | |||||
| record: T, | record: T, | ||||
| onClick?: (record: T, e: React.MouseEvent) => void, | onClick?: (record: T, e: React.MouseEvent) => void, | ||||
| ) { | ) { | ||||
| @@ -142,4 +133,42 @@ function renderLink<T>( | |||||
| ); | ); | ||||
| } | } | ||||
| function renderText(text: any | undefined | null, ellipsis: boolean | 'auto') { | |||||
| if (ellipsis === 'auto') { | |||||
| return ( | |||||
| <Typography.Paragraph | |||||
| style={{ marginBottom: 0 }} | |||||
| 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%', | |||||
| } | |||||
| : undefined | |||||
| } | |||||
| > | |||||
| {!isEmpty(text) ? text : '--'} | |||||
| </span> | |||||
| ); | |||||
| } | |||||
| export default tableCellRender; | export default tableCellRender; | ||||