| @@ -155,7 +155,7 @@ export default [ | |||||
| component: './AutoML/List/index', | component: './AutoML/List/index', | ||||
| }, | }, | ||||
| { | { | ||||
| name: '自动机器学习详情', | |||||
| name: '实验详情', | |||||
| path: 'info/:id', | path: 'info/:id', | ||||
| component: './AutoML/Info/index', | component: './AutoML/Info/index', | ||||
| }, | }, | ||||
| @@ -170,7 +170,7 @@ export default [ | |||||
| component: './AutoML/Create/index', | component: './AutoML/Create/index', | ||||
| }, | }, | ||||
| { | { | ||||
| name: '实验实例', | |||||
| name: '实验实例详情', | |||||
| path: 'instance/:autoMLId/:id', | path: 'instance/:autoMLId/:id', | ||||
| component: './AutoML/Instance/index', | component: './AutoML/Instance/index', | ||||
| }, | }, | ||||
| @@ -261,25 +261,46 @@ export default [ | |||||
| path: '', | path: '', | ||||
| component: './ModelDeployment/List', | component: './ModelDeployment/List', | ||||
| }, | }, | ||||
| { | |||||
| name: '服务详情', | |||||
| path: 'serviceInfo/:id', | |||||
| component: './ModelDeployment/ServiceInfo', | |||||
| }, | |||||
| { | |||||
| name: '服务版本详情', | |||||
| path: 'versionInfo/:id', | |||||
| component: './ModelDeployment/VersionInfo', | |||||
| }, | |||||
| { | { | ||||
| name: '创建推理服务', | name: '创建推理服务', | ||||
| path: 'createService', | path: 'createService', | ||||
| component: './ModelDeployment/CreateService', | component: './ModelDeployment/CreateService', | ||||
| }, | }, | ||||
| { | { | ||||
| name: '新增服务版本', | |||||
| path: 'addVersion/:id', | |||||
| component: './ModelDeployment/CreateVersion', | |||||
| name: '编辑推理服务', | |||||
| path: 'editService/:serviceId', | |||||
| component: './ModelDeployment/CreateService', | |||||
| }, | |||||
| { | |||||
| name: '服务详情', | |||||
| path: 'serviceInfo/:serviceId', | |||||
| routes: [ | |||||
| { | |||||
| name: '服务详情', | |||||
| path: '', | |||||
| component: './ModelDeployment/ServiceInfo', | |||||
| }, | |||||
| { | |||||
| name: '新增服务版本', | |||||
| path: 'createVersion', | |||||
| component: './ModelDeployment/CreateVersion', | |||||
| }, | |||||
| { | |||||
| name: '更新服务版本', | |||||
| path: 'updateVersion', | |||||
| component: './ModelDeployment/CreateVersion', | |||||
| }, | |||||
| { | |||||
| name: '重启服务版本', | |||||
| path: 'restartVersion', | |||||
| component: './ModelDeployment/CreateVersion', | |||||
| }, | |||||
| { | |||||
| name: '服务版本详情', | |||||
| path: 'versionInfo/:id', | |||||
| component: './ModelDeployment/VersionInfo', | |||||
| }, | |||||
| ], | |||||
| }, | }, | ||||
| ], | ], | ||||
| }, | }, | ||||
| @@ -1,3 +1,9 @@ | |||||
| /* | |||||
| * @Author: 赵伟 | |||||
| * @Date: 2024-11-06 14:53:37 | |||||
| * @Description: SessionStorage hook | |||||
| */ | |||||
| import SessionStorage from '@/utils/sessionStorage'; | import SessionStorage from '@/utils/sessionStorage'; | ||||
| import { useEffect, useState } from 'react'; | import { useEffect, useState } from 'react'; | ||||
| @@ -4,7 +4,6 @@ | |||||
| * @Description: 创建服务版本 | * @Description: 创建服务版本 | ||||
| */ | */ | ||||
| import PageTitle from '@/components/PageTitle'; | import PageTitle from '@/components/PageTitle'; | ||||
| import { AutoMLEnsembleClass, AutoMLTaskType } from '@/enums'; | import { AutoMLEnsembleClass, AutoMLTaskType } from '@/enums'; | ||||
| import { addAutoMLReq, getAutoMLInfoReq, updateAutoMLReq } from '@/services/autoML'; | import { addAutoMLReq, getAutoMLInfoReq, updateAutoMLReq } from '@/services/autoML'; | ||||
| import { convertEmptyStringToUndefined, parseJsonText, trimCharacter } from '@/utils'; | import { convertEmptyStringToUndefined, parseJsonText, trimCharacter } from '@/utils'; | ||||
| @@ -167,7 +167,7 @@ function EditorCreate() { | |||||
| <Row gutter={8}> | <Row gutter={8}> | ||||
| <Col span={10}> | <Col span={10}> | ||||
| <Form.Item | <Form.Item | ||||
| label="镜 像" | |||||
| label="镜像" | |||||
| name="image" | name="image" | ||||
| rules={[ | rules={[ | ||||
| { | { | ||||
| @@ -188,17 +188,7 @@ function EditorCreate() { | |||||
| </Row> | </Row> | ||||
| <Row gutter={8}> | <Row gutter={8}> | ||||
| <Col span={10}> | <Col span={10}> | ||||
| <Form.Item | |||||
| label="模 型" | |||||
| name="model" | |||||
| rules={[ | |||||
| { | |||||
| validator: requiredValidator, | |||||
| message: '请选择模型', | |||||
| }, | |||||
| ]} | |||||
| required | |||||
| > | |||||
| <Form.Item label="模型" name="model"> | |||||
| <ResourceSelect | <ResourceSelect | ||||
| type={ResourceSelectorType.Model} | type={ResourceSelectorType.Model} | ||||
| placeholder="请选择模型" | placeholder="请选择模型" | ||||
| @@ -210,17 +200,7 @@ function EditorCreate() { | |||||
| </Row> | </Row> | ||||
| <Row gutter={8}> | <Row gutter={8}> | ||||
| <Col span={10}> | <Col span={10}> | ||||
| <Form.Item | |||||
| label="数据集" | |||||
| name="dataset" | |||||
| rules={[ | |||||
| { | |||||
| validator: requiredValidator, | |||||
| message: '请选择数据集', | |||||
| }, | |||||
| ]} | |||||
| required | |||||
| > | |||||
| <Form.Item label="数据集" name="dataset"> | |||||
| <ResourceSelect | <ResourceSelect | ||||
| type={ResourceSelectorType.Dataset} | type={ResourceSelectorType.Dataset} | ||||
| placeholder="请选择数据集" | placeholder="请选择数据集" | ||||
| @@ -7,14 +7,12 @@ | |||||
| import PageTitle from '@/components/PageTitle'; | import PageTitle from '@/components/PageTitle'; | ||||
| import SubAreaTitle from '@/components/SubAreaTitle'; | import SubAreaTitle from '@/components/SubAreaTitle'; | ||||
| import { CommonTabKeys, serviceTypeOptions } from '@/enums'; | import { CommonTabKeys, serviceTypeOptions } from '@/enums'; | ||||
| import { createServiceReq, updateServiceReq } from '@/services/modelDeployment'; | |||||
| import { createServiceReq, getServiceInfoReq, updateServiceReq } from '@/services/modelDeployment'; | |||||
| import { to } from '@/utils/promise'; | import { to } from '@/utils/promise'; | ||||
| import SessionStorage from '@/utils/sessionStorage'; | |||||
| import { useNavigate } from '@umijs/max'; | |||||
| import { useNavigate, useParams } from '@umijs/max'; | |||||
| import { App, Button, Col, Form, Input, Row, Select } from 'antd'; | import { App, Button, Col, Form, Input, Row, Select } from 'antd'; | ||||
| import { pick } from 'lodash'; | |||||
| import { useEffect, useState } from 'react'; | import { useEffect, useState } from 'react'; | ||||
| import { ServiceData, ServiceOperationType, createServiceVersionMessage } from '../types'; | |||||
| import { ServiceData, createServiceVersionMessage } from '../types'; | |||||
| import styles from './index.less'; | import styles from './index.less'; | ||||
| // 表单数据 | // 表单数据 | ||||
| @@ -27,40 +25,49 @@ export type FormData = { | |||||
| function CreateService() { | function CreateService() { | ||||
| const navigate = useNavigate(); | const navigate = useNavigate(); | ||||
| const [form] = Form.useForm(); | const [form] = Form.useForm(); | ||||
| const [operationType, setOperationType] = useState(ServiceOperationType.Create); | |||||
| const [serviceInfo, setServiceInfo] = useState<ServiceData | undefined>(undefined); | const [serviceInfo, setServiceInfo] = useState<ServiceData | undefined>(undefined); | ||||
| const { message } = App.useApp(); | const { message } = App.useApp(); | ||||
| const params = useParams(); | |||||
| const serviceId = params.serviceId; | |||||
| useEffect(() => { | useEffect(() => { | ||||
| const res = SessionStorage.getItem(SessionStorage.serviceInfoKey, true); | |||||
| if (res) { | |||||
| setOperationType(res.operationType); | |||||
| setServiceInfo(res); | |||||
| form.setFieldsValue(pick(res, ['service_name', 'service_type', 'description'])); | |||||
| if (serviceId) { | |||||
| getServiceInfo(); | |||||
| } | } | ||||
| return () => { | |||||
| SessionStorage.removeItem(SessionStorage.serviceInfoKey); | |||||
| }; | |||||
| }, []); | }, []); | ||||
| // 获取服务详情 | |||||
| const getServiceInfo = async () => { | |||||
| const [res] = await to(getServiceInfoReq(serviceId)); | |||||
| if (res && res.data) { | |||||
| setServiceInfo(res.data); | |||||
| const { service_type, service_name, description } = res.data; | |||||
| form.setFieldsValue({ | |||||
| service_type, | |||||
| service_name, | |||||
| description, | |||||
| }); | |||||
| } | |||||
| }; | |||||
| // 创建、更新服务 | // 创建、更新服务 | ||||
| const createService = async (formData: FormData) => { | const createService = async (formData: FormData) => { | ||||
| const request = | |||||
| operationType === ServiceOperationType.Create ? createServiceReq : updateServiceReq; | |||||
| const params = | |||||
| operationType === ServiceOperationType.Create | |||||
| ? formData | |||||
| : { | |||||
| id: serviceInfo?.id, | |||||
| ...formData, | |||||
| }; | |||||
| const request = serviceId ? updateServiceReq : createServiceReq; | |||||
| const params = serviceId | |||||
| ? { | |||||
| id: serviceId, | |||||
| ...formData, | |||||
| } | |||||
| : formData; | |||||
| const [res] = await to(request(params)); | const [res] = await to(request(params)); | ||||
| if (res && res.data) { | if (res && res.data) { | ||||
| message.success('操作成功'); | message.success('操作成功'); | ||||
| navigate(-1); | navigate(-1); | ||||
| setTimeout(() => { | |||||
| window.postMessage({ type: createServiceVersionMessage, payload: res.data.id }); | |||||
| }, 500); | |||||
| if (!serviceId) { | |||||
| setTimeout(() => { | |||||
| window.postMessage({ type: createServiceVersionMessage, payload: res.data.id }); | |||||
| }, 500); | |||||
| } | |||||
| } | } | ||||
| }; | }; | ||||
| @@ -74,8 +81,8 @@ function CreateService() { | |||||
| navigate(-1); | navigate(-1); | ||||
| }; | }; | ||||
| const disabled = operationType !== ServiceOperationType.Create; | |||||
| const title = operationType === ServiceOperationType.Create ? '创建推理服务' : '更新推理服务'; | |||||
| const disabled = !!serviceId; | |||||
| const title = serviceId ? '编辑推理服务' : '创建推理服务'; | |||||
| return ( | return ( | ||||
| <div className={styles['model-deployment-create']}> | <div className={styles['model-deployment-create']}> | ||||
| @@ -27,12 +27,7 @@ import { useNavigate, useParams } from '@umijs/max'; | |||||
| import { App, Button, Col, Flex, Form, Input, InputNumber, Row, Select } from 'antd'; | import { App, Button, Col, Flex, Form, Input, InputNumber, Row, Select } from 'antd'; | ||||
| import { omit, pick } from 'lodash'; | import { omit, pick } from 'lodash'; | ||||
| import { useEffect, useState } from 'react'; | import { useEffect, useState } from 'react'; | ||||
| import { | |||||
| CreateServiceVersionFrom, | |||||
| ServiceData, | |||||
| ServiceOperationType, | |||||
| ServiceVersionData, | |||||
| } from '../types'; | |||||
| import { CreateServiceVersionFrom, ServiceOperationType, ServiceVersionData } from '../types'; | |||||
| import styles from './index.less'; | import styles from './index.less'; | ||||
| // 表单数据 | // 表单数据 | ||||
| @@ -49,6 +44,11 @@ export type FormData = { | |||||
| env_variables: { key: string; value: string }[]; // 环境变量 | env_variables: { key: string; value: string }[]; // 环境变量 | ||||
| }; | }; | ||||
| type ServiceVersionCache = ServiceVersionData & { | |||||
| operationType: ServiceOperationType; | |||||
| lastPage: CreateServiceVersionFrom; | |||||
| }; | |||||
| function CreateServiceVersion() { | function CreateServiceVersion() { | ||||
| const navigate = useNavigate(); | const navigate = useNavigate(); | ||||
| const [form] = Form.useForm(); | const [form] = Form.useForm(); | ||||
| @@ -56,18 +56,16 @@ function CreateServiceVersion() { | |||||
| const [operationType, setOperationType] = useState(ServiceOperationType.Create); | const [operationType, setOperationType] = useState(ServiceOperationType.Create); | ||||
| const [lastPage, setLastPage] = useState(CreateServiceVersionFrom.ServiceInfo); | const [lastPage, setLastPage] = useState(CreateServiceVersionFrom.ServiceInfo); | ||||
| const { message } = App.useApp(); | const { message } = App.useApp(); | ||||
| const [serviceInfo, setServiceInfo] = useState<ServiceData | undefined>(undefined); | |||||
| // const [serviceInfo, setServiceInfo] = useState<ServiceData | undefined>(undefined); | |||||
| const [versionInfo, setVersionInfo] = useState<ServiceVersionData | undefined>(undefined); | const [versionInfo, setVersionInfo] = useState<ServiceVersionData | undefined>(undefined); | ||||
| const params = useParams(); | const params = useParams(); | ||||
| const id = params.id; | |||||
| const serviceId = params.serviceId; | |||||
| useEffect(() => { | useEffect(() => { | ||||
| const res: | |||||
| | (ServiceVersionData & { | |||||
| operationType: ServiceOperationType; | |||||
| lastPage: CreateServiceVersionFrom; | |||||
| }) | |||||
| | undefined = SessionStorage.getItem(SessionStorage.serviceVersionInfoKey, true); | |||||
| const res: ServiceVersionCache | undefined = SessionStorage.getItem( | |||||
| SessionStorage.serviceVersionInfoKey, | |||||
| true, | |||||
| ); | |||||
| if (res) { | if (res) { | ||||
| setOperationType(res.operationType); | setOperationType(res.operationType); | ||||
| setLastPage(res.lastPage); | setLastPage(res.lastPage); | ||||
| @@ -109,9 +107,9 @@ function CreateServiceVersion() { | |||||
| // 获取服务详情 | // 获取服务详情 | ||||
| const getServiceInfo = async () => { | const getServiceInfo = async () => { | ||||
| const [res] = await to(getServiceInfoReq(id)); | |||||
| const [res] = await to(getServiceInfoReq(serviceId)); | |||||
| if (res && res.data) { | if (res && res.data) { | ||||
| setServiceInfo(res.data); | |||||
| // setServiceInfo(res.data); | |||||
| form.setFieldsValue({ | form.setFieldsValue({ | ||||
| service_name: res.data.service_name, | service_name: res.data.service_name, | ||||
| }); | }); | ||||
| @@ -144,12 +142,15 @@ function CreateServiceVersion() { | |||||
| showValue: 'show_value', | showValue: 'show_value', | ||||
| }) | }) | ||||
| : undefined, | : undefined, | ||||
| service_id: serviceInfo?.id, | |||||
| service_id: serviceId, | |||||
| }; | }; | ||||
| const params = | const params = | ||||
| operationType === ServiceOperationType.Create | operationType === ServiceOperationType.Create | ||||
| ? object | |||||
| ? { | |||||
| ...object, | |||||
| deploy_type: 'web', | |||||
| } | |||||
| : { | : { | ||||
| id: versionInfo?.id, | id: versionInfo?.id, | ||||
| rerun: operationType === ServiceOperationType.Restart ? true : false, | rerun: operationType === ServiceOperationType.Restart ? true : false, | ||||
| @@ -168,7 +169,7 @@ function CreateServiceVersion() { | |||||
| if (lastPage === CreateServiceVersionFrom.ServiceInfo) { | if (lastPage === CreateServiceVersionFrom.ServiceInfo) { | ||||
| navigate(-1); | navigate(-1); | ||||
| } else { | } else { | ||||
| navigate(`/modelDeployment/serviceInfo/${serviceInfo?.id}`, { replace: true }); | |||||
| navigate(`serviceInfo/${serviceId}`, { replace: true }); | |||||
| } | } | ||||
| } | } | ||||
| }; | }; | ||||
| @@ -116,23 +116,18 @@ function ModelDeployment() { | |||||
| }; | }; | ||||
| // 创建、更新服务 | // 创建、更新服务 | ||||
| const createService = (type: ServiceOperationType, record?: ServiceData) => { | |||||
| SessionStorage.setItem( | |||||
| SessionStorage.serviceInfoKey, | |||||
| { | |||||
| ...record, | |||||
| operationType: type, | |||||
| }, | |||||
| true, | |||||
| ); | |||||
| const createService = (record?: ServiceData) => { | |||||
| setCacheState({ | setCacheState({ | ||||
| pagination, | pagination, | ||||
| searchText, | searchText, | ||||
| serviceType: serviceType, | serviceType: serviceType, | ||||
| }); | }); | ||||
| navigate(`/modelDeployment/createService`); | |||||
| if (record) { | |||||
| navigate(`editService/${record.id}`); | |||||
| } else { | |||||
| navigate('createService'); | |||||
| } | |||||
| }; | }; | ||||
| // 查看详情 | // 查看详情 | ||||
| @@ -143,7 +138,7 @@ function ModelDeployment() { | |||||
| serviceType: serviceType, | serviceType: serviceType, | ||||
| }); | }); | ||||
| navigate(`/modelDeployment/serviceInfo/${record.id}`); | |||||
| navigate(`serviceInfo/${record.id}`); | |||||
| }; | }; | ||||
| const handleMessage = (e: MessageEvent) => { | const handleMessage = (e: MessageEvent) => { | ||||
| @@ -172,7 +167,7 @@ function ModelDeployment() { | |||||
| true, | true, | ||||
| ); | ); | ||||
| navigate(`/modelDeployment/addVersion/${serviceId}`); | |||||
| navigate(`serviceInfo/${serviceId}/createVersion`); | |||||
| }; | }; | ||||
| // 分页切换 | // 分页切换 | ||||
| @@ -248,7 +243,7 @@ function ModelDeployment() { | |||||
| size="small" | size="small" | ||||
| key="edit" | key="edit" | ||||
| icon={<KFIcon type="icon-bianji" />} | icon={<KFIcon type="icon-bianji" />} | ||||
| onClick={() => createService(ServiceOperationType.Update, record)} | |||||
| onClick={() => createService(record)} | |||||
| > | > | ||||
| 编辑 | 编辑 | ||||
| </Button> | </Button> | ||||
| @@ -307,7 +302,7 @@ function ModelDeployment() { | |||||
| <Button | <Button | ||||
| style={{ marginLeft: 'auto', marginRight: '20px' }} | style={{ marginLeft: 'auto', marginRight: '20px' }} | ||||
| type="default" | type="default" | ||||
| onClick={() => createService(ServiceOperationType.Create)} | |||||
| onClick={() => createService()} | |||||
| icon={<KFIcon type="icon-xinjian2" />} | icon={<KFIcon type="icon-xinjian2" />} | ||||
| > | > | ||||
| 创建推理服务 | 创建推理服务 | ||||
| @@ -66,7 +66,7 @@ function ServiceInfo() { | |||||
| }, | }, | ||||
| ); | ); | ||||
| const params = useParams(); | const params = useParams(); | ||||
| const id = params.id; | |||||
| const serviceId = params.serviceId; | |||||
| const [serviceInfo, setServiceInfo] = useState<ServiceData | undefined>(undefined); | const [serviceInfo, setServiceInfo] = useState<ServiceData | undefined>(undefined); | ||||
| const basicInfo = [ | const basicInfo = [ | ||||
| { | { | ||||
| @@ -99,7 +99,7 @@ function ServiceInfo() { | |||||
| // 获取服务详情 | // 获取服务详情 | ||||
| const getServiceInfo = async () => { | const getServiceInfo = async () => { | ||||
| const [res] = await to(getServiceInfoReq(id)); | |||||
| const [res] = await to(getServiceInfoReq(serviceId)); | |||||
| if (res && res.data) { | if (res && res.data) { | ||||
| setServiceInfo(res.data); | setServiceInfo(res.data); | ||||
| } | } | ||||
| @@ -112,7 +112,7 @@ function ServiceInfo() { | |||||
| size: pagination.pageSize, | size: pagination.pageSize, | ||||
| version: searchText, | version: searchText, | ||||
| run_state: serviceStatus, | run_state: serviceStatus, | ||||
| service_id: id, | |||||
| service_id: serviceId, | |||||
| }; | }; | ||||
| const [res] = await to(getServiceVersionsReq(params)); | const [res] = await to(getServiceVersionsReq(params)); | ||||
| if (res && res.data) { | if (res && res.data) { | ||||
| @@ -201,7 +201,13 @@ function ServiceInfo() { | |||||
| serviceStatus: serviceStatus, | serviceStatus: serviceStatus, | ||||
| }); | }); | ||||
| navigate(`/modelDeployment/addVersion/${id}`); | |||||
| if (type === ServiceOperationType.Update) { | |||||
| navigate('updateVersion'); | |||||
| } else if (type === ServiceOperationType.Restart) { | |||||
| navigate('restartVersion'); | |||||
| } else { | |||||
| navigate('createVersion'); | |||||
| } | |||||
| }; | }; | ||||
| // 查看详情 | // 查看详情 | ||||
| @@ -212,7 +218,7 @@ function ServiceInfo() { | |||||
| serviceStatus: serviceStatus, | serviceStatus: serviceStatus, | ||||
| }); | }); | ||||
| navigate(`/modelDeployment/versionInfo/${record.id}`); | |||||
| navigate(`versionInfo/${record.id}`); | |||||
| }; | }; | ||||
| // 分页切换 | // 分页切换 | ||||
| @@ -3,8 +3,6 @@ import { parseJsonText } from './index'; | |||||
| export default class SessionStorage { | export default class SessionStorage { | ||||
| // 用于新建镜像 | // 用于新建镜像 | ||||
| static readonly mirrorNameKey = 'mirror-name'; | static readonly mirrorNameKey = 'mirror-name'; | ||||
| // 模型部署服务 | |||||
| static readonly serviceInfoKey = 'service-info'; | |||||
| // 模型部署服务版本 | // 模型部署服务版本 | ||||
| static readonly serviceVersionInfoKey = 'service-version-info'; | static readonly serviceVersionInfoKey = 'service-version-info'; | ||||
| // 编辑器 url | // 编辑器 url | ||||