Merge remote-tracking branch 'origin/dev' into dev
Before Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 1.4 KiB |
|
@ -29,6 +29,8 @@ export async function getInitialState(): Promise<{
|
||||||
loading?: boolean;
|
loading?: boolean;
|
||||||
fetchUserInfo?: () => Promise<API.CurrentUser | undefined>;
|
fetchUserInfo?: () => Promise<API.CurrentUser | undefined>;
|
||||||
}> {
|
}> {
|
||||||
|
console.log('getInitialState');
|
||||||
|
|
||||||
const fetchUserInfo = async () => {
|
const fetchUserInfo = async () => {
|
||||||
try {
|
try {
|
||||||
const response = await getUserInfo({
|
const response = await getUserInfo({
|
||||||
|
@ -133,22 +135,7 @@ export const layout: RunTimeLayoutConfig = ({ initialState }) => {
|
||||||
// 增加一个 loading 的状态
|
// 增加一个 loading 的状态
|
||||||
childrenRender: (children) => {
|
childrenRender: (children) => {
|
||||||
// if (initialState?.loading) return <PageLoading />;
|
// if (initialState?.loading) return <PageLoading />;
|
||||||
return (
|
return <>{children}</>;
|
||||||
<>
|
|
||||||
{children}
|
|
||||||
{/* <SettingDrawer
|
|
||||||
disableUrlParams
|
|
||||||
enableDarkTheme
|
|
||||||
settings={initialState?.settings}
|
|
||||||
onSettingChange={(settings) => {
|
|
||||||
setInitialState((preInitialState) => ({
|
|
||||||
...preInitialState,
|
|
||||||
settings,
|
|
||||||
}));
|
|
||||||
}}
|
|
||||||
/> */}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
...initialState?.settings,
|
...initialState?.settings,
|
||||||
};
|
};
|
||||||
|
|
After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 13 KiB |
|
@ -17,13 +17,8 @@ const HeaderDropdown: React.FC<HeaderDropdownProps> = ({ overlayClassName: cls,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
return (
|
|
||||||
<Dropdown
|
return <Dropdown overlayClassName={classNames(className, cls)} {...restProps} />;
|
||||||
overlayClassName={classNames(className, cls)}
|
|
||||||
getPopupContainer={(target) => target.parentElement || document.body}
|
|
||||||
{...restProps}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default HeaderDropdown;
|
export default HeaderDropdown;
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
import { clearSessionToken } from '@/access';
|
import { clearSessionToken } from '@/access';
|
||||||
import { PageEnum } from '@/enums/pagesEnums';
|
|
||||||
import { setRemoteMenu } from '@/services/session';
|
import { setRemoteMenu } from '@/services/session';
|
||||||
import { logout } from '@/services/system/auth';
|
import { logout } from '@/services/system/auth';
|
||||||
|
import { gotoLoginPage } from '@/utils/ui';
|
||||||
import { LogoutOutlined, SettingOutlined, UserOutlined } from '@ant-design/icons';
|
import { LogoutOutlined, SettingOutlined, UserOutlined } from '@ant-design/icons';
|
||||||
import { setAlpha } from '@ant-design/pro-components';
|
import { setAlpha } from '@ant-design/pro-components';
|
||||||
import { useEmotionCss } from '@ant-design/use-emotion-css';
|
import { useEmotionCss } from '@ant-design/use-emotion-css';
|
||||||
import { history, useModel } from '@umijs/max';
|
import { history, useModel } from '@umijs/max';
|
||||||
import { Avatar, Spin } from 'antd';
|
import { Avatar, Spin } from 'antd';
|
||||||
import { stringify } from 'querystring';
|
|
||||||
import type { MenuInfo } from 'rc-menu/lib/interface';
|
import type { MenuInfo } from 'rc-menu/lib/interface';
|
||||||
import React, { useCallback } from 'react';
|
import React, { useCallback } from 'react';
|
||||||
import { flushSync } from 'react-dom';
|
import { flushSync } from 'react-dom';
|
||||||
|
@ -23,7 +22,7 @@ const Name = () => {
|
||||||
|
|
||||||
const nameClassName = useEmotionCss(({ token }) => {
|
const nameClassName = useEmotionCss(({ token }) => {
|
||||||
return {
|
return {
|
||||||
width: '70px',
|
// width: '70px',
|
||||||
height: '48px',
|
height: '48px',
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
lineHeight: '48px',
|
lineHeight: '48px',
|
||||||
|
@ -64,19 +63,7 @@ const AvatarDropdown: React.FC<GlobalHeaderRightProps> = ({ menu }) => {
|
||||||
await logout();
|
await logout();
|
||||||
clearSessionToken();
|
clearSessionToken();
|
||||||
setRemoteMenu(null);
|
setRemoteMenu(null);
|
||||||
const { search, pathname } = window.location;
|
gotoLoginPage();
|
||||||
const urlParams = new URL(window.location.href).searchParams;
|
|
||||||
/** 此方法会跳转到 redirect 参数所在的位置 */
|
|
||||||
const redirect = urlParams.get('redirect');
|
|
||||||
// Note: There may be security issues, please note
|
|
||||||
if (window.location.pathname !== PageEnum.LOGIN && !redirect) {
|
|
||||||
history.replace({
|
|
||||||
pathname: PageEnum.LOGIN,
|
|
||||||
search: stringify({
|
|
||||||
redirect: pathname + search,
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
const actionClassName = useEmotionCss(({ token }) => {
|
const actionClassName = useEmotionCss(({ token }) => {
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import { QuestionCircleOutlined } from '@ant-design/icons';
|
|
||||||
import { useEmotionCss } from '@ant-design/use-emotion-css';
|
import { useEmotionCss } from '@ant-design/use-emotion-css';
|
||||||
import { SelectLang, useModel } from '@umijs/max';
|
import { useModel } from '@umijs/max';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Avatar from './AvatarDropdown';
|
import Avatar from './AvatarDropdown';
|
||||||
|
|
||||||
|
@ -17,21 +16,21 @@ const GlobalHeaderRight: React.FC = () => {
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
const actionClassName = useEmotionCss(({ token }) => {
|
// const actionClassName = useEmotionCss(({ token }) => {
|
||||||
return {
|
// return {
|
||||||
display: 'flex',
|
// display: 'flex',
|
||||||
float: 'right',
|
// float: 'right',
|
||||||
height: '48px',
|
// height: '48px',
|
||||||
marginLeft: 'auto',
|
// marginLeft: 'auto',
|
||||||
overflow: 'hidden',
|
// overflow: 'hidden',
|
||||||
cursor: 'pointer',
|
// cursor: 'pointer',
|
||||||
padding: '0 12px',
|
// padding: '0 12px',
|
||||||
borderRadius: token.borderRadius,
|
// borderRadius: token.borderRadius,
|
||||||
'&:hover': {
|
// '&:hover': {
|
||||||
backgroundColor: token.colorBgTextHover,
|
// backgroundColor: token.colorBgTextHover,
|
||||||
},
|
// },
|
||||||
};
|
// };
|
||||||
});
|
// });
|
||||||
|
|
||||||
const { initialState } = useModel('@@initialState');
|
const { initialState } = useModel('@@initialState');
|
||||||
|
|
||||||
|
@ -41,15 +40,15 @@ const GlobalHeaderRight: React.FC = () => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={className}>
|
<div className={className}>
|
||||||
<span
|
{/* <span
|
||||||
className={actionClassName}
|
className={actionClassName}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
window.open('https://pro.ant.design/docs/getting-started');
|
window.open('https://pro.ant.design/docs/getting-started');
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<QuestionCircleOutlined />
|
<QuestionCircleOutlined />
|
||||||
</span>
|
</span> */}
|
||||||
<Avatar menu={true} />
|
<Avatar menu={false} />
|
||||||
{/* <SelectLang className={actionClassName} /> */}
|
{/* <SelectLang className={actionClassName} /> */}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
|
/*
|
||||||
|
* @Author: 赵伟
|
||||||
|
* @Date: 2024-04-28 08:47:43
|
||||||
|
* @Description: 覆盖 antd 样式
|
||||||
|
*/
|
||||||
|
|
||||||
// 设置 Table 可以滑动
|
// 设置 Table 可以滑动
|
||||||
.vertical-scroll-table {
|
.vertical-scroll-table {
|
||||||
.ant-table-wrapper {
|
.ant-table-wrapper {
|
||||||
|
@ -9,7 +15,7 @@
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
.ant-table {
|
.ant-table {
|
||||||
height: calc(100% - 74px);
|
height: calc(100% - 74px); // 分页控件的高度
|
||||||
|
|
||||||
.ant-table-container {
|
.ant-table-container {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
|
@ -224,8 +224,8 @@ const Dataset = () => {
|
||||||
<span style={{ color: '#1d1d20', fontSize: '20px' }}>{datasetDetailObj.name}</span>
|
<span style={{ color: '#1d1d20', fontSize: '20px' }}>{datasetDetailObj.name}</span>
|
||||||
<div className={Styles.smallTagBox}>
|
<div className={Styles.smallTagBox}>
|
||||||
<div className={Styles.tagItem}>数据集 id:{datasetDetailObj.id}</div>
|
<div className={Styles.tagItem}>数据集 id:{datasetDetailObj.id}</div>
|
||||||
<div className={Styles.tagItem}>{datasetDetailObj.data_tag || '...'}</div>
|
<div className={Styles.tagItem}>{datasetDetailObj.dataset_type_name || '...'}</div>
|
||||||
<div className={Styles.tagItem}>{datasetDetailObj.data_type}</div>
|
<div className={Styles.tagItem}>{datasetDetailObj.dataset_tag_name || '...'}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={Styles.datasetIntroCneterBox}>
|
<div className={Styles.datasetIntroCneterBox}>
|
||||||
|
|
|
@ -229,6 +229,11 @@
|
||||||
border-color: #eaeaea;
|
border-color: #eaeaea;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
.dropdown{
|
||||||
|
position: absolute;
|
||||||
|
right: 20px;
|
||||||
|
top: 15px;
|
||||||
|
}
|
||||||
.itemText {
|
.itemText {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 20px;
|
top: 20px;
|
||||||
|
|
|
@ -1,14 +1,22 @@
|
||||||
import { getAccessToken } from '@/access';
|
import { getAccessToken } from '@/access';
|
||||||
import clock from '@/assets/img/clock.png';
|
import clock from '@/assets/img/clock.png';
|
||||||
import creatByImg from '@/assets/img/creatBy.png';
|
import creatByImg from '@/assets/img/creatBy.png';
|
||||||
|
import deleteIcon from '@/assets/img/delete-icon.png';
|
||||||
import KFIcon from '@/components/KFIcon';
|
import KFIcon from '@/components/KFIcon';
|
||||||
import { addDatesetAndVesion, getAssetIcon, getDatasetList } from '@/services/dataset/index.js';
|
import {
|
||||||
|
addDatesetAndVesion,
|
||||||
|
deleteDataset,
|
||||||
|
getAssetIcon,
|
||||||
|
getDatasetList,
|
||||||
|
} from '@/services/dataset/index.js';
|
||||||
import { getDictSelectOption } from '@/services/system/dict';
|
import { getDictSelectOption } from '@/services/system/dict';
|
||||||
|
import { modalConfirm } from '@/utils/ui';
|
||||||
import { UploadOutlined } from '@ant-design/icons';
|
import { UploadOutlined } from '@ant-design/icons';
|
||||||
import { Button, Form, Input, Modal, Pagination, Radio, Select, Upload } from 'antd';
|
import { Button, Form, Input, Modal, Pagination, Radio, Select, Upload } from 'antd';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
import './index.less';
|
import './index.less';
|
||||||
import Styles from './index.less';
|
import Styles from './index.less';
|
||||||
const { Search } = Input;
|
const { Search } = Input;
|
||||||
|
@ -277,7 +285,30 @@ const PublicData = (React.FC = () => {
|
||||||
return (
|
return (
|
||||||
<div className={Styles.dataItem} onClick={(e) => routeToIntro(e, item)}>
|
<div className={Styles.dataItem} onClick={(e) => routeToIntro(e, item)}>
|
||||||
<span className={Styles.itemText}>{item.name}</span>
|
<span className={Styles.itemText}>{item.name}</span>
|
||||||
|
<img
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
modalConfirm({
|
||||||
|
title: '确定删除该条数据集实例吗?',
|
||||||
|
onOk: () => {
|
||||||
|
deleteDataset(item.id).then((ret) => {
|
||||||
|
if (ret.code === 200) {
|
||||||
|
message.success('删除成功');
|
||||||
|
getModelLists(queryFlow);
|
||||||
|
} else {
|
||||||
|
message.error(ret.msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
className={Styles.dropdown}
|
||||||
|
style={{ width: '17px', marginRight: '6px' }}
|
||||||
|
src={deleteIcon}
|
||||||
|
alt=""
|
||||||
|
/>
|
||||||
<div className={Styles.itemDescripition}>{item.description}</div>
|
<div className={Styles.itemDescripition}>{item.description}</div>
|
||||||
|
|
||||||
<div className={Styles.itemTime}>
|
<div className={Styles.itemTime}>
|
||||||
<img
|
<img
|
||||||
style={{ width: '17px', marginRight: '6px' }}
|
style={{ width: '17px', marginRight: '6px' }}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import clock from '@/assets/img/clock.png';
|
import clock from '@/assets/img/clock.png';
|
||||||
import creatByImg from '@/assets/img/creatBy.png';
|
import creatByImg from '@/assets/img/creatBy.png';
|
||||||
import { getAssetIcon, getDatasetList } from '@/services/dataset/index.js';
|
import deleteIcon from '@/assets/img/delete-icon.png';
|
||||||
|
import { deleteDataset, getAssetIcon, getDatasetList } from '@/services/dataset/index.js';
|
||||||
|
import { modalConfirm } from '@/utils/ui';
|
||||||
import { Form, Input, Pagination } from 'antd';
|
import { Form, Input, Pagination } from 'antd';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
|
@ -225,6 +227,28 @@ const PublicData = () => {
|
||||||
return (
|
return (
|
||||||
<div className={Styles.dataItem} onClick={(e) => routeToIntro(e, item)}>
|
<div className={Styles.dataItem} onClick={(e) => routeToIntro(e, item)}>
|
||||||
<span className={Styles.itemText}>{item.name}</span>
|
<span className={Styles.itemText}>{item.name}</span>
|
||||||
|
<img
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
modalConfirm({
|
||||||
|
title: '确定删除该条数据集实例吗?',
|
||||||
|
onOk: () => {
|
||||||
|
deleteDataset(item.id).then((ret) => {
|
||||||
|
if (ret.code === 200) {
|
||||||
|
message.success('删除成功');
|
||||||
|
getModelLists(queryFlow);
|
||||||
|
} else {
|
||||||
|
message.error(ret.msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
className={Styles.dropdown}
|
||||||
|
style={{ width: '17px', marginRight: '6px' }}
|
||||||
|
src={deleteIcon}
|
||||||
|
alt=""
|
||||||
|
/>
|
||||||
<div className={Styles.itemDescripition}>{item.description}</div>
|
<div className={Styles.itemDescripition}>{item.description}</div>
|
||||||
<div className={Styles.itemTime}>
|
<div className={Styles.itemTime}>
|
||||||
<img
|
<img
|
||||||
|
|
|
@ -144,8 +144,15 @@ function AddExperimentModal({
|
||||||
label="实验描述"
|
label="实验描述"
|
||||||
name="description"
|
name="description"
|
||||||
rules={[{ required: true, message: '请输入实验描述' }]}
|
rules={[{ required: true, message: '请输入实验描述' }]}
|
||||||
|
style={{ marginBottom: '48px' }}
|
||||||
>
|
>
|
||||||
<Input placeholder="请输入实验描述" maxLength={128} showCount allowClear />
|
<Input.TextArea
|
||||||
|
placeholder="请输入实验描述"
|
||||||
|
maxLength={128}
|
||||||
|
autoSize={{ minRows: 2, maxRows: 5 }}
|
||||||
|
showCount
|
||||||
|
allowClear
|
||||||
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label="选择流水线"
|
label="选择流水线"
|
||||||
|
|
|
@ -68,19 +68,9 @@ function ExperimentText() {
|
||||||
};
|
};
|
||||||
const formChange = (val) => {};
|
const formChange = (val) => {};
|
||||||
const handlerClick = (e) => {
|
const handlerClick = (e) => {
|
||||||
console.log(propsRef, graph, messageRef.current);
|
if (e.target.get('name') !== 'anchor-point' && e.item) {
|
||||||
// let cache = [];
|
propsRef.current.showDrawer(e, locationParams.id, messageRef.current);
|
||||||
// let json_str = JSON.stringify(graph, function(key, value) {
|
}
|
||||||
// if (typeof value === 'object' && value !== null) {
|
|
||||||
// if (cache.indexOf(value) !== -1) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// cache.push(value);
|
|
||||||
// }
|
|
||||||
// return value;
|
|
||||||
// });
|
|
||||||
// console.log(json_str);
|
|
||||||
propsRef.current.showDrawer(e, locationParams.id, messageRef.current);
|
|
||||||
};
|
};
|
||||||
const getGraphData = (data) => {
|
const getGraphData = (data) => {
|
||||||
if (graph) {
|
if (graph) {
|
||||||
|
@ -387,8 +377,7 @@ function ExperimentText() {
|
||||||
fitView: true,
|
fitView: true,
|
||||||
fitViewPadding: [320, 320, 220, 320],
|
fitViewPadding: [320, 320, 220, 320],
|
||||||
});
|
});
|
||||||
|
graph.on('node:click', handlerClick);
|
||||||
graph.on('dblclick', handlerClick);
|
|
||||||
window.onresize = () => {
|
window.onresize = () => {
|
||||||
if (!graph || graph.get('destroyed')) return;
|
if (!graph || graph.get('destroyed')) return;
|
||||||
if (!graphRef.current || !graphRef.current.scrollWidth || !graphRef.current.scrollHeight)
|
if (!graphRef.current || !graphRef.current.scrollWidth || !graphRef.current.scrollHeight)
|
||||||
|
|
|
@ -29,12 +29,37 @@
|
||||||
background: #ffffff;
|
background: #ffffff;
|
||||||
box-shadow: 0px 3px 6px rgba(146, 146, 146, 0.09);
|
box-shadow: 0px 3px 6px rgba(146, 146, 146, 0.09);
|
||||||
}
|
}
|
||||||
|
.drawBox{
|
||||||
|
:global{
|
||||||
|
.ant-drawer .ant-drawer-body{
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.experimentDrawer{
|
||||||
|
:global{
|
||||||
|
.ant-tabs >.ant-tabs-nav .ant-tabs-nav-list{
|
||||||
|
margin-left: 24px;
|
||||||
|
}
|
||||||
|
.ant-drawer .ant-drawer-body{
|
||||||
|
overflow-y: hidden;
|
||||||
|
}
|
||||||
|
.ant-tabs {
|
||||||
|
height: calc(100% - 160px);
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
.detailBox {
|
.detailBox {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
color: #1d1d20;
|
color: #1d1d20;
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
|
padding-left: 24px;
|
||||||
|
|
||||||
}
|
}
|
||||||
.allMessageItem {
|
.allMessageItem {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
@ -12,7 +12,7 @@ import styles from './paramsModal.less';
|
||||||
type ParamsModalProps = {
|
type ParamsModalProps = {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
onCancel: () => void;
|
onCancel: () => void;
|
||||||
globalParam?: PipelineGlobalParam[];
|
globalParam?: PipelineGlobalParam[] | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
function ParamsModal({ open, onCancel, globalParam = [] }: ParamsModalProps) {
|
function ParamsModal({ open, onCancel, globalParam = [] }: ParamsModalProps) {
|
||||||
|
@ -26,7 +26,7 @@ function ParamsModal({ open, onCancel, globalParam = [] }: ParamsModalProps) {
|
||||||
cancelButtonProps={{ style: { display: 'none' } }}
|
cancelButtonProps={{ style: { display: 'none' } }}
|
||||||
>
|
>
|
||||||
<div className={styles.params_container}>
|
<div className={styles.params_container}>
|
||||||
{globalParam.map((item) => (
|
{globalParam?.map((item) => (
|
||||||
<div key={item.param_name} className={styles.params_container_line}>
|
<div key={item.param_name} className={styles.params_container_line}>
|
||||||
<span className={styles.params_container_line_label}>{getParamType(item)}</span>
|
<span className={styles.params_container_line_label}>{getParamType(item)}</span>
|
||||||
<span className={styles.params_container_line_value}>{item.param_value}</span>
|
<span className={styles.params_container_line_value}>{item.param_value}</span>
|
||||||
|
|
|
@ -386,7 +386,7 @@ const Props = forwardRef(({ onParentChange }, ref) => {
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
return (
|
return (
|
||||||
<>
|
<div className={Styles.drawBox}>
|
||||||
<Drawer
|
<Drawer
|
||||||
title="任务执行详情"
|
title="任务执行详情"
|
||||||
placement="right"
|
placement="right"
|
||||||
|
@ -397,9 +397,12 @@ const Props = forwardRef(({ onParentChange }, ref) => {
|
||||||
afterOpenChange={afterOpenChange}
|
afterOpenChange={afterOpenChange}
|
||||||
open={open}
|
open={open}
|
||||||
width={420}
|
width={420}
|
||||||
|
className={Styles.experimentDrawer}
|
||||||
destroyOnClose={true}
|
destroyOnClose={true}
|
||||||
>
|
>
|
||||||
<div className={Styles.detailBox}>任务名称:{stagingItem.label}</div>
|
<div className={Styles.detailBox} style={{ marginTop: '15px' }}>
|
||||||
|
任务名称:{stagingItem.label}
|
||||||
|
</div>
|
||||||
<div className={Styles.detailBox}>
|
<div className={Styles.detailBox}>
|
||||||
执行状态:
|
执行状态:
|
||||||
<div
|
<div
|
||||||
|
@ -429,7 +432,7 @@ const Props = forwardRef(({ onParentChange }, ref) => {
|
||||||
</div>
|
</div>
|
||||||
<Tabs defaultActiveKey="1" items={items} />
|
<Tabs defaultActiveKey="1" items={items} />
|
||||||
</Drawer>
|
</Drawer>
|
||||||
</>
|
</div>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -69,6 +69,7 @@ function Experiment() {
|
||||||
return { ...item, key: item.id };
|
return { ...item, key: item.id };
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
setTotal(res.data.totalElements);
|
setTotal(res.data.totalElements);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -82,6 +83,7 @@ function Experiment() {
|
||||||
// 获取实验实例
|
// 获取实验实例
|
||||||
const getQueryByExperiment = (val) => {
|
const getQueryByExperiment = (val) => {
|
||||||
getQueryByExperimentId(val).then((ret) => {
|
getQueryByExperimentId(val).then((ret) => {
|
||||||
|
console.log(val);
|
||||||
setExpandedRowKeys(val);
|
setExpandedRowKeys(val);
|
||||||
if (ret && ret.data && ret.data.length > 0) {
|
if (ret && ret.data && ret.data.length > 0) {
|
||||||
try {
|
try {
|
||||||
|
@ -159,6 +161,7 @@ function Experiment() {
|
||||||
};
|
};
|
||||||
const expandChange = (e, record) => {
|
const expandChange = (e, record) => {
|
||||||
clearExperimentInTimers();
|
clearExperimentInTimers();
|
||||||
|
console.log(e, record);
|
||||||
if (record.id === expandedRowKeys) {
|
if (record.id === expandedRowKeys) {
|
||||||
setExpandedRowKeys(null);
|
setExpandedRowKeys(null);
|
||||||
} else {
|
} else {
|
||||||
|
@ -517,6 +520,7 @@ function Experiment() {
|
||||||
: ''}
|
: ''}
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
|
|
||||||
onExpand: (e, a) => {
|
onExpand: (e, a) => {
|
||||||
expandChange(e, a);
|
expandChange(e, a);
|
||||||
},
|
},
|
||||||
|
|
|
@ -219,6 +219,11 @@
|
||||||
border-color: #eaeaea;
|
border-color: #eaeaea;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
.dropdown{
|
||||||
|
position: absolute;
|
||||||
|
right: 20px;
|
||||||
|
top: 15px;
|
||||||
|
}
|
||||||
.itemText {
|
.itemText {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 20px;
|
top: 20px;
|
||||||
|
|
|
@ -222,8 +222,8 @@ const Dataset = () => {
|
||||||
<span style={{ color: '#1d1d20', fontSize: '20px' }}>{datasetDetailObj.name}</span>
|
<span style={{ color: '#1d1d20', fontSize: '20px' }}>{datasetDetailObj.name}</span>
|
||||||
<div className={Styles.smallTagBox}>
|
<div className={Styles.smallTagBox}>
|
||||||
<div className={Styles.tagItem}>模型 id:{datasetDetailObj.id}</div>
|
<div className={Styles.tagItem}>模型 id:{datasetDetailObj.id}</div>
|
||||||
<div className={Styles.tagItem}>{datasetDetailObj.data_tag || '...'}</div>
|
<div className={Styles.tagItem}>{datasetDetailObj.model_type_name || '...'}</div>
|
||||||
<div className={Styles.tagItem}>{datasetDetailObj.data_type}</div>
|
<div className={Styles.tagItem}>{datasetDetailObj.model_tag_name || '...'}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={Styles.datasetIntroCneterBox}>
|
<div className={Styles.datasetIntroCneterBox}>
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
import { getAccessToken } from '@/access';
|
import { getAccessToken } from '@/access';
|
||||||
import clock from '@/assets/img/clock.png';
|
import clock from '@/assets/img/clock.png';
|
||||||
import creatByImg from '@/assets/img/creatBy.png';
|
import creatByImg from '@/assets/img/creatBy.png';
|
||||||
|
import deleteIcon from '@/assets/img/delete-icon.png';
|
||||||
import KFIcon from '@/components/KFIcon';
|
import KFIcon from '@/components/KFIcon';
|
||||||
import { addModel, getAssetIcon, getModelList } from '@/services/dataset/index.js';
|
import { addModel, deleteModel, getAssetIcon, getModelList } from '@/services/dataset/index.js';
|
||||||
|
import { modalConfirm } from '@/utils/ui';
|
||||||
import { UploadOutlined } from '@ant-design/icons';
|
import { UploadOutlined } from '@ant-design/icons';
|
||||||
import { Button, Form, Input, Modal, Pagination, Select, Upload } from 'antd';
|
import { Button, Form, Input, Modal, Pagination, Select, Upload, message } from 'antd';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
@ -54,8 +56,8 @@ const PublicData = () => {
|
||||||
});
|
});
|
||||||
const [activeType, setActiveType] = useState(null);
|
const [activeType, setActiveType] = useState(null);
|
||||||
const [activeTag, setActiveTag] = useState(null);
|
const [activeTag, setActiveTag] = useState(null);
|
||||||
const [datasetTypeList, setDatasetTypeList] = useState([]);
|
const [modelTypeList, setmodelTypeList] = useState([]);
|
||||||
const [datasetDirectionList, setDatasetDirectionList] = useState([]);
|
const [modelDirectionList, setmodelDirectionList] = useState([]);
|
||||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||||
const [datasetList, setDatasetList] = useState([]);
|
const [datasetList, setDatasetList] = useState([]);
|
||||||
const [total, setTotal] = useState(0);
|
const [total, setTotal] = useState(0);
|
||||||
|
@ -82,11 +84,11 @@ const PublicData = () => {
|
||||||
getAssetIcon(params).then((ret) => {
|
getAssetIcon(params).then((ret) => {
|
||||||
console.log(ret);
|
console.log(ret);
|
||||||
if (ret.code == 200 && ret.data.content && ret.data.content.length > 0) {
|
if (ret.code == 200 && ret.data.content && ret.data.content.length > 0) {
|
||||||
setDatasetTypeList(ret.data.content.filter((item) => item.category_id == 3));
|
setmodelTypeList(ret.data.content.filter((item) => item.category_id == 3));
|
||||||
setDatasetDirectionList(ret.data.content.filter((item) => item.category_id == 4));
|
setmodelDirectionList(ret.data.content.filter((item) => item.category_id == 4));
|
||||||
} else {
|
} else {
|
||||||
setDatasetTypeList([]);
|
setmodelTypeList([]);
|
||||||
setDatasetDirectionList([]);
|
setmodelDirectionList([]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -181,8 +183,8 @@ const PublicData = () => {
|
||||||
/>
|
/>
|
||||||
<div className={Styles.itemTitle}>模型框架</div>
|
<div className={Styles.itemTitle}>模型框架</div>
|
||||||
<div className={Styles.itemBox}>
|
<div className={Styles.itemBox}>
|
||||||
{datasetTypeList && datasetTypeList.length > 0
|
{modelTypeList && modelTypeList.length > 0
|
||||||
? datasetTypeList.map((item) => {
|
? modelTypeList.map((item) => {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
|
@ -222,8 +224,8 @@ const PublicData = () => {
|
||||||
</div>
|
</div>
|
||||||
<div className={Styles.itemTitle}>模型能力</div>
|
<div className={Styles.itemTitle}>模型能力</div>
|
||||||
<div className={Styles.itemBox}>
|
<div className={Styles.itemBox}>
|
||||||
{datasetDirectionList && datasetDirectionList.length > 0
|
{modelDirectionList && modelDirectionList.length > 0
|
||||||
? datasetDirectionList.map((item) => {
|
? modelDirectionList.map((item) => {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
|
@ -282,9 +284,80 @@ const PublicData = () => {
|
||||||
{datasetList && datasetList.length > 0
|
{datasetList && datasetList.length > 0
|
||||||
? datasetList.map((item) => {
|
? datasetList.map((item) => {
|
||||||
return (
|
return (
|
||||||
<div className={Styles.dataItem} onClick={(e) => routeToIntro(e, item)}>
|
<div
|
||||||
|
className={Styles.dataItem}
|
||||||
|
onClick={(e) => {
|
||||||
|
routeToIntro(e, item);
|
||||||
|
}}
|
||||||
|
>
|
||||||
<span className={Styles.itemText}>{item.name}</span>
|
<span className={Styles.itemText}>{item.name}</span>
|
||||||
<div className={Styles.itemDescripition}>{item.description}</div>
|
<img
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
modalConfirm({
|
||||||
|
title: '确定删除该条模型实例吗?',
|
||||||
|
onOk: () => {
|
||||||
|
deleteModel(item.id).then((ret) => {
|
||||||
|
if (ret.code === 200) {
|
||||||
|
message.success('删除成功');
|
||||||
|
getModelLists(queryFlow);
|
||||||
|
} else {
|
||||||
|
message.error(ret.msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
className={Styles.dropdown}
|
||||||
|
style={{ width: '17px', marginRight: '6px' }}
|
||||||
|
src={deleteIcon}
|
||||||
|
alt=""
|
||||||
|
/>
|
||||||
|
{/* <Dropdown
|
||||||
|
className={Styles.dropdown}
|
||||||
|
key={item.name}
|
||||||
|
menu={{
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
label: '详情',
|
||||||
|
key: 'detail',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '删除',
|
||||||
|
key: 'delete',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
onClick: (e) => {
|
||||||
|
console.log(e);
|
||||||
|
if (e.key === 'detail') {
|
||||||
|
routeToIntro(e, item);
|
||||||
|
} else if (e.key === 'delete') {
|
||||||
|
modalConfirm({
|
||||||
|
title: '确定删除该条模型实例吗?',
|
||||||
|
onOk: () => {
|
||||||
|
deleteModel(item.id).then((ret) => {
|
||||||
|
if (ret.code === 200) {
|
||||||
|
message.success('删除成功');
|
||||||
|
getModelLists(queryFlow);
|
||||||
|
} else {
|
||||||
|
message.error(ret.msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<img
|
||||||
|
style={{ width: '17px', marginRight: '6px' }}
|
||||||
|
src={moreBack}
|
||||||
|
alt=""
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Dropdown> */}
|
||||||
|
,<div className={Styles.itemDescripition}>{item.description}</div>
|
||||||
<div className={Styles.itemTime}>
|
<div className={Styles.itemTime}>
|
||||||
<img
|
<img
|
||||||
style={{ width: '17px', marginRight: '6px' }}
|
style={{ width: '17px', marginRight: '6px' }}
|
||||||
|
@ -401,7 +474,13 @@ const PublicData = () => {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Select allowClear placeholder="请选择模型类型" options={[]} />
|
<Select
|
||||||
|
allowClear
|
||||||
|
placeholder="请选择模型类型"
|
||||||
|
options={modelTypeList.map((item) => {
|
||||||
|
return { value: item.id, label: item.name };
|
||||||
|
})}
|
||||||
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label="模型能力"
|
label="模型能力"
|
||||||
|
@ -415,7 +494,13 @@ const PublicData = () => {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Select allowClear placeholder="请选择模型标签" options={[]} />
|
<Select
|
||||||
|
allowClear
|
||||||
|
placeholder="请选择模型标签"
|
||||||
|
options={modelDirectionList.map((item) => {
|
||||||
|
return { value: item.id, label: item.name };
|
||||||
|
})}
|
||||||
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item label="模型文件" name="models_version_vos">
|
<Form.Item label="模型文件" name="models_version_vos">
|
||||||
<Upload {...props} data={{ uuid: uuid }} accept=".zip,.tgz">
|
<Upload {...props} data={{ uuid: uuid }} accept=".zip,.tgz">
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
import clock from '@/assets/img/clock.png';
|
import clock from '@/assets/img/clock.png';
|
||||||
import creatByImg from '@/assets/img/creatBy.png';
|
import creatByImg from '@/assets/img/creatBy.png';
|
||||||
import { getAssetIcon, getModelList } from '@/services/dataset/index.js';
|
import deleteIcon from '@/assets/img/delete-icon.png';
|
||||||
import { Form, Input, Modal, Pagination, Radio } from 'antd';
|
import { deleteModel, getAssetIcon, getModelList } from '@/services/dataset/index.js';
|
||||||
|
import { modalConfirm } from '@/utils/ui';
|
||||||
|
import { Form, Input, Modal, Pagination, Radio, message } from 'antd';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
@ -224,8 +226,35 @@ const PublicData = () => {
|
||||||
{datasetList && datasetList.length > 0
|
{datasetList && datasetList.length > 0
|
||||||
? datasetList.map((item) => {
|
? datasetList.map((item) => {
|
||||||
return (
|
return (
|
||||||
<div className={Styles.dataItem} onClick={(e) => routeToIntro(e, item)}>
|
<div
|
||||||
|
className={Styles.dataItem}
|
||||||
|
onClick={(e) => {
|
||||||
|
routeToIntro(e, item);
|
||||||
|
}}
|
||||||
|
>
|
||||||
<span className={Styles.itemText}>{item.name}</span>
|
<span className={Styles.itemText}>{item.name}</span>
|
||||||
|
<img
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
modalConfirm({
|
||||||
|
title: '确定删除该条模型实例吗?',
|
||||||
|
onOk: () => {
|
||||||
|
deleteModel(item.id).then((ret) => {
|
||||||
|
if (ret.code === 200) {
|
||||||
|
message.success('删除成功');
|
||||||
|
getModelLists(queryFlow);
|
||||||
|
} else {
|
||||||
|
message.error(ret.msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
className={Styles.dropdown}
|
||||||
|
style={{ width: '17px', marginRight: '6px' }}
|
||||||
|
src={deleteIcon}
|
||||||
|
alt=""
|
||||||
|
/>
|
||||||
<div className={Styles.itemDescripition}>{item.description}</div>
|
<div className={Styles.itemDescripition}>{item.description}</div>
|
||||||
<div className={Styles.itemTime}>
|
<div className={Styles.itemTime}>
|
||||||
<img
|
<img
|
||||||
|
|
|
@ -14,7 +14,7 @@ import styles from './globalParamsDrawer.less';
|
||||||
type GlobalParamsDrawerProps = {
|
type GlobalParamsDrawerProps = {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
globalParam: PipelineGlobalParam[];
|
globalParam: PipelineGlobalParam[] | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
const GlobalParamsDrawer = forwardRef(
|
const GlobalParamsDrawer = forwardRef(
|
||||||
|
|
|
@ -128,18 +128,7 @@ const EditPipeline = () => {
|
||||||
};
|
};
|
||||||
const handlerClick = (e) => {
|
const handlerClick = (e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
console.log(propsRef, graph);
|
// console.log(propsRef, graph);
|
||||||
// let cache = [];
|
|
||||||
// let json_str = JSON.stringify(graph, function(key, value) {
|
|
||||||
// if (typeof value === 'object' && value !== null) {
|
|
||||||
// if (cache.indexOf(value) !== -1) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// cache.push(value);
|
|
||||||
// }
|
|
||||||
// return value;
|
|
||||||
// });
|
|
||||||
// console.log(json_str);
|
|
||||||
propsRef.current.showDrawer(e);
|
propsRef.current.showDrawer(e);
|
||||||
};
|
};
|
||||||
const getGraphData = (data) => {
|
const getGraphData = (data) => {
|
||||||
|
@ -281,7 +270,7 @@ const EditPipeline = () => {
|
||||||
const getFirstWorkflow = (val) => {
|
const getFirstWorkflow = (val) => {
|
||||||
getWorkflowById(val).then((ret) => {
|
getWorkflowById(val).then((ret) => {
|
||||||
if (ret && ret.data) {
|
if (ret && ret.data) {
|
||||||
setGlobalParam(ret.data.global_param);
|
setGlobalParam(ret.data.global_param || []);
|
||||||
}
|
}
|
||||||
if (graph && ret.data && ret.data.dag) {
|
if (graph && ret.data && ret.data.dag) {
|
||||||
getGraphData(JSON.parse(ret.data.dag));
|
getGraphData(JSON.parse(ret.data.dag));
|
||||||
|
@ -353,7 +342,7 @@ const EditPipeline = () => {
|
||||||
// this.graph.setItemState(e.item, 'showAnchors', false);
|
// this.graph.setItemState(e.item, 'showAnchors', false);
|
||||||
graph.setItemState(e.item, 'nodeSelected', false);
|
graph.setItemState(e.item, 'nodeSelected', false);
|
||||||
});
|
});
|
||||||
graph.off('dblclick', handlerClick);
|
// graph.off('dblclick', handlerClick);
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
const initGraph = () => {
|
const initGraph = () => {
|
||||||
|
@ -390,30 +379,15 @@ const EditPipeline = () => {
|
||||||
getAnchorPoints(cfg) {
|
getAnchorPoints(cfg) {
|
||||||
return (
|
return (
|
||||||
cfg.anchorPoints || [
|
cfg.anchorPoints || [
|
||||||
// 上下各3,左右各1
|
// 四个
|
||||||
[0.5, 0],
|
[0.5, 0],
|
||||||
[0.5, 1],
|
[0.5, 1],
|
||||||
|
// [0, 0.5],
|
||||||
|
// [1, 0.5],
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
// draw(cfg, group) {
|
|
||||||
|
|
||||||
// let rect=group.addShape('text', {
|
|
||||||
// attrs: {
|
|
||||||
// text: fittingString(cfg.label, 110, 15),
|
|
||||||
// x: 90 - getTextSize(cfg.label, 110, 15),
|
|
||||||
// y: 0,
|
|
||||||
// fontSize: 10,
|
|
||||||
// textAlign: 'center',
|
|
||||||
// textBaseline: 'middle',
|
|
||||||
// fill:'#000'
|
|
||||||
// },
|
|
||||||
// name: 'text-shape',
|
|
||||||
// });
|
|
||||||
// return rect;
|
|
||||||
// },
|
|
||||||
afterDraw(cfg, group) {
|
afterDraw(cfg, group) {
|
||||||
// console.log(group, cfg, 12312);
|
|
||||||
const image = group.addShape('image', {
|
const image = group.addShape('image', {
|
||||||
attrs: {
|
attrs: {
|
||||||
x: -45,
|
x: -45,
|
||||||
|
@ -442,7 +416,6 @@ const EditPipeline = () => {
|
||||||
}
|
}
|
||||||
const bbox = group.getBBox();
|
const bbox = group.getBBox();
|
||||||
const anchorPoints = this.getAnchorPoints(cfg);
|
const anchorPoints = this.getAnchorPoints(cfg);
|
||||||
// console.log(anchorPoints);
|
|
||||||
anchorPoints.forEach((anchorPos, i) => {
|
anchorPoints.forEach((anchorPos, i) => {
|
||||||
group.addShape('circle', {
|
group.addShape('circle', {
|
||||||
attrs: {
|
attrs: {
|
||||||
|
@ -456,6 +429,7 @@ const EditPipeline = () => {
|
||||||
anchorPointIdx: i, // flag the idx of the anchor-point circle
|
anchorPointIdx: i, // flag the idx of the anchor-point circle
|
||||||
links: 0, // cache the number of edges connected to this shape
|
links: 0, // cache the number of edges connected to this shape
|
||||||
visible: false, // invisible by default, shows up when links > 1 or the node is in showAnchors state
|
visible: false, // invisible by default, shows up when links > 1 or the node is in showAnchors state
|
||||||
|
draggable: true,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
return image;
|
return image;
|
||||||
|
@ -503,7 +477,7 @@ const EditPipeline = () => {
|
||||||
// config the shouldBegin and shouldEnd to make sure the create-edge is began and ended at anchor-point circles
|
// config the shouldBegin and shouldEnd to make sure the create-edge is began and ended at anchor-point circles
|
||||||
{
|
{
|
||||||
type: 'create-edge',
|
type: 'create-edge',
|
||||||
// trigger: 'drag',
|
trigger: 'drag',
|
||||||
shouldBegin: (e) => {
|
shouldBegin: (e) => {
|
||||||
// avoid beginning at other shapes on the node
|
// avoid beginning at other shapes on the node
|
||||||
if (e.target && e.target.get('name') !== 'anchor-point') return false;
|
if (e.target && e.target.get('name') !== 'anchor-point') return false;
|
||||||
|
@ -575,7 +549,7 @@ const EditPipeline = () => {
|
||||||
},
|
},
|
||||||
defaultEdge: {
|
defaultEdge: {
|
||||||
// type: 'quadratic',
|
// type: 'quadratic',
|
||||||
type: 'cubic-vertical',
|
// type: 'cubic-vertical',
|
||||||
|
|
||||||
style: {
|
style: {
|
||||||
endArrow: {
|
endArrow: {
|
||||||
|
@ -619,16 +593,20 @@ const EditPipeline = () => {
|
||||||
fitView: true,
|
fitView: true,
|
||||||
fitViewPadding: [320, 320, 220, 320],
|
fitViewPadding: [320, 320, 220, 320],
|
||||||
});
|
});
|
||||||
graph.on('dblclick', (e) => {
|
// graph.on('dblclick', (e) => {
|
||||||
console.log(e.item);
|
// console.log(e.item);
|
||||||
if (e.item) {
|
// if (e.item) {
|
||||||
|
// graph.setItemState(e.item, 'nodeClicked', true);
|
||||||
|
// handlerClick(e);
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
graph.on('node:click', (e) => {
|
||||||
|
console.log(e.target.get('name'));
|
||||||
|
if (e.target.get('name') !== 'anchor-point' && e.item) {
|
||||||
graph.setItemState(e.item, 'nodeClicked', true);
|
graph.setItemState(e.item, 'nodeClicked', true);
|
||||||
handlerClick(e);
|
handlerClick(e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
graph.on('click', (e) => {
|
|
||||||
console.log(e.item);
|
|
||||||
});
|
|
||||||
graph.on('aftercreateedge', (e) => {
|
graph.on('aftercreateedge', (e) => {
|
||||||
// update the sourceAnchor and targetAnchor for the newly added edge
|
// update the sourceAnchor and targetAnchor for the newly added edge
|
||||||
graph.updateItem(e.edge, {
|
graph.updateItem(e.edge, {
|
||||||
|
@ -666,6 +644,39 @@ const EditPipeline = () => {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
graph.on('node:dragenter', (e) => {
|
||||||
|
console.log(e.target.get('name'));
|
||||||
|
console.log('node:dragenter');
|
||||||
|
graph.setItemState(e.item, 'nodeSelected', true);
|
||||||
|
graph.updateItem(e.item, {
|
||||||
|
// 节点的样式
|
||||||
|
style: {
|
||||||
|
stroke: '#1664ff',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
graph.on('node:dragleave', (e) => {
|
||||||
|
console.log(e.target.get('name'));
|
||||||
|
console.log('node:dragleave');
|
||||||
|
graph.setItemState(e.item, 'nodeSelected', false);
|
||||||
|
graph.updateItem(e.item, {
|
||||||
|
// 节点的样式
|
||||||
|
style: {
|
||||||
|
stroke: 'transparent',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
graph.on('node:dragstart', (e) => {
|
||||||
|
console.log('node:dragstart');
|
||||||
|
graph.setItemState(e.item, 'nodeSelected', true);
|
||||||
|
graph.updateItem(e.item, {
|
||||||
|
// 节点的样式
|
||||||
|
style: {
|
||||||
|
stroke: '#1664ff',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
graph.on('afterremoveitem', (e) => {
|
graph.on('afterremoveitem', (e) => {
|
||||||
if (e.item && e.item.source && e.item.target) {
|
if (e.item && e.item.source && e.item.target) {
|
||||||
const sourceNode = graph.findById(e.item.source);
|
const sourceNode = graph.findById(e.item.source);
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
/*
|
/*
|
||||||
* @Author: 赵伟
|
* @Author: 赵伟
|
||||||
* @Date: 2024-03-25 13:52:54
|
* @Date: 2024-03-25 13:52:54
|
||||||
* @Description:
|
* @Description: 网络请求配置,详情请参考 https://umijs.org/docs/max/request
|
||||||
*/
|
*/
|
||||||
import type { RequestConfig } from '@umijs/max';
|
import type { RequestConfig } from '@umijs/max';
|
||||||
import { message } from 'antd';
|
import { message } from 'antd';
|
||||||
import { clearSessionToken, getAccessToken, getRefreshToken, getTokenExpireTime } from './access';
|
import { clearSessionToken, getAccessToken } from './access';
|
||||||
|
import { setRemoteMenu } from './services/session';
|
||||||
const checkRegion = 5 * 60 * 1000;
|
import { gotoLoginPage } from './utils/ui';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Umi Max 网络请求配置
|
* Umi Max 网络请求配置
|
||||||
|
@ -21,23 +21,25 @@ export const requestConfig: RequestConfig = {
|
||||||
const authHeader = headers['Authorization'];
|
const authHeader = headers['Authorization'];
|
||||||
const isToken = headers['isToken'];
|
const isToken = headers['isToken'];
|
||||||
if (!authHeader && isToken !== false) {
|
if (!authHeader && isToken !== false) {
|
||||||
const expireTime = getTokenExpireTime();
|
const accessToken = getAccessToken();
|
||||||
if (expireTime) {
|
if (accessToken) {
|
||||||
const left = Number(expireTime) - new Date().getTime();
|
headers['Authorization'] = `Bearer ${accessToken}`;
|
||||||
const refreshToken = getRefreshToken();
|
|
||||||
if (left < checkRegion && refreshToken) {
|
|
||||||
if (left < 0) {
|
|
||||||
clearSessionToken();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const accessToken = getAccessToken();
|
|
||||||
if (accessToken) {
|
|
||||||
headers['Authorization'] = `Bearer ${accessToken}`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
clearSessionToken();
|
|
||||||
}
|
}
|
||||||
|
// const expireTime = getTokenExpireTime();
|
||||||
|
// if (expireTime) {
|
||||||
|
// const left = Number(expireTime) - new Date().getTime();
|
||||||
|
// const refreshToken = getRefreshToken();
|
||||||
|
// if (left < 0 && refreshToken) {
|
||||||
|
// clearSessionToken();
|
||||||
|
// } else {
|
||||||
|
// const accessToken = getAccessToken();
|
||||||
|
// if (accessToken) {
|
||||||
|
// headers['Authorization'] = `Bearer ${accessToken}`;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// clearSessionToken();
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
return { url, options };
|
return { url, options };
|
||||||
},
|
},
|
||||||
|
@ -45,15 +47,19 @@ export const requestConfig: RequestConfig = {
|
||||||
responseInterceptors: [
|
responseInterceptors: [
|
||||||
(response: any) => {
|
(response: any) => {
|
||||||
const { status, data } = response;
|
const { status, data } = response;
|
||||||
// console.log('response', response);
|
if (status >= 200 && status < 300) {
|
||||||
if (status >= 200 && status < 300 && data && (data instanceof Blob || data.code === 200)) {
|
if (data && (data instanceof Blob || data.code === 200)) {
|
||||||
return response;
|
return response;
|
||||||
} else {
|
} else if (data && data.code === 401) {
|
||||||
if (data && data.msg) {
|
clearSessionToken();
|
||||||
message.error(data.msg);
|
setRemoteMenu(null);
|
||||||
|
gotoLoginPage(false);
|
||||||
} else {
|
} else {
|
||||||
message.error('请求失败');
|
message.error(data?.msg ?? '请求失败');
|
||||||
|
return Promise.reject(response);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
message.error('请求失败');
|
||||||
return Promise.reject(response);
|
return Promise.reject(response);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -118,3 +118,15 @@ export function exportDataset(id) {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
// 删除模型集
|
||||||
|
export function deleteModel(id) {
|
||||||
|
return request(`/api/mmp/models/${id}`, {
|
||||||
|
method: 'DELETE',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// 删除数据集
|
||||||
|
export function deleteDataset(id) {
|
||||||
|
return request(`/api/mmp/dataset/${id}`, {
|
||||||
|
method: 'DELETE',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
import { createIcon } from '@/utils/IconUtil';
|
|
||||||
import { MenuDataItem } from '@ant-design/pro-components';
|
import { MenuDataItem } from '@ant-design/pro-components';
|
||||||
import { request } from '@umijs/max';
|
import { request } from '@umijs/max';
|
||||||
import React, { lazy } from 'react';
|
import React, { lazy } from 'react';
|
||||||
import { createFromIconfontCN } from '@ant-design/icons';
|
|
||||||
let remoteMenu: any = null;
|
let remoteMenu: any = null;
|
||||||
|
|
||||||
export function getRemoteMenu() {
|
export function getRemoteMenu() {
|
||||||
|
@ -101,7 +100,7 @@ export function convertCompatRouters(childrens: API.RoutersMenuItem[]): any[] {
|
||||||
return {
|
return {
|
||||||
path: item.path,
|
path: item.path,
|
||||||
// icon:'icon-a-057_fenlei',
|
// icon:'icon-a-057_fenlei',
|
||||||
icon: 'icon-'+item.meta.icon,
|
icon: 'icon-' + item.meta.icon,
|
||||||
// icon: item.meta.icon,
|
// icon: item.meta.icon,
|
||||||
name: item.meta.title,
|
name: item.meta.title,
|
||||||
routes: item.children ? convertCompatRouters(item.children) : undefined,
|
routes: item.children ? convertCompatRouters(item.children) : undefined,
|
||||||
|
|
|
@ -28,8 +28,8 @@ export async function login(body: API.LoginParams, options?: Record<string, any>
|
||||||
|
|
||||||
/** 退出登录接口 POST /api/login/outLogin */
|
/** 退出登录接口 POST /api/login/outLogin */
|
||||||
export async function logout() {
|
export async function logout() {
|
||||||
return request<Record<string, any>>('/api/logout', {
|
return request<Record<string, any>>('/api/auth/logout', {
|
||||||
method: 'delete',
|
method: 'DELETE',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,10 @@
|
||||||
// 全局颜色变量
|
/*
|
||||||
|
* @Author: 赵伟
|
||||||
|
* @Date: 2024-04-28 08:47:43
|
||||||
|
* @Description: 全局变量,可以直接在 less 文件里使用,无需引入;也可以导入到 js 里使用;为 antd 主题修改提供常量值
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 颜色
|
||||||
@primary-color: #1664ff; // 主色调
|
@primary-color: #1664ff; // 主色调
|
||||||
@primary-color-hover: #69b1ff;
|
@primary-color-hover: #69b1ff;
|
||||||
@background-color: #f9fafb; // 页面背景颜色
|
@background-color: #f9fafb; // 页面背景颜色
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
|
/*
|
||||||
|
* @Author: 赵伟
|
||||||
|
* @Date: 2024-04-08 09:54:39
|
||||||
|
* @Description: 定义全局类型,比如无关联的页面都需要要的类型
|
||||||
|
*/
|
||||||
|
|
||||||
// 流水线全局参数
|
// 流水线全局参数
|
||||||
export type PipelineGlobalParam = {
|
export type PipelineGlobalParam = {
|
||||||
param_name: string;
|
param_name: string;
|
||||||
|
|
|
@ -3,7 +3,9 @@
|
||||||
* @Date: 2024-04-19 14:42:51
|
* @Date: 2024-04-19 14:42:51
|
||||||
* @Description: UI 公共方法
|
* @Description: UI 公共方法
|
||||||
*/
|
*/
|
||||||
|
import { PageEnum } from '@/enums/pagesEnums';
|
||||||
import themes from '@/styles/theme.less';
|
import themes from '@/styles/theme.less';
|
||||||
|
import { history } from '@umijs/max';
|
||||||
import { Modal, type ModalFuncProps, type UploadFile } from 'antd';
|
import { Modal, type ModalFuncProps, type UploadFile } from 'antd';
|
||||||
|
|
||||||
// 自定义 Confirm 弹框
|
// 自定义 Confirm 弹框
|
||||||
|
@ -43,3 +45,17 @@ export const getFileListFromEvent = (e: any) => {
|
||||||
return item;
|
return item;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 去登录页面
|
||||||
|
export const gotoLoginPage = (toHome: boolean = true) => {
|
||||||
|
const { pathname, search } = window.location;
|
||||||
|
const urlParams = new URLSearchParams();
|
||||||
|
urlParams.append('redirect', pathname + search);
|
||||||
|
const newSearch = toHome ? '' : urlParams.toString();
|
||||||
|
if (window.location.pathname !== PageEnum.LOGIN) {
|
||||||
|
history.replace({
|
||||||
|
pathname: PageEnum.LOGIN,
|
||||||
|
search: newSearch,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
|
@ -158,7 +158,7 @@ public class DatasetController {
|
||||||
*/
|
*/
|
||||||
@DeleteMapping({"{id}"})
|
@DeleteMapping({"{id}"})
|
||||||
@ApiOperation("根据id删除数据集")
|
@ApiOperation("根据id删除数据集")
|
||||||
public AjaxResult deleteById(@PathVariable("id") Integer id) {
|
public AjaxResult deleteById(@PathVariable("id") Integer id) throws Exception {
|
||||||
return AjaxResult.success(this.datasetService.removeById(id));
|
return AjaxResult.success(this.datasetService.removeById(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -123,7 +123,7 @@ public class ModelsController extends BaseController {
|
||||||
*/
|
*/
|
||||||
@PostMapping
|
@PostMapping
|
||||||
@ApiOperation("添加模型")
|
@ApiOperation("添加模型")
|
||||||
public GenericsAjaxResult<Models> add(@RequestBody Models models) {
|
public GenericsAjaxResult<Models> add(@RequestBody Models models) throws Exception {
|
||||||
return genericsSuccess(this.modelsService.insert(models));
|
return genericsSuccess(this.modelsService.insert(models));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,7 +161,7 @@ public class ModelsController extends BaseController {
|
||||||
*/
|
*/
|
||||||
@DeleteMapping("{id}")
|
@DeleteMapping("{id}")
|
||||||
@ApiOperation("删除模型")
|
@ApiOperation("删除模型")
|
||||||
public GenericsAjaxResult<String> deleteById(@PathVariable("id") Integer id) {
|
public GenericsAjaxResult<String> deleteById(@PathVariable("id") Integer id) throws Exception {
|
||||||
return genericsSuccess(this.modelsService.removeById(id));
|
return genericsSuccess(this.modelsService.removeById(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ package com.ruoyi.platform.domain;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
|
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
|
||||||
import com.fasterxml.jackson.databind.annotation.JsonNaming;
|
import com.fasterxml.jackson.databind.annotation.JsonNaming;
|
||||||
|
import com.ruoyi.platform.annotations.CheckDuplicate;
|
||||||
import io.swagger.annotations.ApiModel;
|
import io.swagger.annotations.ApiModel;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
|
||||||
|
@ -22,6 +23,7 @@ public class Models implements Serializable {
|
||||||
private Integer id;
|
private Integer id;
|
||||||
|
|
||||||
@ApiModelProperty(value = "模型名称")
|
@ApiModelProperty(value = "模型名称")
|
||||||
|
@CheckDuplicate
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
@ApiModelProperty(value = "模型描述")
|
@ApiModelProperty(value = "模型描述")
|
||||||
|
@ -52,6 +54,16 @@ public class Models implements Serializable {
|
||||||
private Integer state;
|
private Integer state;
|
||||||
|
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "模型类型名")
|
||||||
|
private String modelTypeName;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "模型tag名")
|
||||||
|
private String modelTagName;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public Integer getId() {
|
public Integer getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
@ -158,5 +170,21 @@ public class Models implements Serializable {
|
||||||
this.state = state;
|
this.state = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getModelTagName() {
|
||||||
|
return modelTagName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setModelTagName(String modelTagName) {
|
||||||
|
this.modelTagName = modelTagName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getModelTypeName() {
|
||||||
|
return modelTypeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setModelTypeName(String modelTypeName) {
|
||||||
|
this.modelTypeName = modelTypeName;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -84,7 +84,8 @@ public interface DatasetVersionDao {
|
||||||
|
|
||||||
List<DatasetVersion> queryByDatasetId(Integer datasetId);
|
List<DatasetVersion> queryByDatasetId(Integer datasetId);
|
||||||
|
|
||||||
DatasetVersion queryByDatasetVersion(@Param("datasetVersion") DatasetVersion datasetVersion);
|
DatasetVersion
|
||||||
|
queryByDatasetVersion(@Param("datasetVersion") DatasetVersion datasetVersion);
|
||||||
|
|
||||||
List<DatasetVersion> queryAllByDatasetVersion(@Param("datasetId") Integer datasetId, @Param("version") String version);
|
List<DatasetVersion> queryAllByDatasetVersion(@Param("datasetId") Integer datasetId, @Param("version") String version);
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
package com.ruoyi.platform.mapper;
|
package com.ruoyi.platform.mapper;
|
||||||
|
|
||||||
|
|
||||||
|
import com.ruoyi.platform.domain.Dataset;
|
||||||
import com.ruoyi.platform.domain.Models;
|
import com.ruoyi.platform.domain.Models;
|
||||||
import org.apache.ibatis.annotations.Param;
|
import org.apache.ibatis.annotations.Param;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* (Models)表数据库访问层
|
* (Models)表数据库访问层
|
||||||
|
@ -22,6 +24,8 @@ public interface ModelsDao {
|
||||||
*/
|
*/
|
||||||
Models queryById(Integer id);
|
Models queryById(Integer id);
|
||||||
|
|
||||||
|
Models findByName(@Param("name") String name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询指定行数据
|
* 查询指定行数据
|
||||||
*
|
*
|
||||||
|
|
|
@ -68,7 +68,7 @@ DatasetService {
|
||||||
*/
|
*/
|
||||||
boolean deleteById(Integer id);
|
boolean deleteById(Integer id);
|
||||||
|
|
||||||
String removeById(Integer id);
|
String removeById(Integer id) throws Exception;
|
||||||
|
|
||||||
ResponseEntity<InputStreamResource> downloadDataset(Integer id) throws Exception;
|
ResponseEntity<InputStreamResource> downloadDataset(Integer id) throws Exception;
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ package com.ruoyi.platform.service;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import com.ruoyi.platform.domain.Dataset;
|
||||||
import com.ruoyi.platform.domain.Models;
|
import com.ruoyi.platform.domain.Models;
|
||||||
import com.ruoyi.platform.domain.ModelsVersion;
|
import com.ruoyi.platform.domain.ModelsVersion;
|
||||||
import com.ruoyi.platform.vo.ModelsVo;
|
import com.ruoyi.platform.vo.ModelsVo;
|
||||||
|
@ -45,7 +46,7 @@ public interface ModelsService {
|
||||||
* @param models 实例对象
|
* @param models 实例对象
|
||||||
* @return 实例对象
|
* @return 实例对象
|
||||||
*/
|
*/
|
||||||
Models insert(Models models);
|
Models insert(Models models) throws Exception;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修改数据
|
* 修改数据
|
||||||
|
@ -64,7 +65,7 @@ public interface ModelsService {
|
||||||
*/
|
*/
|
||||||
boolean deleteById(Integer id);
|
boolean deleteById(Integer id);
|
||||||
|
|
||||||
String removeById(Integer id);
|
String removeById(Integer id) throws Exception;
|
||||||
|
|
||||||
ResponseEntity<InputStreamResource> downloadModels(Integer id) throws Exception;
|
ResponseEntity<InputStreamResource> downloadModels(Integer id) throws Exception;
|
||||||
|
|
||||||
|
@ -81,5 +82,7 @@ public interface ModelsService {
|
||||||
|
|
||||||
String readFileContent(Integer modelsId, String version) throws Exception;
|
String readFileContent(Integer modelsId, String version) throws Exception;
|
||||||
|
|
||||||
|
public void checkDeclaredName(Models insert) throws Exception;
|
||||||
|
|
||||||
List<Map<String, String>> exportModels(String path, String uuid) throws Exception;
|
List<Map<String, String>> exportModels(String path, String uuid) throws Exception;
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,17 +84,27 @@ public class DatasetServiceImpl implements DatasetService {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Dataset queryById(Integer id) {
|
public Dataset queryById(Integer id) {
|
||||||
|
|
||||||
Dataset dataset = this.datasetDao.queryById(id);
|
Dataset dataset = this.datasetDao.queryById(id);
|
||||||
String dataType = dataset.getDataType();
|
if (dataset != null) {
|
||||||
String dataTag = dataset.getDataTag();
|
String dataType = dataset.getDataType();
|
||||||
//去资产管理表中查询对应的图标名
|
String dataTag = dataset.getDataTag();
|
||||||
AssetIcon dataTypeAssetIcon = assetIconService.queryByPath(dataType);
|
|
||||||
AssetIcon dataTagAssetIcon = assetIconService.queryByPath(dataTag);
|
|
||||||
dataset.setDatasetTypeName(dataTypeAssetIcon.getName());
|
|
||||||
dataset.setDatasetTagName(dataTagAssetIcon.getName());
|
|
||||||
return dataset;
|
|
||||||
|
|
||||||
|
// 判空逻辑,只有当dataType和dataTag不为空时,才进行查询
|
||||||
|
if (dataType != null && !dataType.isEmpty()) {
|
||||||
|
AssetIcon dataTypeAssetIcon = assetIconService.queryById(Integer.valueOf(dataType));
|
||||||
|
if (dataTypeAssetIcon != null) {
|
||||||
|
dataset.setDatasetTypeName(dataTypeAssetIcon.getName());
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dataTag != null && !dataTag.isEmpty()) {
|
||||||
|
AssetIcon dataTagAssetIcon = assetIconService.queryById(Integer.valueOf(dataTag));
|
||||||
|
if (dataTagAssetIcon != null) {
|
||||||
|
dataset.setDatasetTagName(dataTagAssetIcon.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dataset;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -163,10 +173,10 @@ public class DatasetServiceImpl implements DatasetService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String removeById(Integer id) {
|
public String removeById(Integer id) throws Exception {
|
||||||
Dataset dataset = this.datasetDao.queryById(id);
|
Dataset dataset = this.datasetDao.queryById(id);
|
||||||
if (dataset == null){
|
if (dataset == null){
|
||||||
return "数据集不存在";
|
throw new Exception("数据集不存在");
|
||||||
}
|
}
|
||||||
|
|
||||||
//判断权限,只有admin和创建者本身可以删除该数据集
|
//判断权限,只有admin和创建者本身可以删除该数据集
|
||||||
|
@ -174,10 +184,10 @@ public class DatasetServiceImpl implements DatasetService {
|
||||||
String username = loginUser.getUsername();
|
String username = loginUser.getUsername();
|
||||||
String createdBy = dataset.getCreateBy();
|
String createdBy = dataset.getCreateBy();
|
||||||
if (!(StringUtils.equals(username,"admin") || StringUtils.equals(username,createdBy))){
|
if (!(StringUtils.equals(username,"admin") || StringUtils.equals(username,createdBy))){
|
||||||
return "无权限删除该数据集版本";
|
throw new Exception("无权限删除该数据集");
|
||||||
}
|
}
|
||||||
if (datasetVersionService.queryByDatasetId(id).size()>0){
|
if (datasetVersionService.queryByDatasetId(id).size()>0){
|
||||||
return "请先删除该数据集的版本文件";
|
throw new Exception("请先删除该数据集下的版本文件");
|
||||||
}
|
}
|
||||||
|
|
||||||
dataset.setState(0);
|
dataset.setState(0);
|
||||||
|
@ -232,6 +242,7 @@ public class DatasetServiceImpl implements DatasetService {
|
||||||
@Override
|
@Override
|
||||||
public List<Map<String, String>> uploadDataset(MultipartFile[] files, String uuid) throws Exception {
|
public List<Map<String, String>> uploadDataset(MultipartFile[] files, String uuid) throws Exception {
|
||||||
List<Map<String, String>> results = new ArrayList<>();
|
List<Map<String, String>> results = new ArrayList<>();
|
||||||
|
|
||||||
for (MultipartFile file:files){
|
for (MultipartFile file:files){
|
||||||
// 构建objectName
|
// 构建objectName
|
||||||
String username = SecurityUtils.getLoginUser().getUsername();
|
String username = SecurityUtils.getLoginUser().getUsername();
|
||||||
|
@ -251,7 +262,6 @@ public class DatasetServiceImpl implements DatasetService {
|
||||||
if (dataset == null) {
|
if (dataset == null) {
|
||||||
throw new Exception("数据集不存在,请检查数据集id");
|
throw new Exception("数据集不存在,请检查数据集id");
|
||||||
}
|
}
|
||||||
|
|
||||||
DatasetVersion version = datasetVersionService.queryByDatasetVersion(datasetVersion);
|
DatasetVersion version = datasetVersionService.queryByDatasetVersion(datasetVersion);
|
||||||
String url = "";
|
String url = "";
|
||||||
if (version == null) {
|
if (version == null) {
|
||||||
|
|
|
@ -221,7 +221,7 @@ public class ImageServiceImpl implements ImageService {
|
||||||
if (imageVersionInsert == null) {
|
if (imageVersionInsert == null) {
|
||||||
throw new Exception("新增镜像版本失败");
|
throw new Exception("新增镜像版本失败");
|
||||||
}
|
}
|
||||||
// 使用CompletableFuture异步执行不同的镜像构建逻辑
|
// 使用CompletableFuture异步执行不同的镜像构建逻辑,在构建镜像的同时,更新数据库中的镜像版本状态
|
||||||
CompletableFuture.supplyAsync(() -> {
|
CompletableFuture.supplyAsync(() -> {
|
||||||
Map<String, String> resultMap = new HashMap<>();
|
Map<String, String> resultMap = new HashMap<>();
|
||||||
try {
|
try {
|
||||||
|
@ -281,6 +281,7 @@ public class ImageServiceImpl implements ImageService {
|
||||||
String pushCmd = "docker push " + imageUrl;
|
String pushCmd = "docker push " + imageUrl;
|
||||||
String sizeCmd = "docker inspect --format='{{.Size}}' " + imageUrl;
|
String sizeCmd = "docker inspect --format='{{.Size}}' " + imageUrl;
|
||||||
String s = k8sClientUtil.executeCommand(pod, tagCmd);
|
String s = k8sClientUtil.executeCommand(pod, tagCmd);
|
||||||
|
|
||||||
if (StringUtils.isNotEmpty(k8sClientUtil.executeCommand(pod, pushCmd))){
|
if (StringUtils.isNotEmpty(k8sClientUtil.executeCommand(pod, pushCmd))){
|
||||||
resultMap.put("url", imageUrl);
|
resultMap.put("url", imageUrl);
|
||||||
//得到镜像文件大小
|
//得到镜像文件大小
|
||||||
|
|
|
@ -1,10 +1,14 @@
|
||||||
package com.ruoyi.platform.service.impl;
|
package com.ruoyi.platform.service.impl;
|
||||||
|
|
||||||
import com.ruoyi.common.security.utils.SecurityUtils;
|
import com.ruoyi.common.security.utils.SecurityUtils;
|
||||||
|
import com.ruoyi.platform.annotations.CheckDuplicate;
|
||||||
|
import com.ruoyi.platform.domain.AssetIcon;
|
||||||
|
import com.ruoyi.platform.domain.Dataset;
|
||||||
import com.ruoyi.platform.domain.Models;
|
import com.ruoyi.platform.domain.Models;
|
||||||
import com.ruoyi.platform.domain.ModelsVersion;
|
import com.ruoyi.platform.domain.ModelsVersion;
|
||||||
import com.ruoyi.platform.mapper.ModelsDao;
|
import com.ruoyi.platform.mapper.ModelsDao;
|
||||||
import com.ruoyi.platform.mapper.ModelsVersionDao;
|
import com.ruoyi.platform.mapper.ModelsVersionDao;
|
||||||
|
import com.ruoyi.platform.service.AssetIconService;
|
||||||
import com.ruoyi.platform.service.MinioService;
|
import com.ruoyi.platform.service.MinioService;
|
||||||
import com.ruoyi.platform.service.ModelsService;
|
import com.ruoyi.platform.service.ModelsService;
|
||||||
import com.ruoyi.platform.service.ModelsVersionService;
|
import com.ruoyi.platform.service.ModelsVersionService;
|
||||||
|
@ -33,6 +37,7 @@ import javax.annotation.Resource;
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
@ -58,6 +63,9 @@ public class ModelsServiceImpl implements ModelsService {
|
||||||
@Resource
|
@Resource
|
||||||
private MinioService minioService;
|
private MinioService minioService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private AssetIconService assetIconService;
|
||||||
|
|
||||||
|
|
||||||
// 固定存储桶名
|
// 固定存储桶名
|
||||||
@Value("${minio.dataReleaseBucketName}")
|
@Value("${minio.dataReleaseBucketName}")
|
||||||
|
@ -74,7 +82,23 @@ public class ModelsServiceImpl implements ModelsService {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Models queryById(Integer id) {
|
public Models queryById(Integer id) {
|
||||||
return this.modelsDao.queryById(id);
|
Models models = this.modelsDao.queryById(id);
|
||||||
|
String modelType = models.getModelType();
|
||||||
|
String modelTag = models.getModelTag();
|
||||||
|
//去资产管理表中查询对应的图标名,注意判空逻辑,只有当dataType和dataTag不为空时,才进行查询
|
||||||
|
if(modelType != null && !modelType.isEmpty()){
|
||||||
|
AssetIcon modelTypeAssetIcon = assetIconService.queryById(Integer.valueOf(modelType));
|
||||||
|
if (modelTypeAssetIcon != null){
|
||||||
|
models.setModelTypeName(modelTypeAssetIcon.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(modelTag != null && !modelTag.isEmpty()){
|
||||||
|
AssetIcon modelTagAssetIcon = assetIconService.queryById(Integer.valueOf(modelTag));
|
||||||
|
if (modelTagAssetIcon != null){
|
||||||
|
models.setModelTagName(modelTagAssetIcon.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return models;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -97,8 +121,9 @@ public class ModelsServiceImpl implements ModelsService {
|
||||||
* @return 实例对象
|
* @return 实例对象
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Models insert(Models models) {
|
public Models insert(Models models) throws Exception {
|
||||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||||
|
checkDeclaredName(models);
|
||||||
models.setCreateBy(loginUser.getUsername());
|
models.setCreateBy(loginUser.getUsername());
|
||||||
models.setUpdateBy(loginUser.getUsername());
|
models.setUpdateBy(loginUser.getUsername());
|
||||||
models.setUpdateTime(new Date());
|
models.setUpdateTime(new Date());
|
||||||
|
@ -139,23 +164,24 @@ public class ModelsServiceImpl implements ModelsService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String removeById(Integer id) {
|
public String removeById(Integer id) throws Exception {
|
||||||
Models models = this.modelsDao.queryById(id);
|
Models models = this.modelsDao.queryById(id);
|
||||||
if (models == null){
|
if (models == null){
|
||||||
return "模型不存在";
|
throw new Exception("模型不存在");
|
||||||
}
|
}
|
||||||
|
|
||||||
//判断权限,只有admin和创建者本身可以删除该数据集
|
//判断权限,只有admin和创建者本身可以删除该模型
|
||||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||||
String username = loginUser.getUsername();
|
String username = loginUser.getUsername();
|
||||||
|
|
||||||
|
|
||||||
String createdBy = models.getCreateBy();
|
String createdBy = models.getCreateBy();
|
||||||
if (!(StringUtils.equals(username,"admin") || StringUtils.equals(username,createdBy))){
|
if (!(StringUtils.equals(username,"admin") || StringUtils.equals(username,createdBy))){
|
||||||
return "无权限删除该模型";
|
throw new Exception("无权限删除该模型");
|
||||||
}
|
}
|
||||||
if (modelsVersionService.queryByModelsId(id).size()>0){
|
//判断是否有版本文件
|
||||||
return "请先删除该模型的版本文件";
|
if (!modelsVersionService.queryByModelsId(id).isEmpty()){
|
||||||
|
throw new Exception("请先删除该模型下的版本文件");
|
||||||
}
|
}
|
||||||
models.setState(0);
|
models.setState(0);
|
||||||
return this.modelsDao.update(models)>0?"删除成功":"删除失败";
|
return this.modelsDao.update(models)>0?"删除成功":"删除失败";
|
||||||
|
@ -209,7 +235,6 @@ public class ModelsServiceImpl implements ModelsService {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public List<Map<String, String>> uploadModels(MultipartFile[] files, String uuid) throws Exception {
|
public List<Map<String, String>> uploadModels(MultipartFile[] files, String uuid) throws Exception {
|
||||||
|
|
||||||
List<Map<String, String>> results = new ArrayList<>();
|
List<Map<String, String>> results = new ArrayList<>();
|
||||||
for (MultipartFile file:files) {
|
for (MultipartFile file:files) {
|
||||||
// 构建objectName
|
// 构建objectName
|
||||||
|
@ -234,7 +259,6 @@ public class ModelsServiceImpl implements ModelsService {
|
||||||
|
|
||||||
ModelsVersion version = modelsVersionService.queryByModelsVersion(modelsVersion);
|
ModelsVersion version = modelsVersionService.queryByModelsVersion(modelsVersion);
|
||||||
|
|
||||||
|
|
||||||
String url = "";
|
String url = "";
|
||||||
if (version == null) {
|
if (version == null) {
|
||||||
//插表,因为这里是一次直接插表所以这里定掉date,然后用DAO插入
|
//插表,因为这里是一次直接插表所以这里定掉date,然后用DAO插入
|
||||||
|
@ -410,6 +434,31 @@ public class ModelsServiceImpl implements ModelsService {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void checkDeclaredName(Models insert) throws Exception {
|
||||||
|
Models existingModel = modelsDao.findByName(insert.getName());
|
||||||
|
if (existingModel != null) {
|
||||||
|
// Check if the found models is not the same as the one being inserted
|
||||||
|
// This is important if you are using this method for both insert and update operations
|
||||||
|
// You may need an identifier check here, e.g., if 'insert' has an ID and it's the same as 'existingDataset'
|
||||||
|
if (insert.getId() != null && insert.getId().equals(existingModel.getId())) {
|
||||||
|
// This is the same dataset, no duplicate name issue for update operation
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now we know there's another dataset with the same name
|
||||||
|
Field[] fields = Models.class.getDeclaredFields();
|
||||||
|
for (Field field : fields) {
|
||||||
|
field.setAccessible(true); // Make private fields accessible
|
||||||
|
if ("name".equals(field.getName()) && field.isAnnotationPresent(CheckDuplicate.class)) {
|
||||||
|
// If the field is 'name' and is marked with CheckDuplicate annotation
|
||||||
|
CheckDuplicate annotation = field.getAnnotation(CheckDuplicate.class);
|
||||||
|
throw new Exception("重复的模型名称: " + insert.getName() + ". " + annotation.message());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Map<String, String>> exportModels(String path, String uuid) throws Exception {
|
public List<Map<String, String>> exportModels(String path, String uuid) throws Exception {
|
||||||
List<Map<String, String>> results = new ArrayList<>();
|
List<Map<String, String>> results = new ArrayList<>();
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
from dataset
|
from dataset
|
||||||
where name = #{name} and state = 1 limit 1
|
where name = #{name} and state = 1 limit 1
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<!--查询指定行数据-->
|
<!--查询指定行数据-->
|
||||||
<select id="queryAllByLimit" resultMap="DatasetMap">
|
<select id="queryAllByLimit" resultMap="DatasetMap">
|
||||||
select
|
select
|
||||||
|
|
|
@ -24,6 +24,14 @@
|
||||||
where id = #{id} and state = 1
|
where id = #{id} and state = 1
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<!--查询单个-->
|
||||||
|
<select id="findByName" resultMap="ModelsMap">
|
||||||
|
select
|
||||||
|
id, name, description,available_range, model_type,model_tag, create_by, create_time, update_by, update_time, state
|
||||||
|
from models
|
||||||
|
where name = #{name} and state = 1 limit 1
|
||||||
|
</select>
|
||||||
|
|
||||||
<!--查询指定行数据-->
|
<!--查询指定行数据-->
|
||||||
<select id="queryAllByLimit" resultMap="ModelsMap">
|
<select id="queryAllByLimit" resultMap="ModelsMap">
|
||||||
select
|
select
|
||||||
|
|