Browse Source

feat: 统一格式化数据集、模型、代码配置等

pull/171/head
cp3hnu 1 year ago
parent
commit
45f440b348
18 changed files with 374 additions and 286 deletions
  1. +6
    -55
      react-ui/src/components/BasicInfo/BasicInfoItem.tsx
  2. +54
    -0
      react-ui/src/components/BasicInfo/BasicInfoItemValue.tsx
  3. +0
    -48
      react-ui/src/components/BasicInfo/format.ts
  4. +1
    -2
      react-ui/src/components/BasicInfo/index.tsx
  5. +2
    -2
      react-ui/src/components/BasicInfo/types.ts
  6. +1
    -2
      react-ui/src/components/BasicTableInfo/index.tsx
  7. +2
    -7
      react-ui/src/pages/AutoML/components/AutoMLBasic/index.tsx
  8. +0
    -1
      react-ui/src/pages/AutoML/components/ConfigInfo/index.tsx
  9. +65
    -26
      react-ui/src/pages/HyperParameter/components/CreateForm/ExecuteConfig.tsx
  10. +22
    -0
      react-ui/src/pages/HyperParameter/components/CreateForm/index.less
  11. +17
    -9
      react-ui/src/pages/HyperParameter/components/HyperParameterBasic/index.tsx
  12. +1
    -2
      react-ui/src/pages/HyperParameter/types.ts
  13. +11
    -3
      react-ui/src/pages/ModelDeployment/CreateVersion/index.tsx
  14. +2
    -2
      react-ui/src/pages/ModelDeployment/VersionInfo/index.tsx
  15. +0
    -120
      react-ui/src/pages/ModelDeployment/components/BasicInfo/index.tsx
  16. +0
    -0
      react-ui/src/pages/ModelDeployment/components/VersionBasicInfo/index.less
  17. +134
    -0
      react-ui/src/pages/ModelDeployment/components/VersionBasicInfo/index.tsx
  18. +56
    -7
      react-ui/src/utils/format.ts

react-ui/src/components/BasicInfo/components.tsx → react-ui/src/components/BasicInfo/BasicInfoItem.tsx View File

@@ -4,9 +4,8 @@
* @Description: 用于 BasicInfo 和 BasicTableInfo 组件的子组件
*/

import { Link } from '@umijs/max';
import { Typography } from 'antd';
import React from 'react';
import BasicInfoItemValue from './BasicInfoItemValue';
import { type BasicInfoData, type BasicInfoLink } from './types';

type BasicInfoItemProps = {
@@ -15,12 +14,14 @@ type BasicInfoItemProps = {
classPrefix: string;
};

export function BasicInfoItem({ data, labelWidth, classPrefix }: BasicInfoItemProps) {
function BasicInfoItem({ data, labelWidth, classPrefix }: BasicInfoItemProps) {
const { label, value, format, ellipsis } = data;
const formatValue = format ? format(value) : value;
const myClassName = `${classPrefix}__item`;
let valueComponent = undefined;
if (Array.isArray(formatValue)) {
if (React.isValidElement(formatValue)) {
valueComponent = formatValue;
} else if (Array.isArray(formatValue)) {
valueComponent = (
<div className={`${myClassName}__value-container`}>
{formatValue.map((item: BasicInfoLink) => (
@@ -35,11 +36,6 @@ export function BasicInfoItem({ data, labelWidth, classPrefix }: BasicInfoItemPr
))}
</div>
);
} else if (React.isValidElement(formatValue)) {
// 这个判断必须在下面的判断之前
valueComponent = (
<BasicInfoItemValue value={formatValue} ellipsis={ellipsis} classPrefix={classPrefix} />
);
} else if (typeof formatValue === 'object' && formatValue) {
valueComponent = (
<BasicInfoItemValue
@@ -65,49 +61,4 @@ export function BasicInfoItem({ data, labelWidth, classPrefix }: BasicInfoItemPr
);
}

type BasicInfoItemValueProps = {
ellipsis?: boolean;
classPrefix: string;
value: string | React.ReactNode;
link?: string;
url?: string;
};

export function BasicInfoItemValue({
value,
link,
url,
ellipsis,
classPrefix,
}: BasicInfoItemValueProps) {
const myClassName = `${classPrefix}__item__value`;
let component = undefined;
if (url && value) {
component = (
<a className={`${myClassName}__link`} href={url} target="_blank" rel="noopener noreferrer">
{value}
</a>
);
} else if (link && value) {
component = (
<Link to={link} className={`${myClassName}__link`}>
{value}
</Link>
);
} else if (React.isValidElement(value)) {
return value;
} else {
component = <span className={`${myClassName}__text`}>{value ?? '--'}</span>;
}

return (
<div className={myClassName}>
<Typography.Text
ellipsis={ellipsis ? { tooltip: value } : false}
style={{ fontSize: 'inherit' }}
>
{component}
</Typography.Text>
</div>
);
}
export default BasicInfoItem;

+ 54
- 0
react-ui/src/components/BasicInfo/BasicInfoItemValue.tsx View File

@@ -0,0 +1,54 @@
/*
* @Author: 赵伟
* @Date: 2024-11-29 09:27:19
* @Description: 用于 BasicInfoItem 的组件
*/

import { Link } from '@umijs/max';
import { Typography } from 'antd';
import React from 'react';

type BasicInfoItemValueProps = {
ellipsis?: boolean;
classPrefix: string;
value: string | React.ReactNode;
link?: string;
url?: string;
};

function BasicInfoItemValue({ value, link, url, ellipsis, classPrefix }: BasicInfoItemValueProps) {
if (React.isValidElement(value)) {
return value;
}

const myClassName = `${classPrefix}__item__value`;
let component = undefined;
if (url && value) {
component = (
<a className={`${myClassName}__link`} href={url} target="_blank" rel="noopener noreferrer">
{value}
</a>
);
} else if (link && value) {
component = (
<Link to={link} className={`${myClassName}__link`}>
{value}
</Link>
);
} else {
component = <span className={`${myClassName}__text`}>{value ?? '--'}</span>;
}

return (
<div className={myClassName}>
<Typography.Text
ellipsis={ellipsis ? { tooltip: value } : false}
style={{ fontSize: 'inherit' }}
>
{component}
</Typography.Text>
</div>
);
}

export default BasicInfoItemValue;

+ 0
- 48
react-ui/src/components/BasicInfo/format.ts View File

@@ -1,48 +0,0 @@
/*
* @Author: 赵伟
* @Date: 2024-11-29 09:27:19
* @Description: 用于 BasicInfo 和 BasicTableInfo 组件的常用转化格式
*/

// 格式化日期
export { formatDate } from '@/utils/date';

/**
* 格式化字符串数组
* @param value - 字符串数组
* @returns 逗号分隔的字符串
*/
export const formatList = (value: string[] | null | undefined): string => {
if (
value === undefined ||
value === null ||
Array.isArray(value) === false ||
value.length === 0
) {
return '--';
}
return value.join(',');
};

/**
* 格式化布尔值
* @param value - 布尔值
* @returns "是" 或 "否"
*/
export const formatBoolean = (value: boolean): string => {
return value ? '是' : '否';
};

type FormatEnum = (value: string | number) => string;

/**
* 格式化枚举
* @param options - 枚举选项
* @returns 格式化枚举函数
*/
export const formatEnum = (options: { value: string | number; label: string }[]): FormatEnum => {
return (value: string | number) => {
const option = options.find((item) => item.value === value);
return option ? option.label : '--';
};
};

+ 1
- 2
react-ui/src/components/BasicInfo/index.tsx View File

@@ -1,9 +1,8 @@
import classNames from 'classnames';
import React from 'react';
import { BasicInfoItem } from './components';
import BasicInfoItem from './BasicInfoItem';
import './index.less';
import type { BasicInfoData, BasicInfoLink } from './types';
export * from './format';
export type { BasicInfoData, BasicInfoLink };

type BasicInfoProps = {


+ 2
- 2
react-ui/src/components/BasicInfo/types.ts View File

@@ -3,12 +3,12 @@ export type BasicInfoData = {
label: string;
value?: any;
ellipsis?: boolean;
format?: (_value?: any) => string | BasicInfoLink | BasicInfoLink[] | undefined;
format?: (_value?: any) => string | React.ReactNode | BasicInfoLink | BasicInfoLink[] | undefined;
};

// 值为链接的类型
export type BasicInfoLink = {
value: string;
value?: string;
link?: string;
url?: string;
};

+ 1
- 2
react-ui/src/components/BasicTableInfo/index.tsx View File

@@ -1,8 +1,7 @@
import classNames from 'classnames';
import { BasicInfoItem } from '../BasicInfo/components';
import BasicInfoItem from '../BasicInfo/BasicInfoItem';
import { type BasicInfoData, type BasicInfoLink } from '../BasicInfo/types';
import './index.less';
export * from '../BasicInfo/format';
export type { BasicInfoData, BasicInfoLink };

type BasicTableInfoProps = {


+ 2
- 7
react-ui/src/pages/AutoML/components/AutoMLBasic/index.tsx View File

@@ -4,16 +4,11 @@ import { experimentStatusInfo } from '@/pages/Experiment/status';
import { type NodeStatus } from '@/types';
import { parseJsonText } from '@/utils';
import { elapsedTime } from '@/utils/date';
import { formatDataset } from '@/utils/format';
import { formatBoolean, formatDataset, formatDate, formatEnum } from '@/utils/format';
import { Flex } from 'antd';
import classNames from 'classnames';
import { useMemo } from 'react';
import ConfigInfo, {
formatBoolean,
formatDate,
formatEnum,
type BasicInfoData,
} from '../ConfigInfo';
import ConfigInfo, { type BasicInfoData } from '../ConfigInfo';
import styles from './index.less';

// 格式化优化方向


+ 0
- 1
react-ui/src/pages/AutoML/components/ConfigInfo/index.tsx View File

@@ -2,7 +2,6 @@ import BasicInfo, { type BasicInfoData } from '@/components/BasicInfo';
import InfoGroup from '@/components/InfoGroup';
import classNames from 'classnames';
import styles from './index.less';
export * from '@/components/BasicInfo/format';
export type { BasicInfoData };

type ConfigInfoProps = {


+ 65
- 26
react-ui/src/pages/HyperParameter/components/CreateForm/ExecuteConfig.tsx View File

@@ -6,9 +6,10 @@ import ResourceSelect, {
} from '@/components/ResourceSelect';
import SubAreaTitle from '@/components/SubAreaTitle';
import { hyperParameterOptimizedModeOptions } from '@/enums';
import { useComputingResource } from '@/hooks/resource';
import { modalConfirm } from '@/utils/ui';
import { MinusCircleOutlined, PlusCircleOutlined } from '@ant-design/icons';
import { Button, Col, Flex, Form, Input, InputNumber, Radio, Row, Select } from 'antd';
import { MinusCircleOutlined, PlusCircleOutlined, QuestionCircleOutlined } from '@ant-design/icons';
import { Button, Col, Flex, Form, Input, InputNumber, Radio, Row, Select, Tooltip } from 'antd';
import { isEqual } from 'lodash';
import PopParameterRange from './PopParameterRange';
import styles from './index.less';
@@ -25,12 +26,48 @@ const schedulerAlgorithms = ['ASHA', 'HyperBand', 'MedianStopping', 'PopulationB
(name) => ({ label: name, value: name }),
);

const parameterTooltip = `uniform(-5, -1)
在 -5.0 和 -1.0 之间均匀采样浮点数
quniform(3.2, 5.4, 0.2)
在 3.2 和 5.4 之间均匀采样浮点数,四舍五入到 0.2 的倍数
loguniform(1e-4, 1e-2)
在 0.0001 和 0.01 之间均匀采样浮点数,对数空间采样
qloguniform(1e-4, 1e-1, 5e-5)
在 0.0001 和 0.01 之间均匀采样浮点数,对数空间采样并四舍五入到 0.00005 的倍数
randn(10, 2)
在均值为 10,方差为 2 的正态分布中进行随机浮点数抽样
qrandn(10, 2, 0.2)
在均值为 10,方差为 2 的正态分布中进行随机浮点数抽样,四舍五入到 0.2 的倍数
randint(-9, 15)
在 -9(包括)到 15(不包括)之间均匀采样整数
qrandint(-21, 12, 3)
在 -21(包括)到 12(不包括)之间均匀采样整数,四舍五入到 3 的倍数
lograndint(1, 10)
在 1(包括)到 10(不包括)之间均匀采样整数,对数空间采样
qlograndint(1, 10, 2)
在 1(包括)到 10(不包括)之间均匀采样整数,对数空间采样并四舍五入到 2 的倍数
choice(["a", "b", "c"])
从指定的选项中采样一个选项
grid([32, 64, 128])
对这些值进行网格搜索,每个值都将被采样
`;

function ExecuteConfig() {
const form = Form.useFormInstance();
const searchAlgorithm = Form.useWatch('search_alg', form);
const paramsTypeOptions = searchAlgorithm === 'Ax' ? axParameterOptions : parameterOptions;
// const parameters = Form.useWatch('parameters', form);
// console.log('parameters', parameters);
const [resourceStandardList, filterResourceStandard] = useComputingResource();

const handleSearchAlgorithmChange = (value: string) => {
if (
@@ -231,7 +268,17 @@ function ExecuteConfig() {
<div className={styles['hyper-parameter']}>
<Flex align="center" className={styles['hyper-parameter__header']}>
<div className={styles['hyper-parameter__header__name']}>参数名称</div>
<div className={styles['hyper-parameter__header__type']}>参数类型</div>
<div className={styles['hyper-parameter__header__type']}>
参数类型
<Tooltip
title={parameterTooltip}
placement="top"
arrow={{ pointAtCenter: true }}
overlayClassName={styles['hyper-parameter__header__tooltip']}
>
<QuestionCircleOutlined />
</Tooltip>
</div>
<div className={styles['hyper-parameter__header__space']}>取值范围</div>
<div className={styles['hyper-parameter__header__operation']}>操作</div>
</Flex>
@@ -465,33 +512,25 @@ function ExecuteConfig() {
<Row gutter={8}>
<Col span={10}>
<Form.Item
label="CPU 数量"
name="cpu"
label="资源规格"
name="resource"
rules={[
{
required: true,
message: '请输入 CPU 数量',
message: '请选择资源规格',
},
]}
>
<InputNumber placeholder="请输入 CPU 数量" min={0} precision={0} />
</Form.Item>
</Col>
</Row>

<Row gutter={8}>
<Col span={10}>
<Form.Item
label="GPU 数量"
name="gpu"
rules={[
{
required: true,
message: '请输入 GPU 数量',
},
]}
>
<InputNumber placeholder="请输入 GPU 数量" min={0} precision={0} />
<Select
showSearch
placeholder="请选择资源规格"
filterOption={filterResourceStandard}
options={resourceStandardList}
fieldNames={{
label: 'description',
value: 'standard',
}}
/>
</Form.Item>
</Col>
</Row>


+ 22
- 0
react-ui/src/pages/HyperParameter/components/CreateForm/index.less View File

@@ -48,6 +48,28 @@
content: '*';
margin-inline-end: 4px;
}

:global {
.anticon-question-circle {
vertical-align: middle;
cursor: help;
}
}
}

&__tooltip {
max-width: 600px;
:global {
.ant-tooltip-inner {
max-height: 400px;
overflow-y: auto;
white-space: pre-line;

&::-webkit-scrollbar-thumb {
background: rgba(255, 255, 255, 0.5);
}
}
}
}

&__operation {


+ 17
- 9
react-ui/src/pages/HyperParameter/components/HyperParameterBasic/index.tsx View File

@@ -1,10 +1,11 @@
import { hyperParameterOptimizedMode } from '@/enums';
import ConfigInfo, { formatDate, type BasicInfoData } from '@/pages/AutoML/components/ConfigInfo';
import { useComputingResource } from '@/hooks/resource';
import ConfigInfo, { type BasicInfoData } from '@/pages/AutoML/components/ConfigInfo';
import { experimentStatusInfo } from '@/pages/Experiment/status';
import { HyperparameterData } from '@/pages/HyperParameter/types';
import { type NodeStatus } from '@/types';
import { elapsedTime } from '@/utils/date';
import { formatDataset, formatSelectCodeConfig } from '@/utils/format';
import { formatDataset, formatDate, formatSelectCodeConfig } from '@/utils/format';
import { Flex } from 'antd';
import classNames from 'classnames';
import { useMemo } from 'react';
@@ -29,6 +30,17 @@ function HyperParameterBasic({
runStatus,
isInstance = false,
}: HyperParameterBasicProps) {
const getResourceDescription = useComputingResource()[2];

// 格式化资源规格
const formatResource = (resource?: string) => {
if (!resource) {
return undefined;
}

return getResourceDescription(resource);
};

const basicDatas: BasicInfoData[] = useMemo(() => {
if (!info) {
return [];
@@ -120,13 +132,9 @@ function HyperParameterBasic({
ellipsis: true,
},
{
label: 'CPU 数量',
value: info.cpu,
ellipsis: true,
},
{
label: 'GPU 数量',
value: info.gpu,
label: '资源规格',
value: info.resource,
format: formatResource,
ellipsis: true,
},
];


+ 1
- 2
react-ui/src/pages/HyperParameter/types.ts View File

@@ -23,8 +23,7 @@ export type FormData = {
num_samples: number; // 总实验次数
max_t: number; // 单次试验最大时间
min_samples_required: number; // 计算中位数的最小试验数
cpu: number; // cpu 数
gpu: number; // gpu 数
resource: string; // 资源规格
parameters: FormParameter[];
points_to_evaluate: { [key: string]: any }[];
};


+ 11
- 3
react-ui/src/pages/ModelDeployment/CreateVersion/index.tsx View File

@@ -432,7 +432,14 @@ function CreateServiceVersion() {
{(fields, { add, remove }) => (
<>
{fields.map(({ key, name, ...restField }, index) => (
<Flex key={key} align="center" gap="0 8px">
<Flex
key={key}
align="center"
gap="0 8px"
style={{
position: 'relative',
}}
>
<Form.Item
{...restField}
name={[name, 'key']}
@@ -460,9 +467,10 @@ function CreateServiceVersion() {
<Flex
style={{
width: '76px',
marginLeft: '10px',
left: 'calc(100% + 10px)',
height: '46px',
marginBottom: '24px',
position: 'absolute',
}}
align="center"
>
@@ -519,7 +527,7 @@ function CreateServiceVersion() {
</Col>
</Row>

<Form.Item wrapperCol={{ offset: 0, span: 16 }}>
<Form.Item wrapperCol={{ offset: 0, span: 16 }} style={{ marginTop: '20px' }}>
<Button type="primary" htmlType="submit">
{buttonText}
</Button>


+ 2
- 2
react-ui/src/pages/ModelDeployment/VersionInfo/index.tsx View File

@@ -11,7 +11,7 @@ import { to } from '@/utils/promise';
import { useParams } from '@umijs/max';
import { Tabs, type TabsProps } from 'antd';
import { useEffect, useState } from 'react';
import BasicInfo from '../components/BasicInfo';
import VersionBasicInfo from '../components/VersionBasicInfo';
import ServerLog from '../components/ServerLog';
import UserGuide from '../components/UserGuide';
import { ServiceVersionData } from '../types';
@@ -75,7 +75,7 @@ function ServiceVersionInfo() {
image={require('@/assets/img/mirror-basic.png')}
style={{ marginBottom: '26px' }}
></SubAreaTitle>
<BasicInfo info={versionInfo} />
<VersionBasicInfo info={versionInfo} />
<div className={styles['service-version-info__content__tabs']}>
<Tabs activeKey={activeTab} items={tabItems} onChange={hanleTabChange} />
</div>


+ 0
- 120
react-ui/src/pages/ModelDeployment/components/BasicInfo/index.tsx View File

@@ -1,120 +0,0 @@
import LabelValue from '@/components/LabelValue';
import { useComputingResource } from '@/hooks/resource';
import { ServiceVersionData } from '@/pages/ModelDeployment/types';
import { getGitUrl } from '@/utils';
import { formatDate } from '@/utils/date';
import { Link } from '@umijs/max';
import { Col, Row } from 'antd';
import ServiceRunStatusCell from '../ModelDeployStatusCell';
import styles from './index.less';

type BasicInfoProps = {
info?: ServiceVersionData;
};

function BasicInfo({ info }: BasicInfoProps) {
const getResourceDescription = useComputingResource()[2];

// 格式化环境变量
const formatEnvText = () => {
if (!info?.env_variables || Object.keys(info.env_variables).length === 0) {
return '--';
}
const env = info.env_variables;
return Object.entries(env)
.map(([key, value]) => `${key}: ${value}`)
.join('\n');
};

const formatCodeConfig = () => {
if (info && info.code_config && info.code_config.code_path) {
const { code_path, branch } = info.code_config;
const url = getGitUrl(code_path, branch);
return (
<a href={url} target="_blank" rel="noreferrer">
{info?.code_config?.show_value}
</a>
);
}
return '--';
};

const formatResource = () => {
if (info && info.resource) {
return getResourceDescription(info.resource);
}
return undefined;
};

const formatModel = () => {
if (info && info.model) {
const model = info.model;
const path = `/dataset/model/info/${model.id}?version=${model.version}&name=${model.name}&owner=${model.owner}&identifier=${model.identifier}`;
return <Link to={path}>{info?.model?.show_value}</Link>;
}
return undefined;
};

return (
<div className={styles['basic-info']}>
<Row gutter={40} style={{ marginBottom: '20px' }}>
<Col span={10}>
<LabelValue label="服务名称:" value={info?.service_name}></LabelValue>
</Col>
<Col span={10}>
<LabelValue label="版本名称:" value={info?.version}></LabelValue>
</Col>
</Row>
<Row gutter={40} style={{ marginBottom: '20px' }}>
<Col span={10}>
<LabelValue label="代码配置" value={formatCodeConfig()}></LabelValue>
</Col>
<Col span={10}>
<LabelValue label="镜  像:" value={info?.image}></LabelValue>
</Col>
</Row>
<Row gutter={40} style={{ marginBottom: '20px' }}>
<Col span={10}>
<LabelValue label="状  态:" value={ServiceRunStatusCell(info?.run_state)}></LabelValue>
</Col>
<Col span={10}>
<LabelValue label="模  型:" value={formatModel()}></LabelValue>
</Col>
</Row>
<Row gutter={40} style={{ marginBottom: '20px' }}>
<Col span={10}>
<LabelValue label="资源规格:" value={formatResource()}></LabelValue>
</Col>
<Col span={10}>
<LabelValue label="挂载路径:" value={info?.mount_path}></LabelValue>
</Col>
</Row>
<Row gutter={40} style={{ marginBottom: '20px' }}>
<Col span={10}>
<LabelValue label="API URL:" value={info?.url}></LabelValue>
</Col>
<Col span={10}>
<LabelValue label="副本数量:" value={info?.replicas}></LabelValue>
</Col>
</Row>
<Row gutter={40} style={{ marginBottom: '20px' }}>
<Col span={10}>
<LabelValue label="创建时间:" value={formatDate(info?.create_time)}></LabelValue>
</Col>
<Col span={10}>
<LabelValue label="更新时间:" value={formatDate(info?.update_time)}></LabelValue>
</Col>
</Row>
<Row gutter={40}>
<Col span={10}>
<LabelValue label="环境变量:" value={formatEnvText()}></LabelValue>
</Col>
<Col span={10}>
<LabelValue label="描  述:" value={info?.description}></LabelValue>
</Col>
</Row>
</div>
);
}

export default BasicInfo;

react-ui/src/pages/ModelDeployment/components/BasicInfo/index.less → react-ui/src/pages/ModelDeployment/components/VersionBasicInfo/index.less View File


+ 134
- 0
react-ui/src/pages/ModelDeployment/components/VersionBasicInfo/index.tsx View File

@@ -0,0 +1,134 @@
import BasicInfo, { type BasicInfoData } from '@/components/BasicInfo';
import { ServiceRunStatus } from '@/enums';
import { useComputingResource } from '@/hooks/resource';
import { ServiceVersionData } from '@/pages/ModelDeployment/types';
import { formatDate } from '@/utils/date';
import { formatModel, formatSelectCodeConfig } from '@/utils/format';
import { Flex } from 'antd';
import ModelDeployStatusCell from '../ModelDeployStatusCell';

type BasicInfoProps = {
info?: ServiceVersionData;
};

// 格式化状态
const formatStatus = (status?: ServiceRunStatus) => {
if (!status) {
return undefined;
}

return (
<Flex align="center" style={{ marginLeft: '16px', fontSize: '16px', lineHeight: 1.6 }}>
{ModelDeployStatusCell(status)}
</Flex>
);
};

// 格式化环境变量
const formatEnvText = (env?: Record<string, string>) => {
if (!env || Object.keys(env).length === 0) {
return undefined;
}

return Object.entries(env).map(([key, value]) => ({
value: `${key}: ${value}`,
}));
};

function VersionBasicInfo({ info }: BasicInfoProps) {
const getResourceDescription = useComputingResource()[2];

// 格式化资源规格
const formatResource = (resource?: string) => {
if (!resource) {
return undefined;
}

return getResourceDescription(resource);
};

const datas: BasicInfoData[] = [
{
label: '服务名称',
value: info?.service_name,
ellipsis: true,
},
{
label: '版本名称',
value: info?.version,
ellipsis: true,
},
{
label: '代码配置',
value: info?.code_config,
format: formatSelectCodeConfig,
ellipsis: true,
},
{
label: '镜像',
value: info?.image,
ellipsis: true,
},
{
label: '状态',
value: info?.run_state,
format: formatStatus,
ellipsis: true,
},
{
label: '模型',
value: info?.model,
format: formatModel,
ellipsis: true,
},
{
label: '资源规格',
value: info?.resource,
format: formatResource,
ellipsis: true,
},
{
label: '挂载路径',
value: info?.mount_path,
ellipsis: true,
},
{
label: 'API URL',
value: info?.url,
ellipsis: true,
},

{
label: '副本数量',
value: info?.replicas,
ellipsis: true,
},
{
label: '创建时间',
value: info?.create_time,
format: formatDate,
ellipsis: true,
},
{
label: '更新时间',
value: info?.update_time,
format: formatDate,
ellipsis: true,
},
{
label: '环境变量',
value: info?.env_variables,
format: formatEnvText,
ellipsis: true,
},
{
label: '描述',
value: info?.description,
ellipsis: true,
},
];

return <BasicInfo datas={datas} labelWidth={66}></BasicInfo>;
}

export default VersionBasicInfo;

+ 56
- 7
react-ui/src/utils/format.ts View File

@@ -1,6 +1,14 @@
import { ResourceInfoTabKeys } from '@/pages/Dataset/components/ResourceInfo';
import { DataSource, DatasetData, ProjectDependency, TrainTask } from '@/pages/Dataset/config';
import {
DataSource,
DatasetData,
ModelData,
ProjectDependency,
TrainTask,
} from '@/pages/Dataset/config';
import { getGitUrl } from '@/utils';
// 格式化日期
export { formatDate } from '@/utils/date';

// 格式化数据集数组
export const formatDatasets = (datasets?: DatasetData[]) => {
@@ -9,7 +17,7 @@ export const formatDatasets = (datasets?: DatasetData[]) => {
}
return datasets.map((item) => ({
value: item.name,
url: `${origin}/dataset/dataset/info/${item.id}?tab=${ResourceInfoTabKeys.Introduction}&version=${item.version}&name=${item.name}&owner=${item.owner}&identifier=${item.identifier}`,
link: `/dataset/dataset/info/${item.id}?tab=${ResourceInfoTabKeys.Introduction}&version=${item.version}&name=${item.name}&owner=${item.owner}&identifier=${item.identifier}`,
}));
};

@@ -20,7 +28,19 @@ export const formatDataset = (dataset?: DatasetData) => {
}
return {
value: dataset.name,
url: `${origin}/dataset/dataset/info/${dataset.id}?tab=${ResourceInfoTabKeys.Introduction}&version=${dataset.version}&name=${dataset.name}&owner=${dataset.owner}&identifier=${dataset.identifier}`,
link: `/dataset/dataset/info/${dataset.id}?tab=${ResourceInfoTabKeys.Introduction}&version=${dataset.version}&name=${dataset.name}&owner=${dataset.owner}&identifier=${dataset.identifier}`,
};
};

// 格式化模型
export const formatModel = (model: ModelData) => {
if (!model) {
return undefined;
}

return {
value: model.name,
link: `/dataset/model/info/${model.id}?tab=${ResourceInfoTabKeys.Introduction}&version=${model.version}&name=${model.name}&owner=${model.owner}&identifier=${model.identifier}`,
};
};

@@ -48,14 +68,15 @@ export const formatCodeConfig = (project?: ProjectDependency) => {
export const formatSelectCodeConfig = (value?: {
code_path: string;
branch: string;
showValue: string;
showValue?: string;
show_value?: string;
}) => {
if (!value) {
return undefined;
}
const { showValue, code_path, branch } = value;
const { showValue, show_value, code_path, branch } = value;
return {
value: showValue,
value: showValue || show_value,
url: getRepoUrl({
url: code_path,
branch,
@@ -70,7 +91,7 @@ export const formatTrainTask = (task?: TrainTask) => {
}
return {
value: task.name,
url: `${origin}/pipeline/experiment/instance/${task.workflow_id}/${task.ins_id}`,
url: `/pipeline/experiment/instance/${task.workflow_id}/${task.ins_id}`,
};
};

@@ -85,3 +106,31 @@ export const formatSource = (source?: string) => {
}
return source;
};

// 格式化字符串数组
export const formatList = (value: string[] | null | undefined): string => {
if (
value === undefined ||
value === null ||
Array.isArray(value) === false ||
value.length === 0
) {
return '--';
}
return value.join(',');
};

// 格式化布尔值
export const formatBoolean = (value: boolean): string => {
return value ? '是' : '否';
};

type FormatEnum = (value: string | number) => string;

// 格式化枚举
export const formatEnum = (options: { value: string | number; label: string }[]): FormatEnum => {
return (value: string | number) => {
const option = options.find((item) => item.value === value);
return option ? option.label : '--';
};
};

Loading…
Cancel
Save