Browse Source

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

dev-complex-computation
cp3hnu 1 year ago
parent
commit
518b1e82cb
14 changed files with 82 additions and 224 deletions
  1. +1
    -0
      react-ui/config/config.ts
  2. +0
    -176
      react-ui/mock/listTableList.ts
  3. +0
    -1
      react-ui/package.json
  4. +1
    -4
      react-ui/src/components/InfoGroup/index.less
  5. +13
    -7
      react-ui/src/components/InfoGroup/index.tsx
  6. +15
    -1
      react-ui/src/hooks/resource.ts
  7. +7
    -9
      react-ui/src/pages/AutoML/components/ExperimentResult/index.less
  8. +17
    -21
      react-ui/src/pages/AutoML/components/ExperimentResult/index.tsx
  9. +6
    -0
      react-ui/src/pages/Experiment/components/ExperimentDrawer/index.less
  10. +3
    -2
      react-ui/src/pages/Experiment/components/ExperimentDrawer/index.tsx
  11. +1
    -1
      react-ui/src/pages/Pipeline/components/GlobalParamsDrawer/index.tsx
  12. +1
    -1
      react-ui/src/pages/Pipeline/components/PipelineNodeDrawer/index.tsx
  13. +1
    -1
      react-ui/src/pages/System/User/index.tsx
  14. +16
    -0
      react-ui/src/state/computingResourceStore.ts

+ 1
- 0
react-ui/config/config.ts View File

@@ -156,4 +156,5 @@ export default defineConfig({
},
javascriptEnabled: true,
},
valtio: {},
});

+ 0
- 176
react-ui/mock/listTableList.ts View File

@@ -1,176 +0,0 @@
import { Request, Response } from 'express';
import moment from 'moment';
import { parse } from 'url';

// mock tableListDataSource
const genList = (current: number, pageSize: number) => {
const tableListDataSource: API.RuleListItem[] = [];

for (let i = 0; i < pageSize; i += 1) {
const index = (current - 1) * 10 + i;
tableListDataSource.push({
key: index,
disabled: i % 6 === 0,
href: 'https://ant.design',
avatar: [
'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png',
'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png',
][i % 2],
name: `TradeCode ${index}`,
owner: '曲丽丽',
desc: '这是一段描述',
callNo: Math.floor(Math.random() * 1000),
status: Math.floor(Math.random() * 10) % 4,
updatedAt: moment().format('YYYY-MM-DD'),
createdAt: moment().format('YYYY-MM-DD'),
progress: Math.ceil(Math.random() * 100),
});
}
tableListDataSource.reverse();
return tableListDataSource;
};

let tableListDataSource = genList(1, 100);

function getRule(req: Request, res: Response, u: string) {
let realUrl = u;
if (!realUrl || Object.prototype.toString.call(realUrl) !== '[object String]') {
realUrl = req.url;
}
const { current = 1, pageSize = 10 } = req.query;
const params = parse(realUrl, true).query as unknown as API.PageParams &
API.RuleListItem & {
sorter: any;
filter: any;
};

let dataSource = [...tableListDataSource].slice(
((current as number) - 1) * (pageSize as number),
(current as number) * (pageSize as number),
);
if (params.sorter) {
const sorter = JSON.parse(params.sorter);
dataSource = dataSource.sort((prev, next) => {
let sortNumber = 0;
(Object.keys(sorter) as Array<keyof API.RuleListItem>).forEach((key) => {
let nextSort = next?.[key] as number;
let preSort = prev?.[key] as number;
if (sorter[key] === 'descend') {
if (preSort - nextSort > 0) {
sortNumber += -1;
} else {
sortNumber += 1;
}
return;
}
if (preSort - nextSort > 0) {
sortNumber += 1;
} else {
sortNumber += -1;
}
});
return sortNumber;
});
}
if (params.filter) {
const filter = JSON.parse(params.filter as any) as {
[key: string]: string[];
};
if (Object.keys(filter).length > 0) {
dataSource = dataSource.filter((item) => {
return (Object.keys(filter) as Array<keyof API.RuleListItem>).some((key) => {
if (!filter[key]) {
return true;
}
if (filter[key].includes(`${item[key]}`)) {
return true;
}
return false;
});
});
}
}

if (params.name) {
dataSource = dataSource.filter((data) => data?.name?.includes(params.name || ''));
}
const result = {
data: dataSource,
total: tableListDataSource.length,
success: true,
pageSize,
current: parseInt(`${params.current}`, 10) || 1,
};

return res.json(result);
}

function postRule(req: Request, res: Response, u: string, b: Request) {
let realUrl = u;
if (!realUrl || Object.prototype.toString.call(realUrl) !== '[object String]') {
realUrl = req.url;
}

const body = (b && b.body) || req.body;
const { method, name, desc, key } = body;

switch (method) {
/* eslint no-case-declarations:0 */
case 'delete':
tableListDataSource = tableListDataSource.filter((item) => key.indexOf(item.key) === -1);
break;
case 'post':
(() => {
const i = Math.ceil(Math.random() * 10000);
const newRule: API.RuleListItem = {
key: tableListDataSource.length,
href: 'https://ant.design',
avatar: [
'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png',
'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png',
][i % 2],
name,
owner: '曲丽丽',
desc,
callNo: Math.floor(Math.random() * 1000),
status: Math.floor(Math.random() * 10) % 2,
updatedAt: moment().format('YYYY-MM-DD'),
createdAt: moment().format('YYYY-MM-DD'),
progress: Math.ceil(Math.random() * 100),
};
tableListDataSource.unshift(newRule);
return res.json(newRule);
})();
return;

case 'update':
(() => {
let newRule = {};
tableListDataSource = tableListDataSource.map((item) => {
if (item.key === key) {
newRule = { ...item, desc, name };
return { ...item, desc, name };
}
return item;
});
return res.json(newRule);
})();
return;
default:
break;
}

const result = {
list: tableListDataSource,
pagination: {
total: tableListDataSource.length,
},
};

res.json(result);
}

export default {
'GET /api/rule': getRule,
'POST /api/rule': postRule,
};

+ 0
- 1
react-ui/package.json View File

@@ -67,7 +67,6 @@
"fabric": "^5.3.0",
"highlight.js": "^11.7.0",
"lodash": "^4.17.21",
"moment": "^2.30.1",
"omit.js": "^2.0.2",
"pnpm": "^8.9.0",
"query-string": "^8.1.0",


+ 1
- 4
react-ui/src/components/InfoGroup/index.less View File

@@ -5,10 +5,7 @@
padding: 20px @content-padding;
background-color: white;
border: 1px solid @border-color-base;
border-top: none;
border-radius: 0 0 4px 4px;

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

+ 13
- 7
react-ui/src/components/InfoGroup/index.tsx View File

@@ -4,21 +4,27 @@ import './index.less';

type InfoGroupProps = {
title: string;
contentScroll?: boolean; // 内容是否需要滚动,如果可以滚动,则取消 padding
height?: string | number; // 如果要纵向滚动,需要设置高度
width?: string | number; // 如果要横向滚动,需要设置宽度
className?: string;
style?: React.CSSProperties;
children?: React.ReactNode;
};

function InfoGroup({ title, contentScroll = false, className, style, children }: InfoGroupProps) {
function InfoGroup({ title, height, width, className, style, children }: InfoGroupProps) {
const contentStyle: React.CSSProperties = {};
if (height) {
contentStyle.height = height;
contentStyle.overflowY = 'auto';
}
if (width) {
contentStyle.width = width;
contentStyle.overflowX = 'auto';
}
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,
})}
>
<div style={contentStyle} className={'kf-info-group__content'}>
{children}
</div>
</div>


+ 15
- 1
react-ui/src/hooks/resource.ts View File

@@ -1,15 +1,28 @@
/*
* @Author: 赵伟
* @Date: 2024-10-10 08:51:41
* @Description: 资源规格 hook
*/

import { getComputingResourceReq } from '@/services/pipeline';
import computingResourceState, { setComputingResource } from '@/state/computingResourceStore';
import { ComputingResource } from '@/types';
import { to } from '@/utils/promise';
import { type SelectProps } from 'antd';
import { useCallback, useEffect, useState } from 'react';
import { useSnapshot } from 'umi';

// 获取资源规格
export function useComputingResource() {
const [resourceStandardList, setResourceStandardList] = useState<ComputingResource[]>([]);
const computingResourceSnap = useSnapshot(computingResourceState);

useEffect(() => {
getComputingResource();
if (computingResourceSnap.computingResource.length > 0) {
setResourceStandardList(computingResourceSnap.computingResource as ComputingResource[]);
} else {
getComputingResource();
}
}, []);

// 获取资源规格列表数据
@@ -22,6 +35,7 @@ export function useComputingResource() {
const [res] = await to(getComputingResourceReq(params));
if (res && res.data && res.data.content) {
setResourceStandardList(res.data.content);
setComputingResource(res.data.content);
}
}, []);



+ 7
- 9
react-ui/src/pages/AutoML/components/ExperimentResult/index.less View File

@@ -7,10 +7,9 @@
border-radius: 10px;

&__download {
display: flex;
align-items: center;
height: 34px;
margin-bottom: 16px;
padding-top: 16px;
padding-bottom: 16px;

padding-left: @content-padding;
color: @text-color;
font-size: 13px;
@@ -18,15 +17,14 @@
border-radius: 4px;

&__btn {
margin-left: 22px;
display: block;
height: 36px;
margin-top: 15px;
font-size: 14px;
}
}

&__text {
width: 100%;
height: 420px;
padding: 20px @content-padding;
overflow: auto;
white-space: pre-wrap;
}



+ 17
- 21
react-ui/src/pages/AutoML/components/ExperimentResult/index.tsx View File

@@ -1,5 +1,4 @@
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';
@@ -38,28 +37,10 @@ function ExperimentResult({ fileUrl, imageUrl, modelPath }: ExperimentResultProp

return (
<div className={styles['experiment-result']}>
{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>
<InfoGroup title="实验结果" height={420} width="100%">
<div className={styles['experiment-result__text']}>{result}</div>
</InfoGroup>
<InfoGroup title="可视化结果" style={{ marginTop: '16px' }}>
<InfoGroup title="可视化结果" style={{ margin: '16px 0' }}>
<div className={styles['experiment-result__images']}>
<Image.PreviewGroup
preview={{
@@ -80,6 +61,21 @@ function ExperimentResult({ fileUrl, imageUrl, modelPath }: ExperimentResultProp
</Image.PreviewGroup>
</div>
</InfoGroup>
{modelPath && (
<div className={styles['experiment-result__download']}>
<span style={{ marginRight: '12px', color: '#606b7a' }}>文件名</span>
<span>save_model.joblib</span>
<Button
type="primary"
className={styles['experiment-result__download__btn']}
onClick={() => {
window.location.href = modelPath;
}}
>
模型下载
</Button>
</div>
)}
</div>
);
}


+ 6
- 0
react-ui/src/pages/Experiment/components/ExperimentDrawer/index.less View File

@@ -3,6 +3,12 @@
.ant-drawer-body {
overflow-y: hidden;
}

.ant-drawer-close {
position: absolute;
top: 16px;
right: 16px;
}
}

&__tabs {


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

@@ -2,7 +2,7 @@ import { ExperimentStatus } from '@/enums';
import { experimentStatusInfo } from '@/pages/Experiment/status';
import { PipelineNodeModelSerialize } from '@/types';
import { elapsedTime, formatDate } from '@/utils/date';
import { DatabaseOutlined, ProfileOutlined } from '@ant-design/icons';
import { CloseOutlined, DatabaseOutlined, ProfileOutlined } from '@ant-design/icons';
import { Drawer, Tabs } from 'antd';
import { useMemo } from 'react';
import ExperimentParameter from '../ExperimentParameter';
@@ -95,10 +95,11 @@ const ExperimentDrawer = ({

return (
<Drawer
rootStyle={{ marginTop: '55px' }}
title="任务执行详情"
placement="right"
getContainer={false}
closeIcon={false}
closeIcon={<CloseOutlined className={styles['experiment-drawer__close']} />}
onClose={onClose}
open={open}
width={520}


+ 1
- 1
react-ui/src/pages/Pipeline/components/GlobalParamsDrawer/index.tsx View File

@@ -49,7 +49,7 @@ const GlobalParamsDrawer = forwardRef(

return (
<Drawer
rootStyle={{ marginTop: '45px' }}
rootStyle={{ marginTop: '55px' }}
title="全局参数"
placement="right"
closeIcon={false}


+ 1
- 1
react-ui/src/pages/Pipeline/components/PipelineNodeDrawer/index.tsx View File

@@ -335,7 +335,7 @@ const PipelineNodeParameter = forwardRef(({ onFormChange }: PipelineNodeParamete
<Drawer
title="编辑任务"
placement="right"
rootStyle={{ marginTop: '52px' }}
rootStyle={{ marginTop: '55px' }}
getContainer={false}
closeIcon={false}
onClose={onClose}


+ 1
- 1
react-ui/src/pages/System/User/index.tsx View File

@@ -235,7 +235,7 @@ const UserTableList: React.FC = () => {
const columns: ProColumns<API.System.User>[] = [
{
title: <FormattedMessage id="system.user.user_id" defaultMessage="用户编号" />,
dataIndex: 'deptId',
dataIndex: 'userId',
valueType: 'text',
},
{


+ 16
- 0
react-ui/src/state/computingResourceStore.ts View File

@@ -0,0 +1,16 @@
import { ComputingResource } from '@/types';
import { proxy } from 'umi';

type ComputingResourceStore = {
computingResource: ComputingResource[];
};

const state = proxy<ComputingResourceStore>({
computingResource: [],
});

export const setComputingResource = (computingResource: ComputingResource[]) => {
state.computingResource = computingResource;
};

export default state;

Loading…
Cancel
Save