| @@ -3,6 +3,7 @@ | |||
| * @Date: 2024-04-16 13:58:08 | |||
| * @Description: 开发环境列表 | |||
| */ | |||
| import CommonTableCell from '@/components/CommonTableCell'; | |||
| import DateTableCell from '@/components/DateTableCell'; | |||
| import KFIcon from '@/components/KFIcon'; | |||
| @@ -15,6 +16,7 @@ import { | |||
| stopEditorReq, | |||
| } from '@/services/developmentEnvironment'; | |||
| import themes from '@/styles/theme.less'; | |||
| import { openAntdModal } from '@/utils/modal'; | |||
| import { to } from '@/utils/promise'; | |||
| import { editorUrlKey, setSessionStorageItem } from '@/utils/sessionStorage'; | |||
| import { modalConfirm } from '@/utils/ui'; | |||
| @@ -29,6 +31,7 @@ import { | |||
| } from 'antd'; | |||
| import classNames from 'classnames'; | |||
| import { useEffect, useState } from 'react'; | |||
| import CreateMirrorModal from '../components/CreateMirrorModal'; | |||
| import EditorStatusCell from '../components/EditorStatusCell'; | |||
| import styles from './index.less'; | |||
| @@ -110,6 +113,16 @@ function EditorList() { | |||
| } | |||
| }; | |||
| // 制作镜像 | |||
| const createMirror = (id: number) => { | |||
| const { close } = openAntdModal(CreateMirrorModal, { | |||
| envId: id, | |||
| onOk: () => { | |||
| close(); | |||
| }, | |||
| }); | |||
| }; | |||
| // 处理删除 | |||
| const handleEditorDelete = (record: EditorData) => { | |||
| modalConfirm({ | |||
| @@ -218,6 +231,17 @@ function EditorList() { | |||
| 启动 | |||
| </Button> | |||
| )} | |||
| {record.status === DevEditorStatus.Running ? ( | |||
| <Button | |||
| type="link" | |||
| size="small" | |||
| key="jingxiang" | |||
| icon={<KFIcon type="icon-jingxiang" />} | |||
| onClick={() => createMirror(record.id)} | |||
| > | |||
| 制作镜像 | |||
| </Button> | |||
| ) : null} | |||
| <ConfigProvider | |||
| theme={{ | |||
| token: { | |||
| @@ -0,0 +1,100 @@ | |||
| import KFModal from '@/components/KFModal'; | |||
| import { createEditorMirrorReq } from '@/services/developmentEnvironment'; | |||
| import { to } from '@/utils/promise'; | |||
| import { Form, Input, message, type ModalProps } from 'antd'; | |||
| interface CreateMirrorModalProps extends Omit<ModalProps, 'onOk'> { | |||
| envId: number; // 开发环境id | |||
| onOk: () => void; | |||
| } | |||
| function CreateMirrorModal({ envId, onOk, ...rest }: CreateMirrorModalProps) { | |||
| // 上传请求 | |||
| const createDatasetVersion = async (params: any) => { | |||
| const [res] = await to( | |||
| createEditorMirrorReq({ | |||
| ...params, | |||
| dev_environment_id: envId, | |||
| upload_type: 1, | |||
| version: params['tagName'], | |||
| }), | |||
| ); | |||
| if (res) { | |||
| message.success('创建成功,请到 “AI资产” - “个人镜像” 中查看'); | |||
| onOk?.(); | |||
| } | |||
| }; | |||
| // 提交 | |||
| const onFinish = (formData: any) => { | |||
| createDatasetVersion(formData); | |||
| }; | |||
| return ( | |||
| <KFModal | |||
| {...rest} | |||
| title="制作镜像" | |||
| image={require('@/assets/img/create-experiment.png')} | |||
| width={825} | |||
| okButtonProps={{ | |||
| htmlType: 'submit', | |||
| form: 'form', | |||
| }} | |||
| > | |||
| <Form name="form" layout="vertical" onFinish={onFinish} autoComplete="off"> | |||
| <Form.Item | |||
| label="镜像名称" | |||
| name="name" | |||
| rules={[ | |||
| { | |||
| required: true, | |||
| message: '请输入镜像名称', | |||
| }, | |||
| { | |||
| pattern: /^[a-zA-Z0-9_-]*$/, | |||
| message: '只支持字母、数字、下划线、中横线', | |||
| }, | |||
| ]} | |||
| > | |||
| <Input placeholder="请输入镜像名称" maxLength={64} showCount allowClear /> | |||
| </Form.Item> | |||
| <Form.Item | |||
| label="镜像Tag" | |||
| name="tag_name" | |||
| rules={[ | |||
| { | |||
| required: true, | |||
| message: '请输入镜像Tag', | |||
| }, | |||
| { | |||
| pattern: /^[a-zA-Z0-9_-]*$/, | |||
| message: '只支持字母、数字、下划线、中横线', | |||
| }, | |||
| ]} | |||
| > | |||
| <Input placeholder="请输入镜像Tag" maxLength={64} showCount allowClear /> | |||
| </Form.Item> | |||
| <Form.Item | |||
| label="镜像描述描述" | |||
| name="description" | |||
| rules={[ | |||
| { | |||
| required: true, | |||
| message: '请输入镜像描述', | |||
| }, | |||
| ]} | |||
| > | |||
| <Input.TextArea | |||
| placeholder="请输入镜像描述" | |||
| autoSize={{ minRows: 3, maxRows: 6 }} | |||
| maxLength={256} | |||
| showCount | |||
| allowClear | |||
| /> | |||
| </Form.Item> | |||
| </Form> | |||
| </KFModal> | |||
| ); | |||
| } | |||
| export default CreateMirrorModal; | |||
| @@ -51,7 +51,7 @@ export const getParamRules = (paramType: number, required: boolean = false): For | |||
| // 防止后台返回不是 number 类型 | |||
| if (Number(paramType) === 2) { | |||
| rules.push({ | |||
| pattern: /^-?\d+(\.\d+)?$/, | |||
| pattern: /^-?((0(\.0*[1-9]\d*)?)|([1-9]\d*(\.\d+)?))$/, | |||
| message: '整型必须是数字', | |||
| }); | |||
| } | |||
| @@ -153,6 +153,10 @@ function MirrorCreate() { | |||
| required: true, | |||
| message: '请输入镜像名称', | |||
| }, | |||
| { | |||
| pattern: /^[a-zA-Z0-9_-]*$/, | |||
| message: '只支持字母、数字、下划线、中横线', | |||
| }, | |||
| ]} | |||
| > | |||
| <Input | |||
| @@ -176,6 +180,10 @@ function MirrorCreate() { | |||
| required: true, | |||
| message: '请输入镜像Tag', | |||
| }, | |||
| { | |||
| pattern: /^[a-zA-Z0-9_-]*$/, | |||
| message: '只支持字母、数字、下划线、中横线', | |||
| }, | |||
| ]} | |||
| > | |||
| <Input placeholder="请输入镜像Tag" maxLength={64} showCount allowClear /> | |||
| @@ -49,9 +49,18 @@ export function startEditorReq(id: number) { | |||
| method: 'POST', | |||
| }); | |||
| } | |||
| // 停止编辑器 | |||
| export function stopEditorReq(id: number) { | |||
| return request(`/api/mmp/jupyter/stop/${id}`, { | |||
| method: 'DELETE', | |||
| }); | |||
| } | |||
| // 制作镜像 | |||
| export function createEditorMirrorReq(data: any) { | |||
| return request(`/api/mmp/image/saveImage`, { | |||
| method: 'POST', | |||
| data, | |||
| }); | |||
| } | |||