Browse Source

Merge pull request '合并dev-zw' (#149) from dev-zw into dev

dev-complex-computation
cp3hnu 1 year ago
parent
commit
98c1b0cb1f
13 changed files with 178 additions and 116 deletions
  1. +14
    -0
      react-ui/src/components/InfoGroup/index.less
  2. +28
    -0
      react-ui/src/components/InfoGroup/index.tsx
  3. +2
    -2
      react-ui/src/components/InfoGroupTitle/index.less
  4. +25
    -0
      react-ui/src/components/InfoGroupTitle/index.tsx
  5. +1
    -1
      react-ui/src/iconfont/iconfont.js
  6. +20
    -5
      react-ui/src/pages/AutoML/Instance/index.tsx
  7. +4
    -6
      react-ui/src/pages/AutoML/components/AutoMLBasic/index.tsx
  8. +1
    -21
      react-ui/src/pages/AutoML/components/ConfigInfo/index.less
  9. +5
    -27
      react-ui/src/pages/AutoML/components/ConfigInfo/index.tsx
  10. +0
    -22
      react-ui/src/pages/AutoML/components/ConfigTitle/index.tsx
  11. +29
    -14
      react-ui/src/pages/AutoML/components/ExperimentResult/index.less
  12. +47
    -16
      react-ui/src/pages/AutoML/components/ExperimentResult/index.tsx
  13. +2
    -2
      react-ui/src/pages/Experiment/components/LogGroup/index.tsx

+ 14
- 0
react-ui/src/components/InfoGroup/index.less View File

@@ -0,0 +1,14 @@
.kf-info-group {
width: 100%;

&__content {
padding: 20px @content-padding;
background-color: white;
border: 1px solid @border-color-base;
border-radius: 0 0 4px 4px;

&&--scroll {
padding: 0;
}
}
}

+ 28
- 0
react-ui/src/components/InfoGroup/index.tsx View File

@@ -0,0 +1,28 @@
import classNames from 'classnames';
import InfoGroupTitle from '../InfoGroupTitle';
import './index.less';

type InfoGroupProps = {
title: string;
contentScroll?: boolean; // 内容是否需要滚动,如果可以滚动,则取消 padding
className?: string;
style?: React.CSSProperties;
children?: React.ReactNode;
};

function InfoGroup({ title, contentScroll = false, className, style, children }: InfoGroupProps) {
return (
<div className={classNames('kf-info-group', className)} style={style}>
<InfoGroupTitle title={title} />
<div
className={classNames('kf-info-group__content', {
'kf-info-group__content--scroll': contentScroll,
})}
>
{children}
</div>
</div>
);
}

export default InfoGroup;

react-ui/src/pages/AutoML/components/ConfigTitle/index.less → react-ui/src/components/InfoGroupTitle/index.less View File

@@ -1,4 +1,4 @@
.config-title {
.kf-info-group-title {
width: 100%;
height: 56px;
padding-left: @content-padding;
@@ -10,7 +10,7 @@
border: 1px solid #e8effb;
border-radius: 4px 4px 0 0;

&__img {
&__image {
width: 16px;
height: 16px;
margin-right: 10px;

+ 25
- 0
react-ui/src/components/InfoGroupTitle/index.tsx View File

@@ -0,0 +1,25 @@
import { Flex } from 'antd';
import classNames from 'classnames';
import './index.less';

type InfoGroupTitleProps = {
title: string;
className?: string;
style?: React.CSSProperties;
};

function InfoGroupTitle({ title, style, className }: InfoGroupTitleProps) {
return (
<Flex align="center" className={classNames('kf-info-group-title', className)} style={style}>
<img
src={require('@/assets/img/code-name-icon.png')}
className="kf-info-group-title__image"
alt=""
draggable={false}
/>
<span className="kf-info-group-title__text">{title}</span>
</Flex>
);
}

export default InfoGroupTitle;

+ 1
- 1
react-ui/src/iconfont/iconfont.js
File diff suppressed because it is too large
View File


+ 20
- 5
react-ui/src/pages/AutoML/Instance/index.tsx View File

@@ -33,7 +33,7 @@ function AutoMLInstance() {

useEffect(() => {
if (instanceId) {
getExperimentInsInfo();
getExperimentInsInfo(false);
}
return () => {
closeSSE();
@@ -41,7 +41,7 @@ function AutoMLInstance() {
}, []);

// 获取实验实例详情
const getExperimentInsInfo = async () => {
const getExperimentInsInfo = async (isStatusDetermined: boolean) => {
const [res] = await to(getExperimentInsReq(instanceId));
if (res && res.data) {
const info = res.data as AutoMLInstanceData;
@@ -51,6 +51,17 @@ function AutoMLInstance() {
if (paramJson) {
setAutoMLInfo(paramJson);
}

// 这个接口返回的状态有延时,SSE 返回的状态是最新的
// SSE 调用时,不需要解析 node_status, 也不要重新建立 SSE
if (isStatusDetermined) {
setInstanceInfo((prev) => ({
...info,
nodeStatus: prev!.nodeStatus,
}));
return;
}

// 进行节点状态
const nodeStatusJson = parseJsonText(node_status);
if (nodeStatusJson) {
@@ -93,7 +104,7 @@ function AutoMLInstance() {
) as NodeStatus;
if (statusData) {
setInstanceInfo((prev) => ({
...(prev as AutoMLInstanceData),
...prev!,
nodeStatus: statusData,
}));

@@ -103,7 +114,7 @@ function AutoMLInstance() {
statusData.phase !== ExperimentStatus.Running
) {
closeSSE();
getExperimentInsInfo();
getExperimentInsInfo(true);
}
}
}
@@ -164,7 +175,11 @@ function AutoMLInstance() {
label: '实验结果',
icon: <KFIcon type="icon-shiyanjieguo1" />,
children: (
<ExperimentResult fileUrl={instanceInfo?.result_path} imageUrl={instanceInfo?.img_path} />
<ExperimentResult
fileUrl={instanceInfo?.result_path}
imageUrl={instanceInfo?.img_path}
modelPath={instanceInfo?.model_path}
/>
),
},
{


+ 4
- 6
react-ui/src/pages/AutoML/components/AutoMLBasic/index.tsx View File

@@ -278,20 +278,19 @@ function AutoMLBasic({ info, className, runStatus, isInstance = false }: AutoMLB

return (
<div className={classNames(styles['auto-ml-basic'], className)}>
{isInstance && runStatus ? (
{isInstance && runStatus && (
<ConfigInfo
title="运行信息"
data={instanceDatas}
labelWidth={70}
threeColumn
style={{ marginBottom: '20px' }}
/>
) : (
)}
{!isInstance && (
<ConfigInfo
title="基本信息"
data={basicDatas}
labelWidth={70}
threeColumn
style={{ marginBottom: '20px' }}
/>
)}
@@ -299,10 +298,9 @@ function AutoMLBasic({ info, className, runStatus, isInstance = false }: AutoMLB
title="配置信息"
data={configDatas}
labelWidth={150}
threeColumn
style={{ marginBottom: '20px' }}
/>
<ConfigInfo title="优化指标" data={metricsData} labelWidth={70} threeColumn />
<ConfigInfo title="优化指标" data={metricsData} labelWidth={70} />
</div>
);
}


+ 1
- 21
react-ui/src/pages/AutoML/components/ConfigInfo/index.less View File

@@ -1,20 +1,10 @@
.config-info {
flex: 1;
min-width: 0;

&__content {
padding: 20px;
padding: 20px @content-padding;
background-color: white;
border: 1px solid @border-color-base;
border-radius: 0 0 4px 4px;
}

:global {
.kf-basic-info {
width: 100%;

&__item {
width: calc((100% - 80px) / 3);
&__label {
font-size: @font-size;
text-align: left;
@@ -27,14 +17,4 @@
}
}
}

&--three-column {
:global {
.kf-basic-info {
&__item {
width: calc((100% - 80px) / 3);
}
}
}
}
}

+ 5
- 27
react-ui/src/pages/AutoML/components/ConfigInfo/index.tsx View File

@@ -1,7 +1,6 @@
import BasicInfo, { type BasicInfoData } from '@/components/BasicInfo';
import InfoGroup from '@/components/InfoGroup';
import classNames from 'classnames';
import { useEffect } from 'react';
import ConfigTitle from '../ConfigTitle';
import styles from './index.less';
export * from '@/components/BasicInfo/format';
export type { BasicInfoData };
@@ -9,39 +8,18 @@ export type { BasicInfoData };
type ConfigInfoProps = {
title: string;
data: BasicInfoData[];
labelWidth: number;
className?: string;
style?: React.CSSProperties;
children?: React.ReactNode;
labelWidth: number;
threeColumn?: boolean;
};

function ConfigInfo({
title,
data,
className,
style,
children,
labelWidth,
threeColumn = false,
}: ConfigInfoProps) {
useEffect(() => {}, []);

function ConfigInfo({ title, data, labelWidth, className, style }: ConfigInfoProps) {
return (
<div
className={classNames(
styles['config-info'],
{ [styles['config-info--three-column']]: threeColumn },
className,
)}
style={style}
>
<ConfigTitle title={title} />
<InfoGroup title={title} className={classNames(styles['config-info'], className)} style={style}>
<div className={styles['config-info__content']}>
<BasicInfo datas={data} labelWidth={labelWidth} />
{children}
</div>
</div>
</InfoGroup>
);
}



+ 0
- 22
react-ui/src/pages/AutoML/components/ConfigTitle/index.tsx View File

@@ -1,22 +0,0 @@
import { Flex } from 'antd';
import styles from './index.less';

type ConfigTitleProps = {
title: string;
};

function ConfigTitle({ title }: ConfigTitleProps) {
return (
<Flex align="center" className={styles['config-title']}>
<img
src={require('@/assets/img/code-name-icon.png')}
className={styles['config-title__img']}
alt=""
draggable={false}
/>
<span className={styles['config-title__text']}>{title}</span>
</Flex>
);
}

export default ConfigTitle;

+ 29
- 14
react-ui/src/pages/AutoML/components/ExperimentResult/index.less View File

@@ -6,34 +6,49 @@
background-color: white;
border-radius: 10px;

&__download {
display: flex;
align-items: center;
height: 34px;
margin-bottom: 16px;
padding-left: @content-padding;
color: @text-color;
font-size: 13px;
background-color: #f8f8f9;
border-radius: 4px;

&__btn {
margin-left: 22px;
}
}

&__text {
width: 100%;
height: 460px;
margin-bottom: 16px;
height: 420px;
padding: 20px @content-padding;
overflow: auto;
white-space: pre-wrap;
border: 1px solid @border-color-base;
border-radius: 0 0 4px 4px;
}

&__image-container {
&__images {
display: flex;
align-items: flex-start;
width: 100%;
padding: 20px @content-padding;
overflow-x: auto;
border: 1px solid @border-color-base;
border-radius: 0 0 4px 4px;

&__image {
height: 248px;
margin-right: 20px;
border: 1px solid rgba(96, 107, 122, 0.3);
:global {
.ant-image {
margin-right: 20px;

&:last-child {
margin-right: 0;
&:last-child {
margin-right: 0;
}
}
}

&__item {
height: 248px;
border: 1px solid rgba(96, 107, 122, 0.3);
}
}
}

+ 47
- 16
react-ui/src/pages/AutoML/components/ExperimentResult/index.tsx View File

@@ -1,15 +1,18 @@
import InfoGroup from '@/components/InfoGroup';
import KFIcon from '@/components/KFIcon';
import { getFileReq } from '@/services/file';
import { to } from '@/utils/promise';
import { Button, Image } from 'antd';
import { useEffect, useMemo, useState } from 'react';
import ConfigTitle from '../ConfigTitle';
import styles from './index.less';

type ExperimentResultProps = {
fileUrl?: string;
imageUrl?: string;
modelPath?: string;
};

function ExperimentResult({ fileUrl, imageUrl }: ExperimentResultProps) {
function ExperimentResult({ fileUrl, imageUrl, modelPath }: ExperimentResultProps) {
const [result, setResult] = useState<string | undefined>('');

const images = useMemo(() => {
@@ -35,20 +38,48 @@ function ExperimentResult({ fileUrl, imageUrl }: ExperimentResultProps) {

return (
<div className={styles['experiment-result']}>
<ConfigTitle title="实验结果"></ConfigTitle>
<div className={styles['experiment-result__text']}>{result}</div>
<ConfigTitle title="可视化结果"></ConfigTitle>
<div className={styles['experiment-result__image-container']}>
{images.map((item, index) => (
<img
key={index}
className={styles['experiment-result__image-container__image']}
src={item}
draggable={false}
alt=""
/>
))}
</div>
{modelPath && (
<div className={styles['experiment-result__download']}>
<span style={{ marginRight: '12px', color: '#606b7a' }}>文件名</span>
<span>save_model.joblib</span>
<Button
type="link"
className={styles['experiment-result__download__btn']}
icon={<KFIcon type="icon-a-xiazai1" />}
size="small"
iconPosition="end"
onClick={() => {
window.location.href = modelPath;
}}
>
模型下载
</Button>
</div>
)}
<InfoGroup title="实验结果" contentScroll>
<div className={styles['experiment-result__text']}>{result}</div>
</InfoGroup>
<InfoGroup title="可视化结果" style={{ marginTop: '16px' }}>
<div className={styles['experiment-result__images']}>
<Image.PreviewGroup
preview={{
onChange: (current, prev) =>
console.log(`current index: ${current}, prev index: ${prev}`),
}}
>
{images.map((item) => (
<Image
key={item}
className={styles['experiment-result__images__item']}
src={item}
height={248}
draggable={false}
alt=""
/>
))}
</Image.PreviewGroup>
</div>
</InfoGroup>
</div>
);
}


+ 2
- 2
react-ui/src/pages/Experiment/components/LogGroup/index.tsx View File

@@ -52,7 +52,7 @@ function LogGroup({
const [_isMouseDown, setIsMouseDown, isMouseDownRef] = useStateRef(false);
const preStatusRef = useRef<ExperimentStatus | undefined>(undefined);
const socketRef = useRef<WebSocket | undefined>(undefined);
const retryRef = useRef(2); // 等待 2 秒,重试 2
const retryRef = useRef(2); // 等待 2 秒,重试 3

useEffect(() => {
scrollToBottom(false);
@@ -147,7 +147,7 @@ function LogGroup({

socket.addEventListener('close', (event) => {
console.log('WebSocket is closed:', event);
// 有时候会出现连接失败,重试 2
// 有时候会出现连接失败,重试 3
if (event.code !== 1000 && retryRef.current > 0) {
retryRef.current -= 1;
setTimeout(() => {


Loading…
Cancel
Save