Browse Source

feat: 完成开发环境

pull/82/head
cp3hnu 1 year ago
parent
commit
5ac61d2cd6
13 changed files with 792 additions and 51 deletions
  1. BIN
      react-ui/src/assets/img/editor-parameter.png
  2. +1
    -1
      react-ui/src/components/ParameterInput/index.tsx
  3. +17
    -0
      react-ui/src/pages/DevelopmentEnvironment/Create/index.less
  4. +344
    -0
      react-ui/src/pages/DevelopmentEnvironment/Create/index.tsx
  5. +22
    -0
      react-ui/src/pages/DevelopmentEnvironment/List/index.less
  6. +263
    -0
      react-ui/src/pages/DevelopmentEnvironment/List/index.tsx
  7. +19
    -0
      react-ui/src/pages/DevelopmentEnvironment/components/EditorStatusCell/index.less
  8. +44
    -0
      react-ui/src/pages/DevelopmentEnvironment/components/EditorStatusCell/index.tsx
  9. +0
    -18
      react-ui/src/pages/Mirror/Info/index.less
  10. +1
    -2
      react-ui/src/pages/Mirror/Info/index.tsx
  11. +22
    -14
      react-ui/src/pages/ModelDeployment/Create/index.tsx
  12. +0
    -16
      react-ui/src/services/developmentEnvironment/index.js
  13. +59
    -0
      react-ui/src/services/developmentEnvironment/index.ts

BIN
react-ui/src/assets/img/editor-parameter.png View File

Before After
Width: 34  |  Height: 31  |  Size: 1.3 kB

+ 1
- 1
react-ui/src/components/ParameterInput/index.tsx View File

@@ -43,7 +43,7 @@ function ParameterInput({
} }
const isSelect = valueObj?.fromSelect; const isSelect = valueObj?.fromSelect;
const InputComponent = textArea ? Input.TextArea : Input; const InputComponent = textArea ? Input.TextArea : Input;
const placeholder = valueObj?.placeholder;
const placeholder = valueObj?.placeholder || rest?.placeholder;


return ( return (
<> <>


+ 17
- 0
react-ui/src/pages/DevelopmentEnvironment/Create/index.less View File

@@ -0,0 +1,17 @@
.editor-create {
height: 100%;

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

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

+ 344
- 0
react-ui/src/pages/DevelopmentEnvironment/Create/index.tsx View File

@@ -0,0 +1,344 @@
/*
* @Author: 赵伟
* @Date: 2024-04-16 13:58:08
* @Description: 创建镜像
*/
import KFIcon from '@/components/KFIcon';
import KFRadio, { type KFRadioItem } from '@/components/KFRadio';
import PageTitle from '@/components/PageTitle';
import ParameterInput from '@/components/ParameterInput';
import SubAreaTitle from '@/components/SubAreaTitle';
import { useComputingResource } from '@/hooks/resource';
import ResourceSelectorModal, {
ResourceSelectorResponse,
ResourceSelectorType,
selectorTypeConfig,
} from '@/pages/Pipeline/components/ResourceSelectorModal';
import { createEditorReq } from '@/services/developmentEnvironment';
import { openAntdModal } from '@/utils/modal';
import { to } from '@/utils/promise';
import { useNavigate } from '@umijs/max';
import { App, Button, Col, Form, Input, Row, Select } from 'antd';
import { pick } from 'lodash';
import { useState } from 'react';
import styles from './index.less';

type FormData = {
name: string;
computing_resource: string;
standard: string;
image: string;
model: ResourceSelectorResponse;
dataset: ResourceSelectorResponse;
};

enum ComputingResourceType {
GPU = 'GPU',
NPU = 'NPU',
}

const EditorRadioItems: KFRadioItem[] = [
{
key: ComputingResourceType.GPU,
title: '英伟达GPU',
icon: <KFIcon type="icon-jiyugongwangjingxiang" />,
},
{
key: ComputingResourceType.NPU,
title: '昇腾NPU',
icon: <KFIcon type="icon-bendishangchuan" />,
},
];

function EditorCreate() {
const navgite = useNavigate();
const [form] = Form.useForm();
const { message } = App.useApp();
const [resourceStandardList, filterResourceStandard] = useComputingResource();
const [selectedModel, setSelectedModel] = useState<ResourceSelectorResponse | undefined>(
undefined,
); // 选择的模型,为了再次打开时恢复原来的选择
const [selectedDataset, setSelectedDataset] = useState<ResourceSelectorResponse | undefined>(
undefined,
); // 选择的数据集,为了再次打开时恢复原来的选择
const [selectedMirror, setSelectedMirror] = useState<ResourceSelectorResponse | undefined>(
undefined,
); // 选择的镜像,为了再次打开时恢复原来的选择

// 创建编辑器
const createEditor = async (formData: FormData) => {
// const { model, dataset } = formData;
// const params = {
// ...formData,
// model: JSON.stringify(omit(model, ['showValue'])),
// dataset: JSON.stringify(dataset, ['showValue']),
// };
const [res] = await to(createEditorReq(formData));
if (res) {
message.success('创建成功');
navgite(-1);
}
};

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

// 取消
const cancel = () => {
navgite(-1);
};
// 获取选择数据集、模型后面按钮 icon
const getSelectBtnIcon = (type: ResourceSelectorType) => {
return <KFIcon type={selectorTypeConfig[type].buttonIcon} font={16} />;
};

// 选择模型、镜像、数据集
const selectResource = (name: string, type: ResourceSelectorType) => {
let resource: ResourceSelectorResponse | undefined;
switch (type) {
case ResourceSelectorType.Model:
resource = selectedModel;
break;
case ResourceSelectorType.Dataset:
resource = selectedDataset;
break;
default:
resource = selectedMirror;
break;
}
const { close } = openAntdModal(ResourceSelectorModal, {
type,
defaultExpandedKeys: resource ? [resource.id] : [],
defaultCheckedKeys: resource ? [`${resource.id}-${resource.version}`] : [],
defaultActiveTab: resource?.activeTab,
onOk: (res) => {
if (res) {
if (type === ResourceSelectorType.Mirror) {
form.setFieldValue(name, res.path);
setSelectedMirror(res);
} else {
const showValue = `${res.name}:${res.version}`;
form.setFieldValue(name, {
...pick(res, ['id', 'version', 'path']),
showValue,
});
if (type === ResourceSelectorType.Model) {
setSelectedModel(res);
} else if (type === ResourceSelectorType.Dataset) {
setSelectedDataset(res);
}
}
} else {
if (type === ResourceSelectorType.Model) {
setSelectedModel(undefined);
} else if (type === ResourceSelectorType.Dataset) {
setSelectedDataset(undefined);
} else if (type === ResourceSelectorType.Mirror) {
setSelectedMirror(undefined);
}
form.setFieldValue(name, '');
}
close();
},
});
};

return (
<div className={styles['editor-create']}>
<PageTitle title="创建编辑器"></PageTitle>
<div className={styles['editor-create__content']}>
<div>
<Form
name="editor-create"
labelCol={{ flex: '100px' }}
wrapperCol={{ flex: 1 }}
labelAlign="left"
form={form}
initialValues={{ computing_resource: ComputingResourceType.GPU }}
onFinish={handleSubmit}
size="large"
>
<SubAreaTitle
title="基本信息"
image={require('@/assets/img/mirror-basic.png')}
style={{ marginBottom: '26px' }}
></SubAreaTitle>
<Row gutter={10}>
<Col span={10}>
<Form.Item
label="任务名称"
name="name"
rules={[
{
required: true,
message: '请输入任务名称',
},
]}
>
<Input placeholder="请输入任务名称" maxLength={64} showCount allowClear />
</Form.Item>
</Col>
</Row>
<Row gutter={10}>
<Col span={10}>
<Form.Item
label="计算资源"
name="computing_resource"
rules={[
{
required: true,
message: '请选择计算资源',
},
]}
>
<KFRadio items={EditorRadioItems}></KFRadio>
</Form.Item>
</Col>
</Row>
<Row gutter={8}>
<Col span={10}>
<Form.Item
label="资源规格"
name="standard"
rules={[
{
required: true,
message: '请选择资源规格',
},
]}
>
<Select
showSearch
placeholder="请选择资源规格"
filterOption={filterResourceStandard}
options={resourceStandardList}
fieldNames={{
label: 'description',
value: 'standard',
}}
/>
</Form.Item>
</Col>
</Row>
<SubAreaTitle
title="参数设置"
image={require('@/assets/img/editor-parameter.png')}
style={{ marginTop: '20px', marginBottom: '24px' }}
></SubAreaTitle>
<Row gutter={8}>
<Col span={10}>
<Form.Item
label="镜像"
name="image"
rules={[
{
required: true,
message: '请输入镜像',
},
]}
>
<ParameterInput
placeholder="请选择镜像"
canInput={false}
size="large"
onClick={() => selectResource('image', ResourceSelectorType.Mirror)}
/>
</Form.Item>
</Col>
<Col span={10}>
<Button
size="large"
type="link"
icon={getSelectBtnIcon(ResourceSelectorType.Mirror)}
onClick={() => selectResource('image', ResourceSelectorType.Mirror)}
>
选择镜像
</Button>
</Col>
</Row>
<Row gutter={8}>
<Col span={10}>
<Form.Item
label="模型"
name="model"
rules={[
{
required: true,
message: '请选择模型',
},
]}
>
<ParameterInput
placeholder="请选择模型"
canInput={false}
size="large"
onClick={() => selectResource('model', ResourceSelectorType.Model)}
/>
</Form.Item>
</Col>
<Col span={10}>
<Button
size="large"
type="link"
icon={getSelectBtnIcon(ResourceSelectorType.Model)}
onClick={() => selectResource('model', ResourceSelectorType.Model)}
>
选择模型
</Button>
</Col>
</Row>
<Row gutter={8}>
<Col span={10}>
<Form.Item
label="数据集"
name="dataset"
rules={[
{
required: true,
message: '请选择数据集',
},
]}
>
<ParameterInput
placeholder="请选择数据集"
canInput={false}
size="large"
onClick={() => selectResource('dataset', ResourceSelectorType.Dataset)}
/>
</Form.Item>
</Col>
<Col span={10}>
<Button
size="large"
type="link"
icon={getSelectBtnIcon(ResourceSelectorType.Dataset)}
onClick={() => selectResource('dataset', ResourceSelectorType.Dataset)}
>
选择数据集
</Button>
</Col>
</Row>

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

export default EditorCreate;

+ 22
- 0
react-ui/src/pages/DevelopmentEnvironment/List/index.less View File

@@ -0,0 +1,22 @@
.develop-env {
height: 100%;
&__header {
display: flex;
align-items: center;
justify-content: flex-end;
height: 50px;
margin-bottom: 10px;
padding: 0 30px;
background-image: url(@/assets/img/page-title-bg.png);
background-repeat: no-repeat;
background-position: top center;
background-size: 100% 100%;
}

&__table {
height: calc(100% - 60px);
padding: 20px 30px 0;
background-color: white;
border-radius: 10px;
}
}

+ 263
- 0
react-ui/src/pages/DevelopmentEnvironment/List/index.tsx View File

@@ -0,0 +1,263 @@
/*
* @Author: 赵伟
* @Date: 2024-04-16 13:58:08
* @Description: 开发环境
*/
import CommonTableCell from '@/components/CommonTableCell';
import DateTableCell from '@/components/DateTableCell';
import KFIcon from '@/components/KFIcon';
import { DevEditorStatus } from '@/enums';
import { useCacheState } from '@/hooks/pageCacheState';
import {
deleteEditorReq,
getEditorListReq,
startEditorReq,
stopEditorReq,
} from '@/services/developmentEnvironment';
import themes from '@/styles/theme.less';
import { to } from '@/utils/promise';
import { modalConfirm } from '@/utils/ui';
import { useNavigate } from '@umijs/max';
import {
App,
Button,
ConfigProvider,
Table,
type TablePaginationConfig,
type TableProps,
} from 'antd';
import classNames from 'classnames';
import { useEffect, useState } from 'react';
import EditorStatusCell from '../components/EditorStatusCell';
import styles from './index.less';

export type EditorData = {
id: number;
name: string;
status: string;
computing_resource: string;
update_by: string;
create_time: string;
};

function EditorList() {
const navigate = useNavigate();
const [cacheState, setCacheState] = useCacheState();
const { message } = App.useApp();
const [tableData, setTableData] = useState<EditorData[]>([]);
const [total, setTotal] = useState(0);
const [pagination, setPagination] = useState<TablePaginationConfig>(
cacheState?.pagination ?? {
current: 1,
pageSize: 10,
},
);

useEffect(() => {
getEditorList();
}, [pagination]);

// 获取编辑器列表
const getEditorList = async () => {
const params: Record<string, any> = {
page: pagination.current! - 1,
size: pagination.pageSize,
};
const [res] = await to(getEditorListReq(params));
if (res && res.data) {
const { content = [], totalElements = 0 } = res.data;
setTableData(content);
setTotal(totalElements);
}
};

// 删除编辑器
const deleteEditor = async (id: number) => {
const [res] = await to(deleteEditorReq(id));
if (res) {
message.success('删除成功');
// 如果是一页的唯一数据,删除时,请求第一页的数据
// 否则直接刷新这一页的数据
// 避免回到第一页
if (tableData.length > 1) {
setPagination((prev) => ({
...prev,
current: 1,
}));
} else {
getEditorList();
}
}
};

// 启动编辑器
const startEditor = async (id: number) => {
const [res] = await to(startEditorReq(id));
if (res) {
message.success('操作成功');
getEditorList();
}
};

// 停止编辑器
const stopEditor = async (id: number) => {
const [res] = await to(stopEditorReq(id));
if (res) {
message.success('操作成功');
getEditorList();
}
};

// 处理删除
const handleEditorDelete = (record: EditorData) => {
modalConfirm({
title: '删除后,该编辑器将不可恢复',
content: '是否确认删除?',
onOk: () => {
deleteEditor(record.id);
},
});
};

// 创建编辑器
const createEditor = () => {
navigate(`/developmentEnvironment/create`);
setCacheState({
pagination,
});
};

// 分页切换
const handleTableChange: TableProps['onChange'] = (pagination, filters, sorter, { action }) => {
if (action === 'paginate') {
setPagination(pagination);
}
};

const columns: TableProps<EditorData>['columns'] = [
{
title: '编辑器名称',
dataIndex: 'name',
key: 'name',
width: '30%',
render: CommonTableCell(),
},
{
title: '状态',
dataIndex: 'status',
key: 'status',
width: '10%',
render: EditorStatusCell,
},
{
title: '资源',
dataIndex: 'computing_resource',
key: 'computing_resource',
width: '20%',
render: CommonTableCell(),
},
{
title: '创建者',
dataIndex: 'update_by',
key: 'update_by',
width: '20%',
render: CommonTableCell(),
},
{
title: '创建时间',
dataIndex: 'create_time',
key: 'create_time',
width: '20%',
render: DateTableCell,
},
{
title: '操作',
dataIndex: 'operation',
width: 300,
key: 'operation',
render: (_: any, record: EditorData) => (
<div>
{record.status === DevEditorStatus.Pending ||
record.status === DevEditorStatus.Running ? (
<Button
type="link"
size="small"
key="stop"
icon={<KFIcon type="icon-tingzhi" />}
onClick={() => stopEditor(record.id)}
>
停止
</Button>
) : (
<Button
type="link"
size="small"
key="debug"
icon={<KFIcon type="icon-tiaoshi" />}
onClick={() => startEditor(record.id)}
>
再次调试
</Button>
)}
<ConfigProvider
theme={{
token: {
colorLink: themes['warningColor'],
},
}}
>
<Button
type="link"
size="small"
key="remove"
icon={<KFIcon type="icon-shanchu" />}
onClick={() => handleEditorDelete(record)}
>
删除
</Button>
</ConfigProvider>
</div>
),
},
];

return (
<div className={styles['develop-env']}>
<div className={styles['develop-env__header']}>
<Button
style={{ marginLeft: '20px' }}
type="default"
onClick={createEditor}
icon={<KFIcon type="icon-xinjian2" />}
>
创建编辑器
</Button>
<Button
style={{ marginLeft: '20px' }}
type="default"
onClick={getEditorList}
icon={<KFIcon type="icon-shuaxin" />}
>
刷新
</Button>
</div>
<div className={classNames('vertical-scroll-table', styles['develop-env__table'])}>
<Table
dataSource={tableData}
columns={columns}
scroll={{ y: 'calc(100% - 55px)' }}
pagination={{
...pagination,
total: total,
showSizeChanger: true,
showQuickJumper: true,
}}
onChange={handleTableChange}
rowKey="id"
/>
</div>
</div>
);
}

export default EditorList;

+ 19
- 0
react-ui/src/pages/DevelopmentEnvironment/components/EditorStatusCell/index.less View File

@@ -0,0 +1,19 @@
.model-deployment-status-cell {
color: @text-color;

&--running {
color: @primary-color;
}

&--terminated {
color: @abort-color;
}

&--error {
color: @error-color;
}

&--pending {
color: @warning-color;
}
}

+ 44
- 0
react-ui/src/pages/DevelopmentEnvironment/components/EditorStatusCell/index.tsx View File

@@ -0,0 +1,44 @@
/*
* @Author: 赵伟
* @Date: 2024-04-18 18:35:41
* @Description: 编辑器状态组件
*/
import { DevEditorStatus } from '@/enums';
import styles from './index.less';

export type DevEditorStatusInfo = {
text: string;
classname: string;
};

export const statusInfo: Record<DevEditorStatus, DevEditorStatusInfo> = {
[DevEditorStatus.Unknown]: {
text: '未启动',
classname: styles['model-deployment-status-cell'],
},
[DevEditorStatus.Running]: {
classname: styles['model-deployment-status-cell--running'],
text: '运行中',
},
[DevEditorStatus.Terminated]: {
classname: styles['model-deployment-status-cell--terminated'],
text: '已停止',
},
[DevEditorStatus.Failed]: {
classname: styles['model-deployment-status-cell--error'],
text: '失败',
},
[DevEditorStatus.Pending]: {
classname: styles['model-deployment-status-cell--pending'],
text: '启动中',
},
};

function EditorStatusCell(status?: DevEditorStatus | null) {
if (status === null || status === undefined || !statusInfo[status]) {
return <span>--</span>;
}
return <span className={statusInfo[status].classname}>{statusInfo[status].text}</span>;
}

export default EditorStatusCell;

+ 0
- 18
react-ui/src/pages/Mirror/Info/index.less View File

@@ -31,23 +31,5 @@
display: flex; display: flex;
align-items: center; align-items: center;
} }

&__table {
:global {
.ant-table-wrapper {
height: 100%;
.ant-spin-nested-loading {
height: 100%;
}
.ant-spin-container {
height: 100%;
}
.ant-table {
height: calc(100% - 74px);
overflow: auto;
}
}
}
}
} }
} }

+ 1
- 2
react-ui/src/pages/Mirror/Info/index.tsx View File

@@ -32,7 +32,6 @@ import {
type TablePaginationConfig, type TablePaginationConfig,
type TableProps, type TableProps,
} from 'antd'; } from 'antd';
import classNames from 'classnames';
import { useEffect, useMemo, useState } from 'react'; import { useEffect, useMemo, useState } from 'react';
import MirrorStatusCell from '../components/MirrorStatusCell'; import MirrorStatusCell from '../components/MirrorStatusCell';
import styles from './index.less'; import styles from './index.less';
@@ -282,7 +281,7 @@ function MirrorInfo() {
</Flex> </Flex>
</div> </div>
<div <div
className={classNames('vertical-scroll-table', styles['mirror-info__content__table'])}
className="vertical-scroll-table"
style={{ marginTop: '24px', height: `calc(100% - ${topHeight + 24}px)` }} style={{ marginTop: '24px', height: `calc(100% - ${topHeight + 24}px)` }}
> >
<Table <Table


+ 22
- 14
react-ui/src/pages/ModelDeployment/Create/index.tsx View File

@@ -63,6 +63,9 @@ function ModelDeploymentCreate() {
const [modelDeploymentInfo, setModelDeploymentInfo] = useState<ModelDeploymentData | undefined>( const [modelDeploymentInfo, setModelDeploymentInfo] = useState<ModelDeploymentData | undefined>(
undefined, undefined,
); );
const [selectedMirror, setSelectedMirror] = useState<ResourceSelectorResponse | undefined>(
undefined,
); // 选择的镜像,为了再次打开时恢复原来的选择
const { message } = App.useApp(); const { message } = App.useApp();


useEffect(() => { useEffect(() => {
@@ -84,16 +87,14 @@ function ModelDeploymentCreate() {
}; };


// 选择模型、镜像 // 选择模型、镜像
const selectResource = (name: string, selectType: string) => {
let type;
const selectResource = (name: string, type: ResourceSelectorType) => {
let resource: ResourceSelectorResponse | undefined; let resource: ResourceSelectorResponse | undefined;
switch (selectType) {
case 'model':
type = ResourceSelectorType.Model;
switch (type) {
case ResourceSelectorType.Model:
resource = selectedModel; resource = selectedModel;
break; break;
default: default:
type = ResourceSelectorType.Mirror;
resource = selectedMirror;
break; break;
} }
const { close } = openAntdModal(ResourceSelectorModal, { const { close } = openAntdModal(ResourceSelectorModal, {
@@ -105,18 +106,20 @@ function ModelDeploymentCreate() {
if (res) { if (res) {
if (type === ResourceSelectorType.Mirror) { if (type === ResourceSelectorType.Mirror) {
form.setFieldValue(name, res.path); form.setFieldValue(name, res.path);
setSelectedMirror(res);
} else { } else {
const response = res as ResourceSelectorResponse;
const showValue = `${response.name}:${response.version}`;
const showValue = `${res.name}:${res.version}`;
form.setFieldValue(name, { form.setFieldValue(name, {
...pick(response, ['id', 'version', 'path']),
...pick(res, ['id', 'version', 'path']),
showValue, showValue,
}); });
setSelectedModel(response);
setSelectedModel(res);
} }
} else { } else {
if (type === ResourceSelectorType.Model) { if (type === ResourceSelectorType.Model) {
setSelectedModel(undefined); setSelectedModel(undefined);
} else {
setSelectedMirror(undefined);
} }
form.setFieldValue(name, ''); form.setFieldValue(name, '');
} }
@@ -248,7 +251,6 @@ function ModelDeploymentCreate() {
image={require('@/assets/img/model-deployment.png')} image={require('@/assets/img/model-deployment.png')}
style={{ marginTop: '20px', marginBottom: '24px' }} style={{ marginTop: '20px', marginBottom: '24px' }}
></SubAreaTitle> ></SubAreaTitle>

<Row gutter={8}> <Row gutter={8}>
<Col span={10}> <Col span={10}>
<Form.Item <Form.Item
@@ -266,6 +268,7 @@ function ModelDeploymentCreate() {
disabled={disabled} disabled={disabled}
canInput={false} canInput={false}
size="large" size="large"
onClick={() => selectResource('model', ResourceSelectorType.Model)}
/> />
</Form.Item> </Form.Item>
</Col> </Col>
@@ -275,7 +278,7 @@ function ModelDeploymentCreate() {
size="large" size="large"
type="link" type="link"
icon={getSelectBtnIcon(ResourceSelectorType.Model)} icon={getSelectBtnIcon(ResourceSelectorType.Model)}
onClick={() => selectResource('model', 'model')}
onClick={() => selectResource('model', ResourceSelectorType.Model)}
> >
选择模型 选择模型
</Button> </Button>
@@ -293,7 +296,12 @@ function ModelDeploymentCreate() {
}, },
]} ]}
> >
<ParameterInput placeholder="请选择镜像" canInput={false} size="large" />
<ParameterInput
placeholder="请选择镜像"
canInput={false}
size="large"
onClick={() => selectResource('image', ResourceSelectorType.Mirror)}
/>
</Form.Item> </Form.Item>
</Col> </Col>
<Col span={10}> <Col span={10}>
@@ -301,7 +309,7 @@ function ModelDeploymentCreate() {
size="large" size="large"
type="link" type="link"
icon={getSelectBtnIcon(ResourceSelectorType.Mirror)} icon={getSelectBtnIcon(ResourceSelectorType.Mirror)}
onClick={() => selectResource('image', 'image')}
onClick={() => selectResource('image', ResourceSelectorType.Mirror)}
> >
选择镜像 选择镜像
</Button> </Button>


+ 0
- 16
react-ui/src/services/developmentEnvironment/index.js View File

@@ -1,16 +0,0 @@
import { request } from '@umijs/max';
// 查询开发环境url
export function getJupyterUrl(params) {
return request(`/api/mmp/jupyter/getURL`, {
method: 'GET',
params,
});
}

// 查询 labelStudio url
export function getLabelStudioUrl(params) {
return request(`/api/mmp/labelStudio/getURL`, {
method: 'GET',
params,
});
}

+ 59
- 0
react-ui/src/services/developmentEnvironment/index.ts View File

@@ -0,0 +1,59 @@
import { request } from '@umijs/max';
// 查询开发环境url
export function getJupyterUrl(params: any) {
return request(`/api/mmp/jupyter/getURL`, {
method: 'GET',
params,
});
}

// 查询 labelStudio url
export function getLabelStudioUrl(params: any) {
return request(`/api/mmp/labelStudio/getURL`, {
method: 'GET',
params,
});
}

// 创建编辑器
export function createEditorReq(data: any) {
return request(`/api/mmp/devEnvironment`, {
method: 'POST',
data,
});
}

// 获取编辑器列表
export function getEditorListReq(params: any) {
return request(`/api/mmp/devEnvironment`, {
method: 'GET',
params,
});
}

// 获取编辑器详情
export function getEditorInfoReq(id: number) {
return request(`/api/mmp/devEnvironment/${id}`, {
method: 'GET',
});
}

// 创建编辑器
export function deleteEditorReq(id: number) {
return request(`/api/mmp/devEnvironment/${id}`, {
method: 'DELETE',
});
}

// 启动编辑器
export function startEditorReq(id: number) {
return request(`/api/mmp/jupyter/run/${id}`, {
method: 'POST',
});
}
// 停止编辑器
export function stopEditorReq(id: number) {
return request(`/api/mmp/jupyter/stop/${id}`, {
method: 'DELETE',
});
}

Loading…
Cancel
Save