Browse Source

Merge branch 'dev' of https://gitlink.org.cn/ci4s/ci4sManagement-cloud into dev

pull/121/head
fanshuai 1 year ago
parent
commit
25be4d3954
13 changed files with 205 additions and 58 deletions
  1. +1
    -1
      react-ui/src/components/MenuIconSelector/index.tsx
  2. +1
    -1
      react-ui/src/iconfont/iconfont-menu.js
  3. +42
    -42
      react-ui/src/iconfont/iconfont-menu.json
  4. +1
    -1
      react-ui/src/iconfont/iconfont.js
  5. +24
    -0
      react-ui/src/pages/DevelopmentEnvironment/List/index.tsx
  6. +100
    -0
      react-ui/src/pages/DevelopmentEnvironment/components/CreateMirrorModal/index.tsx
  7. +1
    -1
      react-ui/src/pages/Experiment/components/AddExperimentModal/index.tsx
  8. +4
    -4
      react-ui/src/pages/Experiment/index.jsx
  9. +8
    -0
      react-ui/src/pages/Mirror/Create/index.tsx
  10. +12
    -6
      react-ui/src/pages/User/Login/index.tsx
  11. +1
    -1
      react-ui/src/requestConfig.ts
  12. +9
    -0
      react-ui/src/services/developmentEnvironment/index.ts
  13. +1
    -1
      react-ui/src/utils/promise.ts

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

@@ -1,6 +1,6 @@
import KFIcon from '@/components/KFIcon'; import KFIcon from '@/components/KFIcon';
import KFModal from '@/components/KFModal'; import KFModal from '@/components/KFModal';
import iconData from '@/iconfont/iconfont.json';
import iconData from '@/iconfont/iconfont-menu.json';
import { type ModalProps } from 'antd'; import { type ModalProps } from 'antd';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import styles from './index.less'; import styles from './index.less';


+ 1
- 1
react-ui/src/iconfont/iconfont-menu.js
File diff suppressed because it is too large
View File


react-ui/src/iconfont/iconfont.json → react-ui/src/iconfont/iconfont-menu.json View File

@@ -5,6 +5,48 @@
"css_prefix_text": "icon-", "css_prefix_text": "icon-",
"description": "", "description": "",
"glyphs": [ "glyphs": [
{
"icon_id": "41643218",
"name": "模型开发",
"font_class": "model-icon",
"unicode": "e624",
"unicode_decimal": 58916
},
{
"icon_id": "41643132",
"name": "工作空间",
"font_class": "workspace-icon",
"unicode": "e628",
"unicode_decimal": 58920
},
{
"icon_id": "41643135",
"name": "系统管理",
"font_class": "system-icon",
"unicode": "e622",
"unicode_decimal": 58914
},
{
"icon_id": "41643131",
"name": "数据准备",
"font_class": "datasetPreparation-icon",
"unicode": "e625",
"unicode_decimal": 58917
},
{
"icon_id": "41643133",
"name": "开发环境",
"font_class": "developmentEnvironment-icon",
"unicode": "e626",
"unicode_decimal": 58918
},
{
"icon_id": "41642989",
"name": "使用手册",
"font_class": "manual-icon",
"unicode": "e623",
"unicode_decimal": 58915
},
{ {
"icon_id": "40233218", "icon_id": "40233218",
"name": "操作手册-active", "name": "操作手册-active",
@@ -12,13 +54,6 @@
"unicode": "e62c", "unicode": "e62c",
"unicode_decimal": 58924 "unicode_decimal": 58924
}, },
{
"icon_id": "40233217",
"name": "操作手册",
"font_class": "manual-icon",
"unicode": "e62d",
"unicode_decimal": 58925
},
{ {
"icon_id": "40171713", "icon_id": "40171713",
"name": "监控运维-active", "name": "监控运维-active",
@@ -40,20 +75,6 @@
"unicode": "e62a", "unicode": "e62a",
"unicode_decimal": 58922 "unicode_decimal": 58922
}, },
{
"icon_id": "40171699",
"name": "开发环境",
"font_class": "developmentEnvironment-icon",
"unicode": "e62b",
"unicode_decimal": 58923
},
{
"icon_id": "39969575",
"name": "系统管理",
"font_class": "system-icon",
"unicode": "e618",
"unicode_decimal": 58904
},
{ {
"icon_id": "39969573", "icon_id": "39969573",
"name": "流水线-active", "name": "流水线-active",
@@ -68,13 +89,6 @@
"unicode": "e61c", "unicode": "e61c",
"unicode_decimal": 58908 "unicode_decimal": 58908
}, },
{
"icon_id": "39969568",
"name": "数据准备",
"font_class": "datasetPreparation-icon",
"unicode": "e61d",
"unicode_decimal": 58909
},
{ {
"icon_id": "39969570", "icon_id": "39969570",
"name": "模型在线部署", "name": "模型在线部署",
@@ -103,13 +117,6 @@
"unicode": "e621", "unicode": "e621",
"unicode_decimal": 58913 "unicode_decimal": 58913
}, },
{
"icon_id": "39969580",
"name": "工作空间",
"font_class": "workspace-icon",
"unicode": "e611",
"unicode_decimal": 58897
},
{ {
"icon_id": "39969572", "icon_id": "39969572",
"name": "模型开发-active", "name": "模型开发-active",
@@ -131,13 +138,6 @@
"unicode": "e613", "unicode": "e613",
"unicode_decimal": 58899 "unicode_decimal": 58899
}, },
{
"icon_id": "39969565",
"name": "模型开发",
"font_class": "model-icon",
"unicode": "e614",
"unicode_decimal": 58900
},
{ {
"icon_id": "39969577", "icon_id": "39969577",
"name": "应用开发", "name": "应用开发",

+ 1
- 1
react-ui/src/iconfont/iconfont.js
File diff suppressed because it is too large
View File


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

@@ -3,6 +3,7 @@
* @Date: 2024-04-16 13:58:08 * @Date: 2024-04-16 13:58:08
* @Description: 开发环境列表 * @Description: 开发环境列表
*/ */

import CommonTableCell from '@/components/CommonTableCell'; import CommonTableCell from '@/components/CommonTableCell';
import DateTableCell from '@/components/DateTableCell'; import DateTableCell from '@/components/DateTableCell';
import KFIcon from '@/components/KFIcon'; import KFIcon from '@/components/KFIcon';
@@ -15,6 +16,7 @@ import {
stopEditorReq, stopEditorReq,
} from '@/services/developmentEnvironment'; } from '@/services/developmentEnvironment';
import themes from '@/styles/theme.less'; import themes from '@/styles/theme.less';
import { openAntdModal } from '@/utils/modal';
import { to } from '@/utils/promise'; import { to } from '@/utils/promise';
import { editorUrlKey, setSessionStorageItem } from '@/utils/sessionStorage'; import { editorUrlKey, setSessionStorageItem } from '@/utils/sessionStorage';
import { modalConfirm } from '@/utils/ui'; import { modalConfirm } from '@/utils/ui';
@@ -29,6 +31,7 @@ import {
} from 'antd'; } from 'antd';
import classNames from 'classnames'; import classNames from 'classnames';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import CreateMirrorModal from '../components/CreateMirrorModal';
import EditorStatusCell from '../components/EditorStatusCell'; import EditorStatusCell from '../components/EditorStatusCell';
import styles from './index.less'; 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) => { const handleEditorDelete = (record: EditorData) => {
modalConfirm({ modalConfirm({
@@ -218,6 +231,17 @@ function EditorList() {
启动 启动
</Button> </Button>
)} )}
{record.status === DevEditorStatus.Running ? (
<Button
type="link"
size="small"
key="jingxiang"
icon={<KFIcon type="icon-jingxiang" />}
onClick={() => createMirror(record.id)}
>
制作镜像
</Button>
) : null}
<ConfigProvider <ConfigProvider
theme={{ theme={{
token: { token: {


+ 100
- 0
react-ui/src/pages/DevelopmentEnvironment/components/CreateMirrorModal/index.tsx View File

@@ -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;

+ 1
- 1
react-ui/src/pages/Experiment/components/AddExperimentModal/index.tsx View File

@@ -51,7 +51,7 @@ export const getParamRules = (paramType: number, required: boolean = false): For
// 防止后台返回不是 number 类型 // 防止后台返回不是 number 类型
if (Number(paramType) === 2) { if (Number(paramType) === 2) {
rules.push({ rules.push({
pattern: /^-?\d+(\.\d+)?$/,
pattern: /^-?((0(\.0*[1-9]\d*)?)|([1-9]\d*(\.\d+)?))$/,
message: '整型必须是数字', message: '整型必须是数字',
}); });
} }


+ 4
- 4
react-ui/src/pages/Experiment/index.jsx View File

@@ -74,7 +74,7 @@ function Experiment() {
page: pageOption.current.page - 1, page: pageOption.current.page - 1,
size: pageOption.current.size, size: pageOption.current.size,
}; };
const [res, _] = await to(getExperiment(params));
const [res] = await to(getExperiment(params));
if (res && res.data && Array.isArray(res.data.content)) { if (res && res.data && Array.isArray(res.data.content)) {
setExperimentList( setExperimentList(
res.data.content.map((item) => { res.data.content.map((item) => {
@@ -88,7 +88,7 @@ function Experiment() {


// 获取流水线列表 // 获取流水线列表
const getWorkflowList = async () => { const getWorkflowList = async () => {
const [res, _] = await to(getWorkflow(queryFlow));
const [res] = await to(getWorkflow(queryFlow));
if (res && res.data && res.data.content) { if (res && res.data && res.data.content) {
setWorkflowList(res.data.content); setWorkflowList(res.data.content);
} }
@@ -236,7 +236,7 @@ function Experiment() {
...values, ...values,
global_param, global_param,
}; };
const [res, _] = await to(postExperiment(params));
const [res] = await to(postExperiment(params));
if (res) { if (res) {
message.success('新建实验成功'); message.success('新建实验成功');
setIsModalOpen(false); setIsModalOpen(false);
@@ -244,7 +244,7 @@ function Experiment() {
} }
} else { } else {
const params = { ...values, global_param, id: experimentId }; const params = { ...values, global_param, id: experimentId };
const [res, _] = await to(putExperiment(params));
const [res] = await to(putExperiment(params));
if (res) { if (res) {
message.success('编辑实验成功'); message.success('编辑实验成功');
setIsModalOpen(false); setIsModalOpen(false);


+ 8
- 0
react-ui/src/pages/Mirror/Create/index.tsx View File

@@ -153,6 +153,10 @@ function MirrorCreate() {
required: true, required: true,
message: '请输入镜像名称', message: '请输入镜像名称',
}, },
{
pattern: /^[a-zA-Z0-9_-]*$/,
message: '只支持字母、数字、下划线、中横线',
},
]} ]}
> >
<Input <Input
@@ -176,6 +180,10 @@ function MirrorCreate() {
required: true, required: true,
message: '请输入镜像Tag', message: '请输入镜像Tag',
}, },
{
pattern: /^[a-zA-Z0-9_-]*$/,
message: '只支持字母、数字、下划线、中横线',
},
]} ]}
> >
<Input placeholder="请输入镜像Tag" maxLength={64} showCount allowClear /> <Input placeholder="请输入镜像Tag" maxLength={64} showCount allowClear />


+ 12
- 6
react-ui/src/pages/User/Login/index.tsx View File

@@ -3,8 +3,8 @@ import { getCaptchaImg, login } from '@/services/system/auth';
import { loginPasswordKey, loginUserKey, rememberPasswordKey } from '@/utils/localStorage'; import { loginPasswordKey, loginUserKey, rememberPasswordKey } from '@/utils/localStorage';
import { to } from '@/utils/promise'; import { to } from '@/utils/promise';
import { history, useModel } from '@umijs/max'; import { history, useModel } from '@umijs/max';
import { Button, Checkbox, Flex, Form, Image, Input, message } from 'antd';
import React, { useEffect, useState } from 'react';
import { Button, Checkbox, Flex, Form, Image, Input, message, type InputRef } from 'antd';
import { useEffect, useRef, useState } from 'react';
import { flushSync } from 'react-dom'; import { flushSync } from 'react-dom';
import styles from './login.less'; import styles from './login.less';


@@ -17,12 +17,13 @@ const LoginInputPrefix = ({ icon }: { icon: string }) => {
); );
}; };


const Login: React.FC = () => {
const Login = () => {
const { initialState, setInitialState } = useModel('@@initialState'); const { initialState, setInitialState } = useModel('@@initialState');
const [captchaCode, setCaptchaCode] = useState<string>(''); const [captchaCode, setCaptchaCode] = useState<string>('');
const [uuid, setUuid] = useState<string>(''); const [uuid, setUuid] = useState<string>('');
const [form] = Form.useForm(); const [form] = Form.useForm();
const [usernameReadOnly, setUsernameReadOnly] = useState<boolean>(true); const [usernameReadOnly, setUsernameReadOnly] = useState<boolean>(true);
const captchaInputRef = useRef<InputRef>(null);


useEffect(() => { useEffect(() => {
getCaptchaCode(); getCaptchaCode();
@@ -59,11 +60,11 @@ const Login: React.FC = () => {


// 登录 // 登录
const handleSubmit = async (values: API.LoginParams) => { const handleSubmit = async (values: API.LoginParams) => {
const [response] = await to(login({ ...values, uuid }));
if (response && response.data) {
const [res, error] = await to(login({ ...values, uuid }));
if (res && res.data) {
const current = new Date(); const current = new Date();
const expireTime = current.setTime(current.getTime() + 1000 * 12 * 60 * 60); const expireTime = current.setTime(current.getTime() + 1000 * 12 * 60 * 60);
const { access_token } = response.data;
const { access_token } = res.data;
setSessionToken(access_token, access_token, expireTime); setSessionToken(access_token, access_token, expireTime);
message.success('登录成功!'); message.success('登录成功!');


@@ -80,6 +81,10 @@ const Login: React.FC = () => {
const urlParams = new URL(window.location.href).searchParams; const urlParams = new URL(window.location.href).searchParams;
history.push(urlParams.get('redirect') || '/'); history.push(urlParams.get('redirect') || '/');
} else { } else {
if (error?.data?.code === 500 && error?.data?.msg === '验证码错误') {
captchaInputRef.current?.focus();
}

clearSessionToken(); clearSessionToken();
getCaptchaCode(); getCaptchaCode();
} }
@@ -156,6 +161,7 @@ const Login: React.FC = () => {
prefix={ prefix={
<LoginInputPrefix icon={require('@/assets/img/login-captcha.png')} /> <LoginInputPrefix icon={require('@/assets/img/login-captcha.png')} />
} }
ref={captchaInputRef}
allowClear allowClear
/> />
</Form.Item> </Form.Item>


+ 1
- 1
react-ui/src/requestConfig.ts View File

@@ -10,7 +10,7 @@ import { setRemoteMenu } from './services/session';
import { gotoLoginPage } from './utils/ui'; import { gotoLoginPage } from './utils/ui';


// [antd: Notification] You are calling notice in render which will break in React 18 concurrent mode. Please trigger in effect instead. // [antd: Notification] You are calling notice in render which will break in React 18 concurrent mode. Please trigger in effect instead.
const popupError = (error: string, skipErrorHandler?: boolean = false) => {
const popupError = (error: string, skipErrorHandler: boolean | undefined = false) => {
if (skipErrorHandler) { if (skipErrorHandler) {
return; return;
} }


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

@@ -49,9 +49,18 @@ export function startEditorReq(id: number) {
method: 'POST', method: 'POST',
}); });
} }

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

// 制作镜像
export function createEditorMirrorReq(data: any) {
return request(`/api/mmp/image/saveImage`, {
method: 'POST',
data,
});
}

+ 1
- 1
react-ui/src/utils/promise.ts View File

@@ -2,7 +2,7 @@
* @param { Promise } promise * @param { Promise } promise
* @return { Promise } * @return { Promise }
*/ */
export async function to<T, U = Error>(promise: Promise<T>): Promise<[T, null] | [null, U]> {
export async function to<T, U = any>(promise: Promise<T>): Promise<[T, null] | [null, U]> {
try { try {
const data = await promise; const data = await promise;
return [data, null]; return [data, null];


Loading…
Cancel
Save