|
- import TableColTitle from '@/components/TableColTitle';
- import TrialStatusCell from '@/pages/HyperParameter/components/TrialStatusCell';
- import { HyperParameterTrial } from '@/pages/HyperParameter/types';
- import { getExpMetricsReq } from '@/services/hyperParameter';
- import { to } from '@/utils/promise';
- import SessionStorage from '@/utils/sessionStorage';
- import tableCellRender, { TableCellValueType } from '@/utils/table';
- import { useNavigate } from '@umijs/max';
- import { App, Button, Table, type TableProps } from 'antd';
- import classNames from 'classnames';
- import { useEffect, useState } from 'react';
- import TrialFileTree from '../TrialFileTree';
- import styles from './index.less';
-
- type ExperimentHistoryProps = {
- trialList?: HyperParameterTrial[];
- };
-
- function ExperimentHistory({ trialList = [] }: ExperimentHistoryProps) {
- const [expandedRowKeys, setExpandedRowKeys] = useState<string[]>([]);
- const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
- const { message } = App.useApp();
- const [tableData, setTableData] = useState<HyperParameterTrial[]>([]);
- const [loading, setLoading] = useState(false);
-
- // 防止 Tabs 卡顿
- useEffect(() => {
- setLoading(true);
- setTimeout(() => {
- setTableData(trialList);
- setLoading(false);
- }, 500);
- }, [trialList]);
-
- // 计算 column
- const first: HyperParameterTrial | undefined = trialList ? trialList[0] : undefined;
- const config: Record<string, any> = first?.config ?? {};
- const metricAnalysis: Record<string, any> = first?.metric_analysis ?? {};
- const paramsNames = Object.keys(config);
- const metricNames = Object.keys(metricAnalysis);
- const navigate = useNavigate();
-
- const trialColumns: TableProps<HyperParameterTrial>['columns'] = [
- {
- title: '序号',
- dataIndex: 'index',
- key: 'index',
- width: 100,
- fixed: 'left',
- render: (_text, record, index: number) => {
- return (
- <div className={styles['cell-index']}>
- <span className={styles['cell-index__text']}>{index + 1}</span>
- {record.is_best && <span className={styles['cell-index__best-tag']}>最佳</span>}
- </div>
- );
- },
- },
- {
- title: '基本信息',
- align: 'center',
- children: [
- {
- title: '运行次数',
- dataIndex: 'training_iteration',
- key: 'training_iteration',
- width: 120,
- fixed: 'left',
- render: tableCellRender(false),
- },
- {
- title: '平均时长(秒)',
- dataIndex: 'time_avg',
- key: 'time_avg',
- width: 150,
- fixed: 'left',
- render: tableCellRender(false, TableCellValueType.Custom, {
- format: (value = 0) => Number(value).toFixed(2),
- }),
- },
- {
- title: '状态',
- dataIndex: 'status',
- key: 'status',
- width: 120,
- fixed: 'left',
- render: TrialStatusCell,
- },
- ],
- },
- ];
-
- if (paramsNames.length) {
- trialColumns.push({
- title: '运行参数',
- dataIndex: 'config',
- key: 'config',
- align: 'center',
- children: paramsNames.map((name) => ({
- title: <TableColTitle title={name} />,
- dataIndex: ['config', name],
- key: name,
- width: 120,
- align: 'center',
- render: tableCellRender(true),
- })),
- });
- }
-
- if (metricNames.length) {
- trialColumns.push({
- title: `指标分析(${first?.metric ?? ''})`,
- dataIndex: 'metrics',
- key: 'metrics',
- align: 'center',
- children: metricNames.map((name) => ({
- title: <TableColTitle title={name} />,
- dataIndex: ['metric_analysis', name],
- key: name,
- width: 120,
- align: 'center',
- render: tableCellRender(true),
- })),
- });
- }
-
- // 自定义展开视图
- const expandedRowRender = (record: HyperParameterTrial) => {
- return <TrialFileTree title="寻优结果" file={record.file}></TrialFileTree>;
- };
-
- // 展开实例
- const handleExpandChange = (expanded: boolean, record: HyperParameterTrial) => {
- if (expanded) {
- setExpandedRowKeys([record.trial_id]);
- } else {
- setExpandedRowKeys([]);
- }
- };
-
- // 选择行
- const rowSelection: TableProps<HyperParameterTrial>['rowSelection'] = {
- type: 'checkbox',
- columnWidth: 48,
- fixed: 'left',
- selectedRowKeys,
- onChange: (selectedRowKeys: React.Key[]) => {
- setSelectedRowKeys(selectedRowKeys);
- },
- };
-
- // 对比
- const handleComparisonClick = () => {
- if (selectedRowKeys.length < 1) {
- message.error('请至少选择一项');
- return;
- }
- getExpMetrics();
- };
-
- // 获取对比 url
- const getExpMetrics = async () => {
- const [res] = await to(getExpMetricsReq(selectedRowKeys));
- if (res && res.data) {
- const url = res.data;
- SessionStorage.setItem(SessionStorage.aimUrlKey, url);
- navigate('compare-visual');
- }
- };
-
- return (
- <div className={styles['experiment-history']}>
- <div className={styles['experiment-history__content']}>
- <Button type="default" onClick={handleComparisonClick}>
- 可视化对比
- </Button>
- <div
- className={classNames(
- 'vertical-scroll-table-no-page',
- styles['experiment-history__content__table'],
- )}
- >
- <Table
- loading={loading}
- rowClassName={(record) => (record.is_best ? styles['table-best-row'] : '')}
- dataSource={tableData}
- columns={trialColumns}
- pagination={false}
- bordered={true}
- scroll={{ y: 'calc(100% - 110px)', x: '100%' }}
- rowKey="trial_id"
- expandable={{
- expandedRowRender: expandedRowRender,
- onExpand: handleExpandChange,
- expandedRowKeys: expandedRowKeys,
- rowExpandable: (record: HyperParameterTrial) => !!record.file,
- }}
- rowSelection={rowSelection}
- />
- </div>
- </div>
- </div>
- );
- }
-
- export default ExperimentHistory;
|