Merge pull request '合并dev' (#119) from dev-zw into dev
This commit is contained in:
commit
c9e8e908d0
|
@ -1,6 +1,6 @@
|
|||
import KFIcon from '@/components/KFIcon';
|
||||
import KFModal from '@/components/KFModal';
|
||||
import iconData from '@/iconfont/iconfont.json';
|
||||
import iconData from '@/iconfont/iconfont-menu.json';
|
||||
import { type ModalProps } from 'antd';
|
||||
import { useEffect, useState } from 'react';
|
||||
import styles from './index.less';
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -5,6 +5,48 @@
|
|||
"css_prefix_text": "icon-",
|
||||
"description": "",
|
||||
"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",
|
||||
"name": "操作手册-active",
|
||||
|
@ -12,13 +54,6 @@
|
|||
"unicode": "e62c",
|
||||
"unicode_decimal": 58924
|
||||
},
|
||||
{
|
||||
"icon_id": "40233217",
|
||||
"name": "操作手册",
|
||||
"font_class": "manual-icon",
|
||||
"unicode": "e62d",
|
||||
"unicode_decimal": 58925
|
||||
},
|
||||
{
|
||||
"icon_id": "40171713",
|
||||
"name": "监控运维-active",
|
||||
|
@ -40,20 +75,6 @@
|
|||
"unicode": "e62a",
|
||||
"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",
|
||||
"name": "流水线-active",
|
||||
|
@ -68,13 +89,6 @@
|
|||
"unicode": "e61c",
|
||||
"unicode_decimal": 58908
|
||||
},
|
||||
{
|
||||
"icon_id": "39969568",
|
||||
"name": "数据准备",
|
||||
"font_class": "datasetPreparation-icon",
|
||||
"unicode": "e61d",
|
||||
"unicode_decimal": 58909
|
||||
},
|
||||
{
|
||||
"icon_id": "39969570",
|
||||
"name": "模型在线部署",
|
||||
|
@ -103,13 +117,6 @@
|
|||
"unicode": "e621",
|
||||
"unicode_decimal": 58913
|
||||
},
|
||||
{
|
||||
"icon_id": "39969580",
|
||||
"name": "工作空间",
|
||||
"font_class": "workspace-icon",
|
||||
"unicode": "e611",
|
||||
"unicode_decimal": 58897
|
||||
},
|
||||
{
|
||||
"icon_id": "39969572",
|
||||
"name": "模型开发-active",
|
||||
|
@ -131,13 +138,6 @@
|
|||
"unicode": "e613",
|
||||
"unicode_decimal": 58899
|
||||
},
|
||||
{
|
||||
"icon_id": "39969565",
|
||||
"name": "模型开发",
|
||||
"font_class": "model-icon",
|
||||
"unicode": "e614",
|
||||
"unicode_decimal": 58900
|
||||
},
|
||||
{
|
||||
"icon_id": "39969577",
|
||||
"name": "应用开发",
|
File diff suppressed because one or more lines are too long
|
@ -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: '整型必须是数字',
|
||||
});
|
||||
}
|
||||
|
|
|
@ -74,7 +74,7 @@ function Experiment() {
|
|||
page: pageOption.current.page - 1,
|
||||
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)) {
|
||||
setExperimentList(
|
||||
res.data.content.map((item) => {
|
||||
|
@ -88,7 +88,7 @@ function Experiment() {
|
|||
|
||||
// 获取流水线列表
|
||||
const getWorkflowList = async () => {
|
||||
const [res, _] = await to(getWorkflow(queryFlow));
|
||||
const [res] = await to(getWorkflow(queryFlow));
|
||||
if (res && res.data && res.data.content) {
|
||||
setWorkflowList(res.data.content);
|
||||
}
|
||||
|
@ -236,7 +236,7 @@ function Experiment() {
|
|||
...values,
|
||||
global_param,
|
||||
};
|
||||
const [res, _] = await to(postExperiment(params));
|
||||
const [res] = await to(postExperiment(params));
|
||||
if (res) {
|
||||
message.success('新建实验成功');
|
||||
setIsModalOpen(false);
|
||||
|
@ -244,7 +244,7 @@ function Experiment() {
|
|||
}
|
||||
} else {
|
||||
const params = { ...values, global_param, id: experimentId };
|
||||
const [res, _] = await to(putExperiment(params));
|
||||
const [res] = await to(putExperiment(params));
|
||||
if (res) {
|
||||
message.success('编辑实验成功');
|
||||
setIsModalOpen(false);
|
||||
|
|
|
@ -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 />
|
||||
|
|
|
@ -3,8 +3,8 @@ import { getCaptchaImg, login } from '@/services/system/auth';
|
|||
import { loginPasswordKey, loginUserKey, rememberPasswordKey } from '@/utils/localStorage';
|
||||
import { to } from '@/utils/promise';
|
||||
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 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 [captchaCode, setCaptchaCode] = useState<string>('');
|
||||
const [uuid, setUuid] = useState<string>('');
|
||||
const [form] = Form.useForm();
|
||||
const [usernameReadOnly, setUsernameReadOnly] = useState<boolean>(true);
|
||||
const captchaInputRef = useRef<InputRef>(null);
|
||||
|
||||
useEffect(() => {
|
||||
getCaptchaCode();
|
||||
|
@ -59,11 +60,11 @@ const Login: React.FC = () => {
|
|||
|
||||
// 登录
|
||||
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 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);
|
||||
message.success('登录成功!');
|
||||
|
||||
|
@ -80,6 +81,10 @@ const Login: React.FC = () => {
|
|||
const urlParams = new URL(window.location.href).searchParams;
|
||||
history.push(urlParams.get('redirect') || '/');
|
||||
} else {
|
||||
if (error?.data?.code === 500 && error?.data?.msg === '验证码错误') {
|
||||
captchaInputRef.current?.focus();
|
||||
}
|
||||
|
||||
clearSessionToken();
|
||||
getCaptchaCode();
|
||||
}
|
||||
|
@ -156,6 +161,7 @@ const Login: React.FC = () => {
|
|||
prefix={
|
||||
<LoginInputPrefix icon={require('@/assets/img/login-captcha.png')} />
|
||||
}
|
||||
ref={captchaInputRef}
|
||||
allowClear
|
||||
/>
|
||||
</Form.Item>
|
||||
|
|
|
@ -10,7 +10,7 @@ import { setRemoteMenu } from './services/session';
|
|||
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.
|
||||
const popupError = (error: string, skipErrorHandler?: boolean = false) => {
|
||||
const popupError = (error: string, skipErrorHandler: boolean | undefined = false) => {
|
||||
if (skipErrorHandler) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* @param { Promise } 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 {
|
||||
const data = await promise;
|
||||
return [data, null];
|
||||
|
|
Loading…
Reference in New Issue