Browse Source

feat: 模型部署UI修改

pull/134/head
cp3hnu 1 year ago
parent
commit
857d56a451
6 changed files with 358 additions and 3 deletions
  1. +3
    -3
      react-ui/config/config.ts
  2. +10
    -0
      react-ui/config/routes.ts
  3. +19
    -0
      react-ui/src/pages/ModelDeployment/CreateServer/index.less
  4. +212
    -0
      react-ui/src/pages/ModelDeployment/CreateServer/index.tsx
  5. +38
    -0
      react-ui/src/pages/ModelDeployment/ServerInfo/index.less
  6. +76
    -0
      react-ui/src/pages/ModelDeployment/ServerInfo/index.tsx

+ 3
- 3
react-ui/config/config.ts View File

@@ -150,9 +150,9 @@ export default defineConfig({
projectName: 'swagger',
},
],
mfsu: {
strategy: 'normal',
},
// mfsu: {
// strategy: 'normal',
// },
requestRecord: {},
icons: {},
lessLoader: {


+ 10
- 0
react-ui/config/routes.ts View File

@@ -220,6 +220,11 @@ export default [
path: '',
component: './ModelDeployment/List',
},
{
name: '服务详情',
path: 'serverInfo/:id',
component: './ModelDeployment/Info',
},
{
name: '模型部署详情',
path: 'info/:id',
@@ -228,6 +233,11 @@ export default [
{
name: '创建推理服务',
path: 'create',
component: './ModelDeployment/CreateServer',
},
{
name: '新增服务版本',
path: 'addVersion/:id',
component: './ModelDeployment/Create',
},
],


+ 19
- 0
react-ui/src/pages/ModelDeployment/CreateServer/index.less View File

@@ -0,0 +1,19 @@
.model-deployment-create {
height: 100%;

&__content {
height: calc(100% - 60px);
margin-top: 10px;
padding: 30px 30px 10px;
overflow: auto;
color: @text-color;
font-size: @font-size-content;
background-color: white;
border-radius: 10px;

&__type {
color: @text-color;
font-size: @font-size-input-lg;
}
}
}

+ 212
- 0
react-ui/src/pages/ModelDeployment/CreateServer/index.tsx View File

@@ -0,0 +1,212 @@
/*
* @Author: 赵伟
* @Date: 2024-04-16 13:58:08
* @Description: 创建模型部署
*/
import PageTitle from '@/components/PageTitle';
import SubAreaTitle from '@/components/SubAreaTitle';
import { CommonTabKeys } from '@/enums';
import {
createModelDeploymentReq,
restartModelDeploymentReq,
updateModelDeploymentReq,
} from '@/services/modelDeployment';
import { camelCaseToUnderscore, underscoreToCamelCase } from '@/utils';
import { to } from '@/utils/promise';
import {
getSessionStorageItem,
modelDeploymentInfoKey,
removeSessionStorageItem,
} from '@/utils/sessionStorage';
import { useNavigate } from '@umijs/max';
import { App, Button, Col, Form, Input, Row } from 'antd';
import { pick } from 'lodash';
import { useEffect, useState } from 'react';
import { ModelDeploymentData, ModelDeploymentOperationType } from '../types';
import styles from './index.less';

// 表单数据
export type FormData = {
serviceName: string; // 服务名称
serviceVersion: string; // 服务版本
description: string; // 描述
};

function ModelDeploymentCreate() {
const navigate = useNavigate();
const [form] = Form.useForm();
const [operationType, setOperationType] = useState(ModelDeploymentOperationType.Create);
const [modelDeploymentInfo, setModelDeploymentInfo] = useState<ModelDeploymentData | undefined>(
undefined,
);
const { message } = App.useApp();

useEffect(() => {
const res = getSessionStorageItem(modelDeploymentInfoKey, true);
if (res) {
setOperationType(res.operationType);
setModelDeploymentInfo(res);
const formData = underscoreToCamelCase(res) as FormData;
form.setFieldsValue(formData);
}
return () => {
removeSessionStorageItem(modelDeploymentInfoKey);
};
}, []);

// 创建
const createModelDeployment = async (formData: FormData) => {
// 根据后台要求,修改表单数据
const object = camelCaseToUnderscore({
...formData,
});

const params =
operationType === ModelDeploymentOperationType.Create
? object
: {
...pick(modelDeploymentInfo, ['service_id', 'service_ins_id']),
update_model: {
...pick(object, ['description', 'env', 'replicas', 'resource', 'image']),
},
};

let request = createModelDeploymentReq;
if (operationType === ModelDeploymentOperationType.Restart) {
request = restartModelDeploymentReq;
} else if (operationType === ModelDeploymentOperationType.Update) {
request = updateModelDeploymentReq;
}
const [res] = await to(request(params));
if (res) {
message.success('操作成功');
navigate(-1);
}
};

// 提交
const handleSubmit = (values: FormData) => {
createModelDeployment(values);
};

// 取消
const cancel = () => {
navigate(-1);
};

const disabled = operationType !== ModelDeploymentOperationType.Create;
let buttonText = '新建';
if (operationType === ModelDeploymentOperationType.Update) {
buttonText = '更新';
} else if (operationType === ModelDeploymentOperationType.Restart) {
buttonText = '重启';
}

return (
<div className={styles['model-deployment-create']}>
<PageTitle title="创建推理服务"></PageTitle>
<div className={styles['model-deployment-create__content']}>
<div>
<Form
name="model-deployment-create"
labelCol={{ flex: '100px' }}
labelAlign="left"
form={form}
initialValues={{ upload_type: CommonTabKeys.Public }}
onFinish={handleSubmit}
size="large"
autoComplete="off"
>
<SubAreaTitle
title="基本信息"
image={require('@/assets/img/mirror-basic.png')}
style={{ marginBottom: '26px' }}
></SubAreaTitle>
<Row gutter={8}>
<Col span={10}>
<Form.Item
label="服务名称"
name="serviceName"
rules={[
{
required: true,
message: '请输入服务名称',
},
]}
>
<Input
placeholder="请输入服务名称"
disabled={disabled}
maxLength={30}
showCount
allowClear
/>
</Form.Item>
</Col>
</Row>
<Row gutter={8}>
<Col span={10}>
<Form.Item
label="服务版本"
name="serviceVersion"
rules={[
{
required: true,
message: '请输入服务版本',
},
]}
>
<Input
placeholder="请输入服务版本"
disabled={disabled}
maxLength={30}
showCount
allowClear
/>
</Form.Item>
</Col>
</Row>
<Row gutter={8}>
<Col span={20}>
<Form.Item
label="描  述"
name="description"
rules={[
{
required: true,
message: '请输入描述',
},
]}
>
<Input.TextArea
autoSize={{ minRows: 2, maxRows: 6 }}
placeholder="请输入描述,最长128字符"
maxLength={128}
showCount
allowClear
/>
</Form.Item>
</Col>
</Row>

<Form.Item wrapperCol={{ offset: 0, span: 16 }}>
<Button type="primary" htmlType="submit">
{buttonText}
</Button>
<Button
type="default"
htmlType="button"
onClick={cancel}
style={{ marginLeft: '20px' }}
>
取消
</Button>
</Form.Item>
</Form>
</div>
</div>
</div>
);
}

export default ModelDeploymentCreate;

+ 38
- 0
react-ui/src/pages/ModelDeployment/ServerInfo/index.less View File

@@ -0,0 +1,38 @@
.model-deployment-info {
height: 100%;

&__content {
display: flex;
flex-direction: column;
height: calc(100% - 60px);
margin-top: 10px;
padding: 30px 30px 0;
background-color: white;
border-radius: 10px;

&__tabs {
flex: 1;
min-height: 0;
margin-top: 20px;
padding-bottom: 10px;

:global {
.ant-tabs {
height: 100%;

.ant-tabs-nav {
margin-bottom: 10px;
}

.ant-tabs-content {
height: 100%;

.ant-tabs-tabpane {
height: 100%;
}
}
}
}
}
}
}

+ 76
- 0
react-ui/src/pages/ModelDeployment/ServerInfo/index.tsx View File

@@ -0,0 +1,76 @@
/*
* @Author: 赵伟
* @Date: 2024-04-16 13:58:08
* @Description: 镜像详情
*/
import KFIcon from '@/components/KFIcon';
import PageTitle from '@/components/PageTitle';
import SubAreaTitle from '@/components/SubAreaTitle';
import { useSessionStorage } from '@/hooks/sessionStorage';
import { modelDeploymentInfoKey } from '@/utils/sessionStorage';
import { Tabs, type TabsProps } from 'antd';
import { useState } from 'react';
import BasicInfo from '../components/BasicInfo';
import ServerLog from '../components/ServerLog';
import UserGuide from '../components/UserGuide';
import { ModelDeploymentData } from '../types';
import styles from './index.less';

export enum ModelDeploymentTabKey {
Predict = 'Predict', // 预测
Guide = 'Guide', // 调用指南
Log = 'Log', // 服务日志
}

function ModelDeploymentInfo() {
const [activeTab, setActiveTab] = useState<string>(ModelDeploymentTabKey.Predict);
const [modelDeployementInfo] = useSessionStorage<ModelDeploymentData | undefined>(
modelDeploymentInfoKey,
true,
undefined,
);

const tabItems = [
{
key: ModelDeploymentTabKey.Predict,
label: '预测',
icon: <KFIcon type="icon-yuce" />,
},
{
key: ModelDeploymentTabKey.Guide,
label: '调用指南',
icon: <KFIcon type="icon-tiaoyongzhinan" />,
children: <UserGuide info={modelDeployementInfo}></UserGuide>,
},
{
key: ModelDeploymentTabKey.Log,
label: '服务日志',
icon: <KFIcon type="icon-fuwurizhi" />,
children: <ServerLog info={modelDeployementInfo}></ServerLog>,
},
];

// 切换 Tab,重置数据
const hanleTabChange: TabsProps['onChange'] = (value) => {
setActiveTab(value);
};

return (
<div className={styles['model-deployment-info']}>
<PageTitle title="服务详情"></PageTitle>
<div className={styles['model-deployment-info__content']}>
<SubAreaTitle
title="基本信息"
image={require('@/assets/img/mirror-basic.png')}
style={{ marginBottom: '26px' }}
></SubAreaTitle>
<BasicInfo info={modelDeployementInfo} />
<div className={styles['model-deployment-info__content__tabs']}>
<Tabs activeKey={activeTab} items={tabItems} onChange={hanleTabChange} />
</div>
</div>
</div>
);
}

export default ModelDeploymentInfo;

Loading…
Cancel
Save