| @@ -21,6 +21,7 @@ import './styles/menu.less'; | |||
| export { requestConfig as request } from './requestConfig'; | |||
| // const isDev = process.env.NODE_ENV === 'development'; | |||
| import { menuItemRender } from '@/utils/menuRender'; | |||
| import { gotoLoginPage } from './utils/ui'; | |||
| /** | |||
| * @see https://umijs.org/zh-CN/plugins/plugin-initial-state | |||
| * */ | |||
| @@ -45,7 +46,7 @@ export async function getInitialState(): Promise<{ | |||
| } as API.CurrentUser; | |||
| } catch (error) { | |||
| console.log(error); | |||
| history.push(PageEnum.LOGIN); | |||
| gotoLoginPage(); | |||
| } | |||
| return undefined; | |||
| }; | |||
| @@ -97,7 +98,7 @@ export const layout: RuntimeConfig['layout'] = ({ initialState }) => { | |||
| const { location } = history; | |||
| // 如果没有登录,重定向到 login | |||
| if (!initialState?.currentUser && location.pathname !== PageEnum.LOGIN) { | |||
| history.push(PageEnum.LOGIN); | |||
| gotoLoginPage(); | |||
| } | |||
| }, | |||
| layoutBgImgList: [ | |||
| @@ -1,7 +1,7 @@ | |||
| /* | |||
| * @Author: 赵伟 | |||
| * @Date: 2024-04-15 10:01:29 | |||
| * @Description: | |||
| * @Description: 自定义 hooks | |||
| */ | |||
| import { FormInstance } from 'antd'; | |||
| import { debounce } from 'lodash'; | |||
| @@ -126,3 +126,28 @@ export const useResetFormOnCloseModal = (form: FormInstance, open: boolean) => { | |||
| } | |||
| }, [form, prevOpen, open]); | |||
| }; | |||
| /** | |||
| * Executes the effect function when the specified condition is true. | |||
| * | |||
| * @param effect - The effect function to execute. | |||
| * @param deps - The dependencies for the effect. | |||
| * @param when - The condition to trigger the effect. | |||
| */ | |||
| export const useEffectWhen = (effect: () => void, deps: React.DependencyList, when: boolean) => { | |||
| const requestFns = useRef<(() => void)[]>([]); | |||
| useEffect(() => { | |||
| if (when) { | |||
| effect(); | |||
| } else { | |||
| requestFns.current.splice(0, 1, effect); | |||
| } | |||
| }, deps); | |||
| useEffect(() => { | |||
| if (when) { | |||
| const fn = requestFns.current.pop(); | |||
| fn?.(); | |||
| } | |||
| }, [when]); | |||
| }; | |||
| @@ -11,14 +11,21 @@ type ResourceIntroProps = { | |||
| resourceType: ResourceType; | |||
| }; | |||
| enum TabKeys { | |||
| Introduction = '1', | |||
| Version = '2', | |||
| Evolution = '3', | |||
| } | |||
| const ResourceIntro = ({ resourceType }: ResourceIntroProps) => { | |||
| const [info, setInfo] = useState<ResourceData>({} as ResourceData); | |||
| const locationParams = useParams(); | |||
| const [searchParams] = useSearchParams(); | |||
| const [versionList, setVersionList] = useState([]); | |||
| const [version, setVersion] = useState<string | undefined>(undefined); | |||
| const defaultTab = searchParams.get('tab') || '1'; | |||
| let versionParam = searchParams.get('version'); | |||
| const [versionList, setVersionList] = useState([]); | |||
| const [version, setVersion] = useState<string | undefined>(undefined); | |||
| const [activeTab, setActiveTab] = useState<string>(defaultTab); | |||
| const resourceId = Number(locationParams.id); | |||
| const typeName = resourceConfig[resourceType].name; // 数据集/模型 | |||
| @@ -67,7 +74,7 @@ const ResourceIntro = ({ resourceType }: ResourceIntroProps) => { | |||
| const items = [ | |||
| { | |||
| key: '1', | |||
| key: TabKeys.Introduction, | |||
| label: `${typeName}简介`, | |||
| children: ( | |||
| <> | |||
| @@ -77,7 +84,7 @@ const ResourceIntro = ({ resourceType }: ResourceIntroProps) => { | |||
| ), | |||
| }, | |||
| { | |||
| key: '2', | |||
| key: TabKeys.Version, | |||
| label: `${typeName}文件/版本`, | |||
| children: ( | |||
| <ResourceVersion | |||
| @@ -87,6 +94,7 @@ const ResourceIntro = ({ resourceType }: ResourceIntroProps) => { | |||
| isPublic={info.available_range === 1} | |||
| versionList={versionList} | |||
| version={version} | |||
| isActive={activeTab === TabKeys.Version} | |||
| getVersionList={getVersionList} | |||
| onVersionChange={handleVersionChange} | |||
| ></ResourceVersion> | |||
| @@ -96,7 +104,7 @@ const ResourceIntro = ({ resourceType }: ResourceIntroProps) => { | |||
| if (resourceType === ResourceType.Model) { | |||
| items.push({ | |||
| key: '3', | |||
| key: TabKeys.Evolution, | |||
| label: `模型演化`, | |||
| children: ( | |||
| <ModelEvolution | |||
| @@ -104,6 +112,7 @@ const ResourceIntro = ({ resourceType }: ResourceIntroProps) => { | |||
| resourceName={info.name} | |||
| versionList={versionList} | |||
| version={version} | |||
| isActive={activeTab === TabKeys.Evolution} | |||
| onVersionChange={handleVersionChange} | |||
| ></ModelEvolution> | |||
| ), | |||
| @@ -136,7 +145,7 @@ const ResourceIntro = ({ resourceType }: ResourceIntroProps) => { | |||
| </Flex> | |||
| </div> | |||
| <div className={styles['resource-intro__bottom']}> | |||
| <Tabs defaultActiveKey={defaultTab} items={items}></Tabs> | |||
| <Tabs activeKey={activeTab} items={items} onChange={(key) => setActiveTab(key)}></Tabs> | |||
| </div> | |||
| </div> | |||
| ); | |||
| @@ -1,14 +1,20 @@ | |||
| import CommonTableCell from '@/components/CommonTableCell'; | |||
| import DateTableCell from '@/components/DateTableCell'; | |||
| import KFIcon from '@/components/KFIcon'; | |||
| import { useEffectWhen } from '@/hooks'; | |||
| import AddVersionModal from '@/pages/Dataset/components/AddVersionModal'; | |||
| import { ResourceFileData, ResourceType, resourceConfig } from '@/pages/Dataset/config'; | |||
| import { | |||
| ResourceFileData, | |||
| ResourceType, | |||
| ResourceVersionData, | |||
| resourceConfig, | |||
| } from '@/pages/Dataset/config'; | |||
| import { downLoadZip } from '@/utils/downloadfile'; | |||
| import { openAntdModal } from '@/utils/modal'; | |||
| import { to } from '@/utils/promise'; | |||
| import { modalConfirm } from '@/utils/ui'; | |||
| import { App, Button, Flex, Select, Table } from 'antd'; | |||
| import { useEffect, useState } from 'react'; | |||
| import { useState } from 'react'; | |||
| import styles from './index.less'; | |||
| type ResourceVersionProps = { | |||
| @@ -16,8 +22,9 @@ type ResourceVersionProps = { | |||
| resourceId: number; | |||
| resourceName: string; | |||
| isPublic: boolean; | |||
| versionList: { label: string; value: string }[]; | |||
| versionList: ResourceVersionData[]; | |||
| version?: string; | |||
| isActive: boolean; | |||
| getVersionList: () => void; | |||
| onVersionChange: (version: string) => void; | |||
| }; | |||
| @@ -28,6 +35,7 @@ function ResourceVersion({ | |||
| isPublic, | |||
| versionList, | |||
| version, | |||
| isActive, | |||
| getVersionList, | |||
| onVersionChange, | |||
| }: ResourceVersionProps) { | |||
| @@ -35,13 +43,17 @@ function ResourceVersion({ | |||
| const { message } = App.useApp(); | |||
| // 获取版本文件列表 | |||
| useEffect(() => { | |||
| if (version) { | |||
| getFileList(version); | |||
| } else { | |||
| setFileList([]); | |||
| } | |||
| }, [resourceId, version]); | |||
| useEffectWhen( | |||
| () => { | |||
| if (version) { | |||
| getFileList(version); | |||
| } else { | |||
| setFileList([]); | |||
| } | |||
| }, | |||
| [resourceId, version], | |||
| isActive, | |||
| ); | |||
| // 获取版本下的文件列表 | |||
| const getFileList = async (version: string) => { | |||
| @@ -155,6 +155,12 @@ export type ResourceData = { | |||
| dataset_tag_name?: string; | |||
| }; | |||
| // 版本数据 | |||
| export type ResourceVersionData = { | |||
| label: string; | |||
| value: string; | |||
| }; | |||
| // 版本文件数据 | |||
| export type ResourceFileData = { | |||
| id: number; | |||
| @@ -16,7 +16,7 @@ function DatasetAnnotation() { | |||
| }; | |||
| return ( | |||
| <div className={styles.container}> | |||
| <iframe src={iframeUrl} className={styles.frame}></iframe> | |||
| {iframeUrl && <iframe src={iframeUrl} className={styles.frame}></iframe>} | |||
| </div> | |||
| ); | |||
| } | |||
| @@ -1,12 +1,13 @@ | |||
| import { useStateRef, useVisible } from '@/hooks'; | |||
| import { getExperimentIns } from '@/services/experiment/index.js'; | |||
| import { getWorkflowById } from '@/services/pipeline/index.js'; | |||
| import themes from '@/styles/theme.less'; | |||
| import { fittingString } from '@/utils'; | |||
| import { elapsedTime, formatDate } from '@/utils/date'; | |||
| import G6 from '@antv/g6'; | |||
| import { Button } from 'antd'; | |||
| import { useEffect, useRef } from 'react'; | |||
| import { useNavigate, useParams } from 'react-router-dom'; | |||
| import { s8 } from '../../../utils'; | |||
| import ParamsModal from '../components/ViewParamsModal'; | |||
| import { experimentStatusInfo } from '../status'; | |||
| import styles from './index.less'; | |||
| @@ -22,27 +23,22 @@ function ExperimentText() { | |||
| const [paramsModalOpen, openParamsModal, closeParamsModal] = useVisible(false); | |||
| const graphRef = useRef(); | |||
| const onDragEnd = (val) => { | |||
| console.log(val, 'eee'); | |||
| const _x = val.x; | |||
| const _y = val.y; | |||
| const point = graph.getPointByClient(_x, _y); | |||
| let model = {}; | |||
| // 元模型 | |||
| model = { | |||
| ...val, | |||
| x: point.x, | |||
| y: point.y, | |||
| id: val.component_name + '-' + s8(), | |||
| isCluster: false, | |||
| }; | |||
| graph.addItem('node', model, true); | |||
| }; | |||
| const handlerClick = (e) => { | |||
| if (e.target.get('name') !== 'anchor-point' && e.item) { | |||
| propsRef.current.showDrawer(e, locationParams.id, messageRef.current); | |||
| } | |||
| }; | |||
| // const onDragEnd = (val) => { | |||
| // console.log(val, 'eee'); | |||
| // const _x = val.x; | |||
| // const _y = val.y; | |||
| // const point = graph.getPointByClient(_x, _y); | |||
| // let model = {}; | |||
| // // 元模型 | |||
| // model = { | |||
| // ...val, | |||
| // x: point.x, | |||
| // y: point.y, | |||
| // id: val.component_name + '-' + s8(), | |||
| // isCluster: false, | |||
| // }; | |||
| // graph.addItem('node', model, true); | |||
| // }; | |||
| const getGraphData = (data) => { | |||
| if (graph) { | |||
| graph.data(data); | |||
| @@ -89,32 +85,6 @@ function ExperimentText() { | |||
| }, []); | |||
| const initGraph = () => { | |||
| const fittingString = (str, maxWidth, fontSize) => { | |||
| const ellipsis = '...'; | |||
| const ellipsisLength = G6.Util.getTextSize(ellipsis, fontSize)[0]; | |||
| let currentWidth = 0; | |||
| let res = str; | |||
| const pattern = new RegExp('[\u4E00-\u9FA5]+'); // distinguish the Chinese charactors and letters | |||
| str.split('').forEach((letter, i) => { | |||
| if (currentWidth > maxWidth - ellipsisLength) return; | |||
| if (pattern.test(letter)) { | |||
| // Chinese charactors | |||
| currentWidth += fontSize; | |||
| } else { | |||
| // get the width of single letter according to the fontSize | |||
| currentWidth += G6.Util.getLetterWidth(letter, fontSize); | |||
| } | |||
| if (currentWidth > maxWidth - ellipsisLength) { | |||
| res = `${str.substr(0, i)}${ellipsis}`; | |||
| } | |||
| }); | |||
| return res; | |||
| }; | |||
| // 获取文本的长度 | |||
| const getTextSize = (str, maxWidth, fontSize) => { | |||
| let width = G6.Util.getTextSize(str, fontSize)[0]; | |||
| return width > maxWidth ? maxWidth : width; | |||
| }; | |||
| G6.registerNode( | |||
| 'rect-node', | |||
| { | |||
| @@ -129,7 +99,6 @@ function ExperimentText() { | |||
| ); | |||
| }, | |||
| afterDraw(cfg, group) { | |||
| // console.log(group, cfg, 12312); | |||
| const image = group.addShape('image', { | |||
| attrs: { | |||
| x: -45, | |||
| @@ -158,7 +127,6 @@ function ExperimentText() { | |||
| } | |||
| const bbox = group.getBBox(); | |||
| const anchorPoints = this.getAnchorPoints(cfg); | |||
| // console.log(anchorPoints); | |||
| anchorPoints.forEach((anchorPos, i) => { | |||
| group.addShape('circle', { | |||
| attrs: { | |||
| @@ -179,19 +147,19 @@ function ExperimentText() { | |||
| // response the state changes and show/hide the link-point circles | |||
| setState(name, value, item) { | |||
| const anchorPoints = item | |||
| .getContainer() | |||
| .findAll((ele) => ele.get('name') === 'anchor-point'); | |||
| anchorPoints.forEach((point) => { | |||
| if (value || point.get('links') > 0) point.show(); | |||
| else point.hide(); | |||
| }); | |||
| // } | |||
| const group = item.getContainer(); | |||
| const shape = group.get('children')[0]; | |||
| if (name === 'hover') { | |||
| if (value) { | |||
| shape.attr('stroke', themes['primaryColor']); | |||
| } else { | |||
| shape.attr('stroke', '#fff'); | |||
| } | |||
| } | |||
| }, | |||
| }, | |||
| 'rect', | |||
| ); | |||
| console.log(graphRef, 'graphRef'); | |||
| graph = new G6.Graph({ | |||
| container: graphRef.current, | |||
| grid: true, | |||
| @@ -209,10 +177,6 @@ function ExperimentText() { | |||
| if (e.target.get('name') === 'anchor-point') return false; | |||
| return true; | |||
| }, | |||
| // shouldEnd: e => { | |||
| // console.log(e); | |||
| // return false; | |||
| // }, | |||
| }, | |||
| // config the shouldBegin and shouldEnd to make sure the create-edge is began and ended at anchor-point circles | |||
| 'drag-canvas', | |||
| @@ -237,7 +201,6 @@ function ExperimentText() { | |||
| style: { | |||
| fill: '#000', | |||
| fontSize: 10, | |||
| cursor: 'pointer', | |||
| x: -20, | |||
| y: 0, | |||
| @@ -252,17 +215,6 @@ function ExperimentText() { | |||
| lineWidth: 0.5, | |||
| }, | |||
| }, | |||
| nodeStateStyles: { | |||
| nodeSelected: { | |||
| fill: 'red', | |||
| shadowColor: 'red', | |||
| stroke: 'red', | |||
| 'text-shape': { | |||
| fill: 'red', | |||
| stroke: 'red', | |||
| }, | |||
| }, | |||
| }, | |||
| defaultEdge: { | |||
| // type: 'quadratic', | |||
| type: 'cubic-vertical', | |||
| @@ -308,15 +260,25 @@ function ExperimentText() { | |||
| // linkCenter: true, | |||
| fitView: true, | |||
| minZoom: 0.5, | |||
| maxZoom: 3, | |||
| fitViewPadding: [320, 320, 220, 320], | |||
| maxZoom: 5, | |||
| fitViewPadding: 300, | |||
| }); | |||
| graph.on('node:click', (e) => { | |||
| if (e.target.get('name') !== 'anchor-point' && e.item) { | |||
| propsRef.current.showDrawer(e, locationParams.id, messageRef.current); | |||
| } | |||
| }); | |||
| graph.on('node:mouseenter', (e) => { | |||
| graph.setItemState(e.item, 'hover', true); | |||
| }); | |||
| graph.on('node:mouseleave', (e) => { | |||
| graph.setItemState(e.item, 'hover', false); | |||
| }); | |||
| graph.on('node:click', handlerClick); | |||
| window.onresize = () => { | |||
| if (!graph || graph.get('destroyed')) return; | |||
| if (!graphRef.current || !graphRef.current.scrollWidth || !graphRef.current.scrollHeight) | |||
| return; | |||
| graph.changeSize(graphRef.current.scrollWidth, graphRef.current.scrollHeight - 20); | |||
| if (!graphRef.current) return; | |||
| graph.changeSize(graphRef.current.clientWidth, graphRef.current.clientHeight); | |||
| graph.fitView(); | |||
| }; | |||
| }; | |||
| return ( | |||
| @@ -1,3 +1,5 @@ | |||
| import { useEffectWhen } from '@/hooks'; | |||
| import { ResourceVersionData } from '@/pages/Dataset/config'; | |||
| import { getModelAtlasReq } from '@/services/dataset/index.js'; | |||
| import themes from '@/styles/theme.less'; | |||
| import { changePropertyName, fittingString } from '@/utils'; | |||
| @@ -19,10 +21,11 @@ import { useEffect, useRef, useState } from 'react'; | |||
| import GraphLegand from '../GraphLegand'; | |||
| import NodeTooltips from '../NodeTooltips'; | |||
| import styles from './index.less'; | |||
| const nodeWidth = 98; | |||
| const nodeHeight = 58; | |||
| const vGap = 30; | |||
| const hGap = 30; | |||
| const vGap = 58; | |||
| const hGap = 58; | |||
| enum NodeType { | |||
| current = 'current', | |||
| @@ -53,7 +56,18 @@ interface ProjectDependency extends NodeConfig { | |||
| model_type: NodeType; | |||
| } | |||
| export interface ModelDepsAPIData { | |||
| type ModalDetail = { | |||
| name: string; | |||
| available_range: number; | |||
| file_name: string; | |||
| file_size: string; | |||
| description: string; | |||
| model_type_name: string; | |||
| model_tag_name: string; | |||
| create_time: string; | |||
| }; | |||
| interface ModelDepsAPIData { | |||
| current_model_id: number; | |||
| version: string; | |||
| exp_ins_id: number; | |||
| @@ -63,11 +77,12 @@ export interface ModelDepsAPIData { | |||
| test_dataset: TrainDataset[]; | |||
| train_dataset: TrainDataset[]; | |||
| train_task: TrainTask; | |||
| model_version_dependcy_vo: ModalDetail; | |||
| children_models: ModelDepsAPIData[]; | |||
| parent_models: ModelDepsAPIData[]; | |||
| } | |||
| interface ModelDepsData extends Omit<ModelDepsAPIData, 'children_models'>, TreeGraphData { | |||
| export interface ModelDepsData extends Omit<ModelDepsAPIData, 'children_models'>, TreeGraphData { | |||
| children: ModelDepsData[]; | |||
| } | |||
| @@ -75,10 +90,10 @@ interface ModelDepsData extends Omit<ModelDepsAPIData, 'children_models'>, TreeG | |||
| function normalizeChildren(data: ModelDepsData[]) { | |||
| if (Array.isArray(data)) { | |||
| data.forEach((item) => { | |||
| item.model_type = NodeType.children; | |||
| item.id = `$M_${item.current_model_id}_${item.version}`; | |||
| item.label = getLabel(item); | |||
| item.style = getStyle(NodeType.children); | |||
| item.model_type = NodeType.children; | |||
| normalizeChildren(item.children); | |||
| }); | |||
| } | |||
| @@ -107,7 +122,7 @@ function getStyle(model_type: NodeType) { | |||
| fill = '#b7cfff'; | |||
| break; | |||
| case NodeType.project: | |||
| fill = '#0000ff'; | |||
| fill = '#FA8C16'; | |||
| break; | |||
| case NodeType.trainDataset: | |||
| fill = '#ff0000'; | |||
| @@ -131,11 +146,12 @@ function normalizeTreeData(apiData: ModelDepsAPIData, currentNodeName: string): | |||
| }) as ModelDepsData; | |||
| // 设置当前模型的数据 | |||
| normalizedData.label = getLabel(normalizedData); | |||
| normalizedData.id = `$M_${normalizedData.current_model_id}_${normalizedData.version}`; | |||
| normalizedData.style = getStyle(NodeType.current); | |||
| normalizedData.model_type = NodeType.current; | |||
| normalizedData.current_model_name = currentNodeName; | |||
| normalizedData.id = `$M_${normalizedData.current_model_id}_${normalizedData.version}`; | |||
| normalizedData.label = getLabel(normalizedData); | |||
| normalizedData.style = getStyle(NodeType.current); | |||
| normalizeChildren(normalizedData.children as ModelDepsData[]); | |||
| // 将 parent_models 转换成树形结构 | |||
| @@ -144,8 +160,8 @@ function normalizeTreeData(apiData: ModelDepsAPIData, currentNodeName: string): | |||
| const parent = parent_models[0]; | |||
| normalizedData = { | |||
| ...parent, | |||
| id: `$M_${parent.current_model_id}_${parent.version}`, | |||
| model_type: NodeType.parent, | |||
| id: `$M_${parent.current_model_id}_${parent.version}`, | |||
| label: getLabel(parent), | |||
| style: getStyle(NodeType.parent), | |||
| children: [ | |||
| @@ -166,8 +182,8 @@ function getGraphData(data: ModelDepsData): GraphData { | |||
| direction: 'LR', | |||
| getHeight: () => nodeHeight, | |||
| getWidth: () => nodeWidth, | |||
| getVGap: () => vGap, | |||
| getHGap: () => hGap, | |||
| getVGap: () => vGap / 2, | |||
| getHGap: () => hGap / 2, | |||
| }; | |||
| // 树形布局计算出坐标 | |||
| @@ -210,8 +226,8 @@ function getGraphData(data: ModelDepsData): GraphData { | |||
| const len = train_dataset.length + test_dataset.length; | |||
| [...train_dataset, ...test_dataset].forEach((item, index) => { | |||
| const half = len / 2 - 0.5; | |||
| item.x = node.x! - (half - index) * (nodeWidth + 30); | |||
| item.y = node.y! - nodeHeight - 30; | |||
| item.x = node.x! - (half - index) * (nodeWidth + hGap); | |||
| item.y = node.y! - nodeHeight - vGap; | |||
| nodes.push(item); | |||
| edges.push({ | |||
| source: node.id, | |||
| @@ -222,7 +238,7 @@ function getGraphData(data: ModelDepsData): GraphData { | |||
| }); | |||
| }); | |||
| if (project_dependency.url) { | |||
| if (project_dependency?.url) { | |||
| project_dependency.id = `$P_${project_dependency.url}`; | |||
| project_dependency.model_type = NodeType.project; | |||
| project_dependency.type = 'rect'; | |||
| @@ -230,7 +246,7 @@ function getGraphData(data: ModelDepsData): GraphData { | |||
| project_dependency.label = fittingString(project_dependency.name, 48, 8); | |||
| project_dependency.style = getStyle(NodeType.project); | |||
| project_dependency.x = node.x; | |||
| project_dependency.y = node.y! + nodeHeight + 30; | |||
| project_dependency.y = node.y! + nodeHeight + vGap; | |||
| nodes.push(project_dependency); | |||
| edges.push({ | |||
| source: node.id, | |||
| @@ -248,8 +264,9 @@ function getGraphData(data: ModelDepsData): GraphData { | |||
| type modeModelEvolutionProps = { | |||
| resourceId: number; | |||
| resourceName: string; | |||
| versionList: { label: string; value: string }[]; | |||
| versionList: ResourceVersionData[]; | |||
| version?: string; | |||
| isActive: boolean; | |||
| onVersionChange: (version: string) => void; | |||
| }; | |||
| @@ -259,6 +276,7 @@ function ModelEvolution({ | |||
| resourceName, | |||
| versionList, | |||
| version, | |||
| isActive, | |||
| onVersionChange, | |||
| }: modeModelEvolutionProps) { | |||
| const graphRef = useRef<HTMLDivElement>(null); | |||
| @@ -283,18 +301,17 @@ function ModelEvolution({ | |||
| }; | |||
| }, []); | |||
| useEffect(() => { | |||
| if (version) { | |||
| getModelAtlas(); | |||
| } else { | |||
| graph.data({ | |||
| nodes: [], | |||
| edges: [], | |||
| }); | |||
| graph.render(); | |||
| graph.fitView(); | |||
| } | |||
| }, [resourceId, version]); | |||
| useEffectWhen( | |||
| () => { | |||
| if (version) { | |||
| getModelAtlas(); | |||
| } else { | |||
| clearGraphData(); | |||
| } | |||
| }, | |||
| [resourceId, version], | |||
| isActive, | |||
| ); | |||
| // 初始化图 | |||
| const initGraph = () => { | |||
| @@ -302,7 +319,6 @@ function ModelEvolution({ | |||
| container: graphRef.current!, | |||
| width: graphRef.current!.clientWidth, | |||
| height: graphRef.current!.clientHeight, | |||
| // animate: false, | |||
| fitView: true, | |||
| fitViewPadding: [50, 100, 50, 100], | |||
| minZoom: 0.5, | |||
| @@ -380,10 +396,14 @@ function ModelEvolution({ | |||
| if (point.x + 300 > canvasWidth) { | |||
| point.x = canvasWidth - 300; | |||
| } | |||
| const zoom = graph.getZoom(); | |||
| // 更加缩放,调整 tooltip 位置 | |||
| const offsetY = (nodeHeight * zoom) / 4; | |||
| setHoverNodeData(model as ModelDepsData); | |||
| setHoverNodeData(model); | |||
| setNodeToolTipX(point.x); | |||
| setNodeToolTipY(point.y - 240); | |||
| // 92: 版本选择器的高度,296: tooltip的高度 | |||
| setNodeToolTipY(point.y + 92 - 296 - offsetY); | |||
| setShowNodeTooltip(true); | |||
| }); | |||
| @@ -395,16 +415,15 @@ function ModelEvolution({ | |||
| graph.on('node:click', (e: G6GraphEvent) => { | |||
| const nodeItem = e.item; | |||
| const model = nodeItem.getModel() as ModelDepsChildren; | |||
| const model = nodeItem.getModel(); | |||
| const { model_type } = model; | |||
| const { origin } = location; | |||
| let url: string = ''; | |||
| switch (model_type) { | |||
| case NodeType.children: | |||
| case NodeType.current: | |||
| case NodeType.parent: { | |||
| const { current_model_id, version } = model as ModelDepsData; | |||
| url = `${origin}/dataset/model/${current_model_id}?isPublic=true&tab=3&version=${version}`; | |||
| url = `${origin}/dataset/model/${current_model_id}?tab=3&version=${version}`; | |||
| break; | |||
| } | |||
| case NodeType.project: { | |||
| @@ -415,7 +434,7 @@ function ModelEvolution({ | |||
| case NodeType.trainDataset: | |||
| case NodeType.testDataset: { | |||
| const { dataset_id, dataset_version } = model as TrainDataset; | |||
| url = `${origin}/dataset/dataset/${dataset_id}?isPublic=true&tab=2&version=${dataset_version}`; | |||
| url = `${origin}/dataset/dataset/${dataset_id}?tab=2&version=${dataset_version}`; | |||
| break; | |||
| } | |||
| default: | |||
| @@ -426,6 +445,12 @@ function ModelEvolution({ | |||
| window.open(url, '_blank'); | |||
| } | |||
| }); | |||
| // 鼠标滚轮缩放时,隐藏 tooltip | |||
| graph.on('wheelzoom', () => { | |||
| setShowNodeTooltip(false); | |||
| setEnterTooltip(false); | |||
| }); | |||
| }; | |||
| const handleTooltipsMouseEnter = () => { | |||
| @@ -450,9 +475,21 @@ function ModelEvolution({ | |||
| graph.data(graphData); | |||
| graph.render(); | |||
| graph.fitView(); | |||
| } else { | |||
| clearGraphData(); | |||
| } | |||
| }; | |||
| // 请求失败或者版本不存在时,清除图形 | |||
| function clearGraphData() { | |||
| graph.data({ | |||
| nodes: [], | |||
| edges: [], | |||
| }); | |||
| graph.render(); | |||
| graph.fitView(); | |||
| } | |||
| return ( | |||
| <div className={styles['model-evolution']}> | |||
| <Flex align="center" className={styles['model-evolution__top']}> | |||
| @@ -1,5 +1,4 @@ | |||
| import { useNavigate } from '@umijs/max'; | |||
| import { useEffect } from 'react'; | |||
| import { formatDate } from '@/utils/date'; | |||
| import { ModelDepsData } from '../ModelEvolution'; | |||
| import styles from './index.less'; | |||
| @@ -12,12 +11,10 @@ type NodeTooltipsProps = { | |||
| }; | |||
| function NodeTooltips({ data, x, y, onMouseEnter, onMouseLeave }: NodeTooltipsProps) { | |||
| const navigate = useNavigate(); | |||
| useEffect(() => {}, []); | |||
| const gotoExperimentPage = () => { | |||
| if (data.train_task?.ins_id) { | |||
| navigate(`/pipeline/experiment/144/${data.train_task.ins_id}`); | |||
| const { origin } = location; | |||
| window.open(`${origin}/pipeline/experiment/144/${data.train_task.ins_id}`, '_blank'); | |||
| } | |||
| }; | |||
| @@ -35,24 +32,32 @@ function NodeTooltips({ data, x, y, onMouseEnter, onMouseLeave }: NodeTooltipsPr | |||
| <span className={styles['node-tooltips__row__value']}>{data.current_model_name}</span> | |||
| </div> | |||
| <div className={styles['node-tooltips__row']}> | |||
| <span className={styles['node-tooltips__row__title']}>版本:</span> | |||
| <span className={styles['node-tooltips__row__title']}>模型版本:</span> | |||
| <span className={styles['node-tooltips__row__value']}>{data.version}</span> | |||
| </div> | |||
| <div className={styles['node-tooltips__row']}> | |||
| <span className={styles['node-tooltips__row__title']}>模型框架:</span> | |||
| <span className={styles['node-tooltips__row__value']}>{data.version}</span> | |||
| <span className={styles['node-tooltips__row__value']}> | |||
| {data.model_version_dependcy_vo?.model_type_name || '--'} | |||
| </span> | |||
| </div> | |||
| <div className={styles['node-tooltips__row']}> | |||
| <span className={styles['node-tooltips__row__title']}>模型大小:</span> | |||
| <span className={styles['node-tooltips__row__value']}>{data.version}</span> | |||
| <span className={styles['node-tooltips__row__value']}> | |||
| {data.model_version_dependcy_vo?.file_size || '--'} | |||
| </span> | |||
| </div> | |||
| <div className={styles['node-tooltips__row']}> | |||
| <span className={styles['node-tooltips__row__title']}>创建时间:</span> | |||
| <span className={styles['node-tooltips__row__value']}>{data.version}</span> | |||
| <span className={styles['node-tooltips__row__value']}> | |||
| {formatDate(data.model_version_dependcy_vo?.create_time)} | |||
| </span> | |||
| </div> | |||
| <div className={styles['node-tooltips__row']}> | |||
| <span className={styles['node-tooltips__row__title']}>模型权限:</span> | |||
| <span className={styles['node-tooltips__row__value']}>{data.version}</span> | |||
| <span className={styles['node-tooltips__row__value']}> | |||
| {data.model_version_dependcy_vo?.available_range === 1 ? '公开' : '私有'} | |||
| </span> | |||
| </div> | |||
| </div> | |||
| <div className={styles['node-tooltips__title']}>训练相关信息</div> | |||
| @@ -1,6 +1,8 @@ | |||
| import KFIcon from '@/components/KFIcon'; | |||
| import { useStateRef, useVisible } from '@/hooks'; | |||
| import { getWorkflowById, saveWorkflow } from '@/services/pipeline/index.js'; | |||
| import themes from '@/styles/theme.less'; | |||
| import { fittingString } from '@/utils'; | |||
| import { to } from '@/utils/promise'; | |||
| import G6 from '@antv/g6'; | |||
| import { App, Button } from 'antd'; | |||
| @@ -27,6 +29,11 @@ const EditPipeline = () => { | |||
| const { message } = App.useApp(); | |||
| let sourceAnchorIdx, targetAnchorIdx; | |||
| useEffect(() => { | |||
| initMenu(); | |||
| getFirstWorkflow(locationParams.id); | |||
| }, []); | |||
| const onDragEnd = (val) => { | |||
| console.log(val); | |||
| const _x = val.x; | |||
| @@ -103,20 +110,8 @@ const EditPipeline = () => { | |||
| }); | |||
| }, 500); | |||
| }; | |||
| const handlerClick = (e) => { | |||
| e.stopPropagation(); | |||
| if (e.target.get('name') !== 'anchor-point' && e.item) { | |||
| graph.setItemState(e.item, 'nodeClicked', true); | |||
| const parentNodes = findAllParentNodes(graph, e.item); | |||
| // 如果没有打开过全局参数抽屉,获取不到全局参数 | |||
| const globalParams = | |||
| paramsDrawerRef.current.getFieldsValue().global_param || globalParamRef.current; | |||
| propsRef.current.showDrawer(e, globalParams, parentNodes); | |||
| } | |||
| }; | |||
| const getGraphData = (data) => { | |||
| if (graph) { | |||
| console.log(data); | |||
| graph.data(data); | |||
| graph.render(); | |||
| } else { | |||
| @@ -312,49 +307,8 @@ const EditPipeline = () => { | |||
| initGraph(); | |||
| }; | |||
| useEffect(() => { | |||
| initMenu(); | |||
| getFirstWorkflow(locationParams.id); | |||
| return () => { | |||
| graph.off('node:mouseenter', (e) => { | |||
| graph.setItemState(e.item, 'showAnchors', true); | |||
| graph.setItemState(e.item, 'nodeSelected', true); | |||
| }); | |||
| graph.off('node:mouseleave', (e) => { | |||
| // this.graph.setItemState(e.item, 'showAnchors', false); | |||
| graph.setItemState(e.item, 'nodeSelected', false); | |||
| }); | |||
| // graph.off('dblclick', handlerClick); | |||
| }; | |||
| }, []); | |||
| const initGraph = () => { | |||
| const fittingString = (str, maxWidth, fontSize) => { | |||
| const ellipsis = '...'; | |||
| const ellipsisLength = G6.Util.getTextSize(ellipsis, fontSize)[0]; | |||
| let currentWidth = 0; | |||
| let res = str; | |||
| const pattern = new RegExp('[\u4E00-\u9FA5]+'); // distinguish the Chinese charactors and letters | |||
| str.split('').forEach((letter, i) => { | |||
| if (currentWidth > maxWidth - ellipsisLength) return; | |||
| if (pattern.test(letter)) { | |||
| // Chinese charactors | |||
| currentWidth += fontSize; | |||
| } else { | |||
| // get the width of single letter according to the fontSize | |||
| currentWidth += G6.Util.getLetterWidth(letter, fontSize); | |||
| } | |||
| if (currentWidth > maxWidth - ellipsisLength) { | |||
| res = `${str.substr(0, i)}${ellipsis}`; | |||
| } | |||
| }); | |||
| return res; | |||
| }; | |||
| // 获取文本的长度 | |||
| const getTextSize = (str, maxWidth, fontSize) => { | |||
| let width = G6.Util.getTextSize(str, fontSize)[0]; | |||
| return width > maxWidth ? maxWidth : width; | |||
| }; | |||
| G6.registerNode( | |||
| 'rect-node', | |||
| { | |||
| @@ -407,6 +361,7 @@ const EditPipeline = () => { | |||
| y: bbox.y + bbox.height * anchorPos[1], | |||
| fill: '#fff', | |||
| stroke: '#a4a4a5', | |||
| cursor: 'crosshair', | |||
| }, | |||
| name: `anchor-point`, // the name, for searching by group.find(ele => ele.get('name') === 'anchor-point') | |||
| anchorPointIdx: i, // flag the idx of the anchor-point circle | |||
| @@ -420,14 +375,30 @@ const EditPipeline = () => { | |||
| // response the state changes and show/hide the link-point circles | |||
| setState(name, value, item) { | |||
| const anchorPoints = item | |||
| .getContainer() | |||
| .findAll((ele) => ele.get('name') === 'anchor-point'); | |||
| anchorPoints.forEach((point) => { | |||
| if (value || point.get('links') > 0) point.show(); | |||
| else point.hide(); | |||
| }); | |||
| // } | |||
| // const anchorPoints = item | |||
| // .getContainer() | |||
| // .findAll((ele) => ele.get('name') === 'anchor-point'); | |||
| // anchorPoints.forEach((point) => { | |||
| // if (value || point.get('links') > 0) point.show(); | |||
| // else point.hide(); | |||
| // }); | |||
| const group = item.getContainer(); | |||
| const shape = group.get('children')[0]; | |||
| const anchorPoints = group.findAll((ele) => ele.get('name') === 'anchor-point'); | |||
| if (name === 'hover') { | |||
| if (value) { | |||
| shape.attr('stroke', themes['primaryColor']); | |||
| anchorPoints.forEach((point) => { | |||
| point.show(); | |||
| }); | |||
| } else { | |||
| shape.attr('stroke', '#fff'); | |||
| anchorPoints.forEach((point) => { | |||
| point.hide(); | |||
| }); | |||
| } | |||
| } | |||
| }, | |||
| }, | |||
| 'rect', | |||
| @@ -435,7 +406,6 @@ const EditPipeline = () => { | |||
| graph = new G6.Graph({ | |||
| container: graphRef.current, | |||
| grid: true, | |||
| width: graphRef.current.clientWidth || 500, | |||
| height: graphRef.current.clientHeight || '100%', | |||
| animate: false, | |||
| @@ -519,20 +489,8 @@ const EditPipeline = () => { | |||
| lineWidth: 0.5, | |||
| }, | |||
| }, | |||
| nodeStateStyles: { | |||
| nodeSelected: { | |||
| fill: 'red', | |||
| shadowColor: 'red', | |||
| stroke: 'red', | |||
| 'text-shape': { | |||
| fill: 'red', | |||
| stroke: 'red', | |||
| }, | |||
| }, | |||
| }, | |||
| defaultEdge: { | |||
| // type: 'quadratic', | |||
| // type: 'cubic-vertical', | |||
| //type: 'cubic-vertical', | |||
| style: { | |||
| endArrow: { | |||
| @@ -575,17 +533,20 @@ const EditPipeline = () => { | |||
| // linkCenter: true, | |||
| fitView: true, | |||
| minZoom: 0.5, | |||
| maxZoom: 3, | |||
| fitViewPadding: [320, 320, 220, 320], | |||
| maxZoom: 5, | |||
| fitViewPadding: 300, | |||
| }); | |||
| graph.on('node:click', (e) => { | |||
| e.stopPropagation(); | |||
| if (e.target.get('name') !== 'anchor-point' && e.item) { | |||
| // graph.setItemState(e.item, 'nodeClicked', true); | |||
| const parentNodes = findAllParentNodes(graph, e.item); | |||
| // 如果没有打开过全局参数抽屉,获取不到全局参数 | |||
| const globalParams = | |||
| paramsDrawerRef.current.getFieldsValue().global_param || globalParamRef.current; | |||
| propsRef.current.showDrawer(e, globalParams, parentNodes); | |||
| } | |||
| }); | |||
| // graph.on('dblclick', (e) => { | |||
| // console.log(e.item); | |||
| // if (e.item) { | |||
| // graph.setItemState(e.item, 'nodeClicked', true); | |||
| // handlerClick(e); | |||
| // } | |||
| // }); | |||
| graph.on('node:click', handlerClick); | |||
| graph.on('aftercreateedge', (e) => { | |||
| // update the sourceAnchor and targetAnchor for the newly added edge | |||
| graph.updateItem(e.edge, { | |||
| @@ -603,59 +564,6 @@ const EditPipeline = () => { | |||
| }); | |||
| }); | |||
| }); | |||
| graph.on('node:mouseenter', (e) => { | |||
| // this.graph.setItemState(e.item, 'showAnchors', true); | |||
| graph.setItemState(e.item, 'nodeSelected', true); | |||
| graph.updateItem(e.item, { | |||
| // 节点的样式 | |||
| style: { | |||
| stroke: '#1664ff', | |||
| }, | |||
| }); | |||
| }); | |||
| graph.on('node:mouseleave', (e) => { | |||
| // this.graph.setItemState(e.item, 'showAnchors', false); | |||
| graph.setItemState(e.item, 'nodeSelected', false); | |||
| graph.updateItem(e.item, { | |||
| // 节点的样式 | |||
| style: { | |||
| stroke: 'transparent', | |||
| }, | |||
| }); | |||
| }); | |||
| 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) => { | |||
| if (e.item && e.item.source && e.item.target) { | |||
| const sourceNode = graph.findById(e.item.source); | |||
| @@ -681,7 +589,6 @@ const EditPipeline = () => { | |||
| } | |||
| } | |||
| }); | |||
| // after clicking on the first node, the edge is created, update the sourceAnchor | |||
| graph.on('afteradditem', (e) => { | |||
| if (e.item && e.item.getType() === 'edge') { | |||
| @@ -690,11 +597,29 @@ const EditPipeline = () => { | |||
| }); | |||
| } | |||
| }); | |||
| graph.on('node:mouseenter', (e) => { | |||
| graph.setItemState(e.item, 'hover', true); | |||
| }); | |||
| graph.on('node:mouseleave', (e) => { | |||
| graph.setItemState(e.item, 'hover', false); | |||
| }); | |||
| graph.on('node:dragenter', (e) => { | |||
| graph.setItemState(e.item, 'hover', true); | |||
| }); | |||
| graph.on('node:dragleave', (e) => { | |||
| graph.setItemState(e.item, 'hover', false); | |||
| }); | |||
| graph.on('node:dragstart', (e) => { | |||
| graph.setItemState(e.item, 'hover', true); | |||
| }); | |||
| graph.on('node:drag', (e) => { | |||
| graph.setItemState(e.item, 'hover', true); | |||
| }); | |||
| window.onresize = () => { | |||
| if (!graph || graph.get('destroyed')) return; | |||
| if (!graphRef.current || !graphRef.current.scrollWidth || !graphRef.current.scrollHeight) | |||
| return; | |||
| graph.changeSize(graphRef.current.scrollWidth, graphRef.current.scrollHeight - 20); | |||
| if (!graphRef.current) return; | |||
| graph.changeSize(graphRef.current.clientWidth, graphRef.current.clientHeight); | |||
| graph.fitView(); | |||
| }; | |||
| }; | |||
| return ( | |||
| @@ -50,16 +50,18 @@ export const getFileListFromEvent = (e: any) => { | |||
| }); | |||
| }; | |||
| // 去登录页面 | |||
| /** | |||
| * 跳转到登录页 | |||
| * @param toHome 是否跳转到首页 | |||
| */ | |||
| export const gotoLoginPage = (toHome: boolean = true) => { | |||
| const { pathname, search } = window.location; | |||
| const { pathname, search } = location; | |||
| const urlParams = new URLSearchParams(); | |||
| urlParams.append('redirect', pathname + search); | |||
| const newSearch = | |||
| toHome && pathname !== PageEnum.LOGIN && pathname !== '/' ? '' : urlParams.toString(); | |||
| console.log('pathname', pathname); | |||
| console.log('search', search); | |||
| if (window.location.pathname !== PageEnum.LOGIN) { | |||
| const newSearch = toHome && pathname !== '/' ? '' : urlParams.toString(); | |||
| // console.log('pathname', pathname); | |||
| // console.log('search', search); | |||
| if (pathname !== PageEnum.LOGIN) { | |||
| closeAllModals(); | |||
| removeAllPageCacheState(); | |||
| history.replace({ | |||
| @@ -0,0 +1,90 @@ | |||
| package com.ruoyi.platform.controller.devEnvironment; | |||
| import com.ruoyi.common.core.web.controller.BaseController; | |||
| import com.ruoyi.common.core.web.domain.GenericsAjaxResult; | |||
| import com.ruoyi.platform.domain.DevEnvironment; | |||
| import com.ruoyi.platform.service.DevEnvironmentService; | |||
| import io.swagger.annotations.Api; | |||
| import org.springframework.data.domain.Page; | |||
| import org.springframework.data.domain.PageRequest; | |||
| import org.springframework.http.ResponseEntity; | |||
| import org.springframework.web.bind.annotation.*; | |||
| import javax.annotation.Resource; | |||
| /** | |||
| * (DevEnvironment)表控制层 | |||
| * | |||
| * @author Xidaray | |||
| * @since 2024-06-03 15:17:37 | |||
| */ | |||
| @RestController | |||
| @RequestMapping("devEnvironment") | |||
| @Api("开发环境管理") | |||
| public class DevEnvironmentController extends BaseController { | |||
| /** | |||
| * 服务对象 | |||
| */ | |||
| @Resource | |||
| private DevEnvironmentService devEnvironmentService; | |||
| /** | |||
| * 分页查询 | |||
| * | |||
| * @param devEnvironment 筛选条件 | |||
| * @param page 页数 | |||
| * @param size 每页大小 | |||
| * @return 查询结果 | |||
| */ | |||
| @GetMapping | |||
| public GenericsAjaxResult<Page<DevEnvironment>> queryByPage(DevEnvironment devEnvironment, int page, int size) { | |||
| PageRequest pageRequest = PageRequest.of(page,size); | |||
| return genericsSuccess(this.devEnvironmentService.queryByPage(devEnvironment, pageRequest)); | |||
| } | |||
| /** | |||
| * 通过主键查询单条数据 | |||
| * | |||
| * @param id 主键 | |||
| * @return 单条数据 | |||
| */ | |||
| @GetMapping("{id}") | |||
| public ResponseEntity<DevEnvironment> queryById(@PathVariable("id") Integer id) { | |||
| return ResponseEntity.ok(this.devEnvironmentService.queryById(id)); | |||
| } | |||
| /** | |||
| * 新增数据 | |||
| * | |||
| * @param devEnvironment 实体 | |||
| * @return 新增结果 | |||
| */ | |||
| @PostMapping | |||
| public ResponseEntity<DevEnvironment> add(@RequestBody DevEnvironment devEnvironment) { | |||
| return ResponseEntity.ok(this.devEnvironmentService.insert(devEnvironment)); | |||
| } | |||
| /** | |||
| * 编辑数据 | |||
| * | |||
| * @param devEnvironment 实体 | |||
| * @return 编辑结果 | |||
| */ | |||
| @PutMapping | |||
| public ResponseEntity<DevEnvironment> edit(@RequestBody DevEnvironment devEnvironment) { | |||
| return ResponseEntity.ok(this.devEnvironmentService.update(devEnvironment)); | |||
| } | |||
| /** | |||
| * 删除数据 | |||
| * | |||
| * @param id 主键 | |||
| * @return 删除是否成功 | |||
| */ | |||
| @DeleteMapping("{id}") | |||
| public ResponseEntity<String> deleteById(@PathVariable("id") Integer id) { | |||
| return ResponseEntity.ok(this.devEnvironmentService.removeById(id)); | |||
| } | |||
| } | |||
| @@ -91,7 +91,7 @@ public class ExperimentController extends BaseController { | |||
| */ | |||
| @PutMapping | |||
| @ApiOperation("编辑实验") | |||
| public GenericsAjaxResult<Experiment> edit(@RequestBody Experiment experiment) throws IOException { | |||
| public GenericsAjaxResult<Experiment> edit(@RequestBody Experiment experiment) throws Exception { | |||
| return genericsSuccess(this.experimentService.update(experiment)); | |||
| } | |||
| @@ -4,11 +4,11 @@ import com.ruoyi.common.core.web.controller.BaseController; | |||
| import com.ruoyi.common.core.web.domain.AjaxResult; | |||
| import com.ruoyi.common.core.web.domain.GenericsAjaxResult; | |||
| import com.ruoyi.platform.service.JupyterService; | |||
| import com.ruoyi.platform.vo.FrameLogPathVo; | |||
| import io.swagger.annotations.Api; | |||
| import io.swagger.annotations.ApiOperation; | |||
| import org.springframework.web.bind.annotation.GetMapping; | |||
| import org.springframework.web.bind.annotation.RequestMapping; | |||
| import org.springframework.web.bind.annotation.RestController; | |||
| import io.swagger.v3.oas.annotations.responses.ApiResponse; | |||
| import org.springframework.web.bind.annotation.*; | |||
| import javax.annotation.Resource; | |||
| import java.io.File; | |||
| @@ -28,6 +28,35 @@ public class JupyterController extends BaseController { | |||
| return genericsSuccess(jupyterService.getJupyterServiceUrl()); | |||
| } | |||
| /** | |||
| * 启动jupyter容器接口 | |||
| * | |||
| * @param id 开发环境配置id | |||
| * @return url | |||
| */ | |||
| @PostMapping("/run/{id}") | |||
| @ApiOperation("根据开发环境id启动jupyter pod") | |||
| @ApiResponse | |||
| public GenericsAjaxResult<String> runJupyter(@PathVariable("id") Integer id) throws Exception { | |||
| return genericsSuccess(this.jupyterService.runJupyterService(id)); | |||
| } | |||
| /** | |||
| * 停止jupyter容器接口 | |||
| * | |||
| * @param id 开发环境配置id | |||
| * @return 操作结果 | |||
| */ | |||
| @DeleteMapping("/stop/{id}") | |||
| @ApiOperation("根据开发环境id停止jupyter pod") | |||
| @ApiResponse | |||
| public GenericsAjaxResult<String> stopJupyter(@PathVariable("id") Integer id) throws Exception { | |||
| return genericsSuccess(this.jupyterService.stopJupyterService(id)); | |||
| } | |||
| @GetMapping(value = "/upload") | |||
| public AjaxResult upload() throws Exception { | |||
| File file = new File("D://nexus-deploy.yaml"); | |||
| @@ -0,0 +1,115 @@ | |||
| package com.ruoyi.platform.controller.model; | |||
| import com.ruoyi.common.core.web.controller.BaseController; | |||
| import com.ruoyi.common.core.web.domain.GenericsAjaxResult; | |||
| import com.ruoyi.platform.domain.ModelDependency; | |||
| import com.ruoyi.platform.domain.ModelsVersion; | |||
| import com.ruoyi.platform.service.ModelDependencyService; | |||
| import com.ruoyi.platform.vo.ModelDependcyTreeVo; | |||
| import io.swagger.annotations.ApiOperation; | |||
| import org.springframework.data.domain.Page; | |||
| import org.springframework.data.domain.PageRequest; | |||
| import org.springframework.http.ResponseEntity; | |||
| import org.springframework.web.bind.annotation.*; | |||
| import javax.annotation.Resource; | |||
| import java.io.IOException; | |||
| import java.util.List; | |||
| /** | |||
| * (ModelDependency)表控制层 | |||
| * | |||
| * @author Xidaray | |||
| * @since 2024-05-29 13:51:23 | |||
| */ | |||
| @RestController | |||
| @RequestMapping("modelDependency") | |||
| public class ModelDependencyController extends BaseController { | |||
| /** | |||
| * 服务对象 | |||
| */ | |||
| @Resource | |||
| private ModelDependencyService modelDependencyService; | |||
| /** | |||
| * 分页查询 | |||
| * | |||
| * @param modelDependency 筛选条件 | |||
| * @param page 分页对象 | |||
| * @param size 分页对象 | |||
| * @return 查询结果 | |||
| */ | |||
| @GetMapping | |||
| @ApiOperation("分页查询") | |||
| public GenericsAjaxResult<Page<ModelDependency>> queryByPage(ModelDependency modelDependency, int page ,int size) { | |||
| PageRequest pageRequest = PageRequest.of(page,size); | |||
| return genericsSuccess(this.modelDependencyService.queryByPage(modelDependency, pageRequest)); | |||
| } | |||
| /** | |||
| * 根据对象查询 | |||
| * | |||
| * @param modelDependency 筛选条件 | |||
| * @return 查询结果 | |||
| */ | |||
| @GetMapping("/queryModelDependency") | |||
| @ApiOperation("根据对象查询") | |||
| public GenericsAjaxResult<List<ModelDependency>> queryByModelDependency(@RequestBody ModelDependency modelDependency) throws IOException { | |||
| modelDependency.setState(1); | |||
| return genericsSuccess(this.modelDependencyService.queryByModelDependency(modelDependency)); | |||
| } | |||
| /** | |||
| * 通过主键查询单条数据 | |||
| * | |||
| * @param id 主键 | |||
| * @return 单条数据 | |||
| */ | |||
| @GetMapping("{id}") | |||
| @ApiOperation("根据id查询") | |||
| public GenericsAjaxResult<ModelDependency> queryById(@PathVariable("id") Integer id) { | |||
| return genericsSuccess(this.modelDependencyService.queryById(id)); | |||
| } | |||
| /** | |||
| * 新增数据 | |||
| * | |||
| * @param modelDependency 实体 | |||
| * @return 新增结果 | |||
| */ | |||
| @PostMapping | |||
| public GenericsAjaxResult<ModelDependency> add(@RequestBody ModelDependency modelDependency) { | |||
| return genericsSuccess(this.modelDependencyService.insert(modelDependency)); | |||
| } | |||
| /** | |||
| * 编辑数据 | |||
| * | |||
| * @param modelDependency 实体 | |||
| * @return 编辑结果 | |||
| */ | |||
| @PutMapping | |||
| public GenericsAjaxResult<ModelDependency> edit(@RequestBody ModelDependency modelDependency) { | |||
| return genericsSuccess(this.modelDependencyService.update(modelDependency)); | |||
| } | |||
| /** | |||
| * 删除数据 | |||
| * | |||
| * @param id 主键 | |||
| * @return 删除是否成功 | |||
| */ | |||
| @DeleteMapping("{id}") | |||
| @ApiOperation("删除模型依赖") | |||
| public GenericsAjaxResult<String> deleteById(@PathVariable("id") Integer id) { | |||
| return genericsSuccess(this.modelDependencyService.removeById(id)); | |||
| } | |||
| @PostMapping("/queryModelAtlas") | |||
| @ApiOperation("根据模型id与版本两个属性得到模型的演化图谱") | |||
| public GenericsAjaxResult<ModelDependcyTreeVo> queryModelAtlas(@RequestBody ModelDependency modelDependency) throws Exception { | |||
| return genericsSuccess(this.modelDependencyService.getModelDependencyTree(modelDependency)); | |||
| } | |||
| } | |||
| @@ -11,6 +11,7 @@ import org.springframework.data.domain.PageRequest; | |||
| import org.springframework.web.bind.annotation.*; | |||
| import javax.annotation.Resource; | |||
| import java.io.IOException; | |||
| import java.util.List; | |||
| import java.util.Map; | |||
| @@ -129,7 +130,7 @@ public class ModelsVersionController extends BaseController { | |||
| @DeleteMapping("/deleteVersion") | |||
| @ApiOperation(value = "逻辑删除模型版本", notes = "根据模型ID和版本逻辑删除模型版本记录。") | |||
| public GenericsAjaxResult<Map<Integer, String>> deleteModelsVersion(@RequestParam("models_id") Integer modelsId, | |||
| @RequestParam("version") String version) { | |||
| @RequestParam("version") String version) throws IOException { | |||
| return genericsSuccess(this.modelsVersionService.deleteModelsVersion(modelsId, version)); | |||
| } | |||
| @@ -116,7 +116,7 @@ public class WorkflowController extends BaseController { | |||
| */ | |||
| @PutMapping | |||
| @ApiOperation("编辑流水线") | |||
| public GenericsAjaxResult<Workflow> edit(@RequestBody Workflow workflow) { | |||
| public GenericsAjaxResult<Workflow> edit(@RequestBody Workflow workflow) throws Exception { | |||
| return genericsSuccess(this.workflowService.update(workflow)); | |||
| } | |||
| @@ -1,6 +1,7 @@ | |||
| package com.ruoyi.platform.domain; | |||
| import com.fasterxml.jackson.annotation.JsonProperty; | |||
| import com.fasterxml.jackson.annotation.JsonRawValue; | |||
| import com.fasterxml.jackson.databind.PropertyNamingStrategy; | |||
| import com.fasterxml.jackson.databind.annotation.JsonNaming; | |||
| import io.swagger.annotations.ApiModelProperty; | |||
| @@ -58,6 +59,7 @@ public class Component implements Serializable { | |||
| */ | |||
| @JsonProperty("env_variables") | |||
| @ApiModelProperty(name = "env_variables", value = "环境变量") | |||
| //@JsonRawValue | |||
| private String envVirables; | |||
| /** | |||
| * 资源规格 | |||
| @@ -78,12 +80,20 @@ public class Component implements Serializable { | |||
| * 输入参数 | |||
| */ | |||
| @ApiModelProperty(name = "in_parameters" ,value = "输入参数") | |||
| //@JsonRawValue | |||
| private String inParameters; | |||
| /** | |||
| * 输出参数 | |||
| */ | |||
| @ApiModelProperty(name = "out_parameters" ,value = "输出参数") | |||
| //@JsonRawValue | |||
| private String outParameters; | |||
| /** | |||
| * 可见范围 | |||
| */ | |||
| @ApiModelProperty(name = "available_range" ,value = "1公开0私有") | |||
| private int availableRange; | |||
| /** | |||
| * 描述 | |||
| */ | |||
| @@ -94,6 +104,8 @@ public class Component implements Serializable { | |||
| * 图标路径 | |||
| */ | |||
| @ApiModelProperty(name = "icon_path" ,value = "图标路径") | |||
| private String iconPath; | |||
| /** | |||
| * 创建者 | |||
| @@ -124,6 +136,8 @@ public class Component implements Serializable { | |||
| @ApiModelProperty(name = "state" , value = "状态") | |||
| private Integer state; | |||
| public Integer getId() { | |||
| return id; | |||
| } | |||
| @@ -228,6 +242,14 @@ public class Component implements Serializable { | |||
| this.outParameters = outParameters; | |||
| } | |||
| public int getAvailableRange() { | |||
| return availableRange; | |||
| } | |||
| public void setAvailableRange(int availableRange) { | |||
| this.availableRange = availableRange; | |||
| } | |||
| public String getDescription() { | |||
| return description; | |||
| } | |||
| @@ -0,0 +1,213 @@ | |||
| package com.ruoyi.platform.domain; | |||
| import com.fasterxml.jackson.databind.PropertyNamingStrategy; | |||
| import com.fasterxml.jackson.databind.annotation.JsonNaming; | |||
| import java.util.Date; | |||
| import java.io.Serializable; | |||
| /** | |||
| * (DevEnvironment)实体类 | |||
| * | |||
| * @author Xidaray | |||
| * @since 2024-06-03 15:17:37 | |||
| */ | |||
| @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) | |||
| public class DevEnvironment implements Serializable { | |||
| private static final long serialVersionUID = 936999018935545992L; | |||
| /** | |||
| * 主键 | |||
| */ | |||
| private Integer id; | |||
| /** | |||
| * 编辑器名称 | |||
| */ | |||
| private String name; | |||
| /** | |||
| * 状态 | |||
| */ | |||
| private String status; | |||
| /** | |||
| * 计算资源 | |||
| */ | |||
| private String computingResource; | |||
| /** | |||
| * 资源规格 | |||
| */ | |||
| private String standard; | |||
| /** | |||
| * 环境变量 | |||
| */ | |||
| private String envVariable; | |||
| /** | |||
| * 所用镜像 | |||
| */ | |||
| private String image; | |||
| /** | |||
| * 对应数据集 | |||
| */ | |||
| private String dataset; | |||
| /** | |||
| * 对应模型 | |||
| */ | |||
| private String model; | |||
| /** | |||
| * 备用字段1 | |||
| */ | |||
| private String altField1; | |||
| /** | |||
| * 备用字段2 | |||
| */ | |||
| private String altField2; | |||
| /** | |||
| * 创建者 | |||
| */ | |||
| private String createBy; | |||
| /** | |||
| * 创建时间 | |||
| */ | |||
| private Date createTime; | |||
| /** | |||
| * 更新者 | |||
| */ | |||
| private String updateBy; | |||
| /** | |||
| * 更新时间 | |||
| */ | |||
| private Date updateTime; | |||
| /** | |||
| * 状态,0失效1生效 | |||
| */ | |||
| private Integer state; | |||
| public Integer getId() { | |||
| return id; | |||
| } | |||
| public void setId(Integer id) { | |||
| this.id = id; | |||
| } | |||
| public String getName() { | |||
| return name; | |||
| } | |||
| public void setName(String name) { | |||
| this.name = name; | |||
| } | |||
| public String getStatus() { | |||
| return status; | |||
| } | |||
| public void setStatus(String status) { | |||
| this.status = status; | |||
| } | |||
| public String getComputingResource() { | |||
| return computingResource; | |||
| } | |||
| public void setComputingResource(String computingResource) { | |||
| this.computingResource = computingResource; | |||
| } | |||
| public String getStandard() { | |||
| return standard; | |||
| } | |||
| public void setStandard(String standard) { | |||
| this.standard = standard; | |||
| } | |||
| public String getEnvVariable() { | |||
| return envVariable; | |||
| } | |||
| public void setEnvVariable(String envVariable) { | |||
| this.envVariable = envVariable; | |||
| } | |||
| public String getImage() { | |||
| return image; | |||
| } | |||
| public void setImage(String image) { | |||
| this.image = image; | |||
| } | |||
| public String getDataset() { | |||
| return dataset; | |||
| } | |||
| public void setDataset(String dataset) { | |||
| this.dataset = dataset; | |||
| } | |||
| public String getModel() { | |||
| return model; | |||
| } | |||
| public void setModel(String model) { | |||
| this.model = model; | |||
| } | |||
| public String getAltField1() { | |||
| return altField1; | |||
| } | |||
| public void setAltField1(String altField1) { | |||
| this.altField1 = altField1; | |||
| } | |||
| public String getAltField2() { | |||
| return altField2; | |||
| } | |||
| public void setAltField2(String altField2) { | |||
| this.altField2 = altField2; | |||
| } | |||
| public String getCreateBy() { | |||
| return createBy; | |||
| } | |||
| public void setCreateBy(String createBy) { | |||
| this.createBy = createBy; | |||
| } | |||
| public Date getCreateTime() { | |||
| return createTime; | |||
| } | |||
| public void setCreateTime(Date createTime) { | |||
| this.createTime = createTime; | |||
| } | |||
| public String getUpdateBy() { | |||
| return updateBy; | |||
| } | |||
| public void setUpdateBy(String updateBy) { | |||
| this.updateBy = updateBy; | |||
| } | |||
| public Date getUpdateTime() { | |||
| return updateTime; | |||
| } | |||
| public void setUpdateTime(Date updateTime) { | |||
| this.updateTime = updateTime; | |||
| } | |||
| public Integer getState() { | |||
| return state; | |||
| } | |||
| public void setState(Integer state) { | |||
| this.state = state; | |||
| } | |||
| } | |||
| @@ -0,0 +1,247 @@ | |||
| package com.ruoyi.platform.domain; | |||
| import com.fasterxml.jackson.databind.PropertyNamingStrategy; | |||
| import com.fasterxml.jackson.databind.annotation.JsonNaming; | |||
| import io.swagger.annotations.ApiModelProperty; | |||
| import java.util.Date; | |||
| import java.io.Serializable; | |||
| /** | |||
| * (ModelDependency)实体类 | |||
| * | |||
| * @author Xidaray | |||
| * @since 2024-05-29 13:51:23 | |||
| */ | |||
| @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) | |||
| public class ModelDependency implements Serializable { | |||
| private static final long serialVersionUID = -86753423714028539L; | |||
| /** | |||
| * 主键 | |||
| */ | |||
| private Integer id; | |||
| /** | |||
| * 当前模型id | |||
| */ | |||
| private Integer currentModelId; | |||
| /** | |||
| * 实验实例id | |||
| */ | |||
| private Integer expInsId; | |||
| /** | |||
| * 父模型 | |||
| */ | |||
| private String parentModels; | |||
| /** | |||
| * 引用项目 | |||
| */ | |||
| private String refItem; | |||
| /** | |||
| * 训练任务 | |||
| */ | |||
| private String trainTask; | |||
| /** | |||
| * 训练数据集 | |||
| */ | |||
| private String trainDataset; | |||
| /** | |||
| * 训练参数 | |||
| */ | |||
| private String trainParams; | |||
| /** | |||
| * 训练镜像 | |||
| */ | |||
| private String trainImage; | |||
| /** | |||
| * 测试数据集 | |||
| */ | |||
| private String testDataset; | |||
| /** | |||
| * 依赖项目 | |||
| */ | |||
| private String projectDependency; | |||
| /** | |||
| * 版本 | |||
| */ | |||
| private String version; | |||
| /** | |||
| * 创建者 | |||
| */ | |||
| private String createBy; | |||
| /** | |||
| * 创建时间 | |||
| */ | |||
| private Date createTime; | |||
| /** | |||
| * 更新者 | |||
| */ | |||
| private String updateBy; | |||
| /** | |||
| * 更新时间 | |||
| */ | |||
| private Date updateTime; | |||
| /** | |||
| * 状态,0失效1生效 | |||
| */ | |||
| private Integer state; | |||
| private Long workflowId; | |||
| private Models models; | |||
| public Integer getId() { | |||
| return id; | |||
| } | |||
| public void setId(Integer id) { | |||
| this.id = id; | |||
| } | |||
| public Integer getCurrentModelId() { | |||
| return currentModelId; | |||
| } | |||
| public void setCurrentModelId(Integer currentModelId) { | |||
| this.currentModelId = currentModelId; | |||
| } | |||
| public Integer getExpInsId() { | |||
| return expInsId; | |||
| } | |||
| public void setExpInsId(Integer expInsId) { | |||
| this.expInsId = expInsId; | |||
| } | |||
| public String getParentModels() { | |||
| return parentModels; | |||
| } | |||
| public void setParentModels(String parentModels) { | |||
| this.parentModels = parentModels; | |||
| } | |||
| public String getRefItem() { | |||
| return refItem; | |||
| } | |||
| public void setRefItem(String refItem) { | |||
| this.refItem = refItem; | |||
| } | |||
| public String getTrainTask() { | |||
| return trainTask; | |||
| } | |||
| public void setTrainTask(String trainTask) { | |||
| this.trainTask = trainTask; | |||
| } | |||
| public String getTrainDataset() { | |||
| return trainDataset; | |||
| } | |||
| public void setTrainDataset(String trainDataset) { | |||
| this.trainDataset = trainDataset; | |||
| } | |||
| public String getTrainParams() { | |||
| return trainParams; | |||
| } | |||
| public void setTrainParams(String trainParams) { | |||
| this.trainParams = trainParams; | |||
| } | |||
| public String getTrainImage() { | |||
| return trainImage; | |||
| } | |||
| public void setTrainImage(String trainImage) { | |||
| this.trainImage = trainImage; | |||
| } | |||
| public String getTestDataset() { | |||
| return testDataset; | |||
| } | |||
| public void setTestDataset(String testDataset) { | |||
| this.testDataset = testDataset; | |||
| } | |||
| public String getProjectDependency() { | |||
| return projectDependency; | |||
| } | |||
| public void setProjectDependency(String projectDependency) { | |||
| this.projectDependency = projectDependency; | |||
| } | |||
| public String getVersion() { | |||
| return version; | |||
| } | |||
| public void setVersion(String version) { | |||
| this.version = version; | |||
| } | |||
| public String getCreateBy() { | |||
| return createBy; | |||
| } | |||
| public void setCreateBy(String createBy) { | |||
| this.createBy = createBy; | |||
| } | |||
| public Date getCreateTime() { | |||
| return createTime; | |||
| } | |||
| public void setCreateTime(Date createTime) { | |||
| this.createTime = createTime; | |||
| } | |||
| public String getUpdateBy() { | |||
| return updateBy; | |||
| } | |||
| public void setUpdateBy(String updateBy) { | |||
| this.updateBy = updateBy; | |||
| } | |||
| public Date getUpdateTime() { | |||
| return updateTime; | |||
| } | |||
| public void setUpdateTime(Date updateTime) { | |||
| this.updateTime = updateTime; | |||
| } | |||
| public Integer getState() { | |||
| return state; | |||
| } | |||
| public void setState(Integer state) { | |||
| this.state = state; | |||
| } | |||
| public Long getWorkflowId() { | |||
| return workflowId; | |||
| } | |||
| public void setWorkflowId(Long workflowId) { | |||
| this.workflowId = workflowId; | |||
| } | |||
| public Models getModels() { | |||
| return models; | |||
| } | |||
| public void setModels(Models models) { | |||
| this.models = models; | |||
| } | |||
| } | |||
| @@ -0,0 +1,14 @@ | |||
| package com.ruoyi.platform.domain.dependencydomain; | |||
| import com.fasterxml.jackson.databind.PropertyNamingStrategy; | |||
| import com.fasterxml.jackson.databind.annotation.JsonNaming; | |||
| import lombok.Data; | |||
| import java.io.Serializable; | |||
| @Data | |||
| @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) | |||
| public class ProjectDepency implements Serializable { | |||
| private String url; | |||
| private String name; | |||
| private String branch; | |||
| } | |||
| @@ -0,0 +1,17 @@ | |||
| package com.ruoyi.platform.domain.dependencydomain; | |||
| import com.fasterxml.jackson.databind.PropertyNamingStrategy; | |||
| import com.fasterxml.jackson.databind.annotation.JsonNaming; | |||
| import lombok.Data; | |||
| import java.io.Serializable; | |||
| @Data | |||
| @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) | |||
| public class TrainTaskDepency implements Serializable { | |||
| //训练任务名 | |||
| private String name; | |||
| //实例id | |||
| private Integer insId; | |||
| //节点Id | |||
| private String taskId; | |||
| } | |||
| @@ -0,0 +1,84 @@ | |||
| package com.ruoyi.platform.mapper; | |||
| import com.ruoyi.platform.domain.DevEnvironment; | |||
| import org.apache.ibatis.annotations.Param; | |||
| import org.springframework.data.domain.Pageable; | |||
| import java.util.List; | |||
| /** | |||
| * (DevEnvironment)表数据库访问层 | |||
| * | |||
| * @author Xidaray | |||
| * @since 2024-06-03 15:17:37 | |||
| */ | |||
| public interface DevEnvironmentDao { | |||
| /** | |||
| * 通过ID查询单条数据 | |||
| * | |||
| * @param id 主键 | |||
| * @return 实例对象 | |||
| */ | |||
| DevEnvironment queryById(Integer id); | |||
| /** | |||
| * 查询指定行数据 | |||
| * | |||
| * @param devEnvironment 查询条件 | |||
| * @param pageable 分页对象 | |||
| * @return 对象列表 | |||
| */ | |||
| List<DevEnvironment> queryAllByLimit(@Param("devEnvironment") DevEnvironment devEnvironment, @Param("pageable") Pageable pageable); | |||
| /** | |||
| * 统计总行数 | |||
| * | |||
| * @param devEnvironment 查询条件 | |||
| * @return 总行数 | |||
| */ | |||
| long count(@Param("devEnvironment") DevEnvironment devEnvironment); | |||
| /** | |||
| * 新增数据 | |||
| * | |||
| * @param devEnvironment 实例对象 | |||
| * @return 影响行数 | |||
| */ | |||
| int insert(@Param("devEnvironment") DevEnvironment devEnvironment); | |||
| /** | |||
| * 批量新增数据(MyBatis原生foreach方法) | |||
| * | |||
| * @param entities List<DevEnvironment> 实例对象列表 | |||
| * @return 影响行数 | |||
| */ | |||
| int insertBatch(@Param("entities") List<DevEnvironment> entities); | |||
| /** | |||
| * 批量新增或按主键更新数据(MyBatis原生foreach方法) | |||
| * | |||
| * @param entities List<DevEnvironment> 实例对象列表 | |||
| * | |||
| * @return 影响行数 | |||
| * @throws org.springframework.jdbc.BadSqlGrammarException 入参是空List的时候会抛SQL语句错误的异常,请自行校验入参 | |||
| */ | |||
| int insertOrUpdateBatch(@Param("entities") List<DevEnvironment> entities); | |||
| /** | |||
| * 修改数据 | |||
| * | |||
| * @param devEnvironment 实例对象 | |||
| * @return 影响行数 | |||
| */ | |||
| int update(@Param("devEnvironment") DevEnvironment devEnvironment); | |||
| /** | |||
| * 通过主键删除数据 | |||
| * | |||
| * @param id 主键 | |||
| * @return 影响行数 | |||
| */ | |||
| int deleteById(Integer id); | |||
| } | |||
| @@ -0,0 +1,88 @@ | |||
| package com.ruoyi.platform.mapper; | |||
| import com.ruoyi.platform.domain.ModelDependency; | |||
| import org.apache.ibatis.annotations.Param; | |||
| import org.springframework.data.domain.Pageable; | |||
| import java.util.List; | |||
| /** | |||
| * (ModelDependency)表数据库访问层 | |||
| * | |||
| * @author Xidaray | |||
| * @since 2024-05-29 13:51:23 | |||
| */ | |||
| public interface ModelDependencyDao { | |||
| /** | |||
| * 通过ID查询单条数据 | |||
| * | |||
| * @param id 主键 | |||
| * @return 实例对象 | |||
| */ | |||
| ModelDependency queryById(Integer id); | |||
| /** | |||
| * 查询指定行数据 | |||
| * | |||
| * @param modelDependency 查询条件 | |||
| * @param pageable 分页对象 | |||
| * @return 对象列表 | |||
| */ | |||
| List<ModelDependency> queryAllByLimit(ModelDependency modelDependency, @Param("pageable") Pageable pageable); | |||
| /** | |||
| * 统计总行数 | |||
| * | |||
| * @param modelDependency 查询条件 | |||
| * @return 总行数 | |||
| */ | |||
| long count(ModelDependency modelDependency); | |||
| /** | |||
| * 新增数据 | |||
| * | |||
| * @param modelDependency 实例对象 | |||
| * @return 影响行数 | |||
| */ | |||
| int insert(ModelDependency modelDependency); | |||
| /** | |||
| * 批量新增数据(MyBatis原生foreach方法) | |||
| * | |||
| * @param entities List<ModelDependency> 实例对象列表 | |||
| * @return 影响行数 | |||
| */ | |||
| int insertBatch(@Param("entities") List<ModelDependency> entities); | |||
| /** | |||
| * 批量新增或按主键更新数据(MyBatis原生foreach方法) | |||
| * | |||
| * @param entities List<ModelDependency> 实例对象列表 | |||
| * @return 影响行数 | |||
| * @throws org.springframework.jdbc.BadSqlGrammarException 入参是空List的时候会抛SQL语句错误的异常,请自行校验入参 | |||
| */ | |||
| int insertOrUpdateBatch(@Param("entities") List<ModelDependency> entities); | |||
| /** | |||
| * 修改数据 | |||
| * | |||
| * @param modelDependency 实例对象 | |||
| * @return 影响行数 | |||
| */ | |||
| int update(ModelDependency modelDependency); | |||
| /** | |||
| * 通过主键删除数据 | |||
| * | |||
| * @param id 主键 | |||
| * @return 影响行数 | |||
| */ | |||
| int deleteById(Integer id); | |||
| List<ModelDependency> queryByModelDependency(@Param("modelDependency") ModelDependency modelDependency); | |||
| List<ModelDependency> queryChildrenByVersionId(@Param("model_id")String modelId, @Param("version")String version); | |||
| } | |||
| @@ -1,24 +1,26 @@ | |||
| package com.ruoyi.platform.scheduling; | |||
| import com.ruoyi.common.security.utils.SecurityUtils; | |||
| import com.ruoyi.platform.domain.Experiment; | |||
| import com.ruoyi.platform.domain.ExperimentIns; | |||
| import com.ruoyi.platform.domain.ModelDependency; | |||
| import com.ruoyi.platform.mapper.ExperimentDao; | |||
| import com.ruoyi.platform.mapper.ExperimentInsDao; | |||
| import com.ruoyi.platform.mapper.ModelDependencyDao; | |||
| import com.ruoyi.platform.service.ExperimentInsService; | |||
| import com.ruoyi.platform.service.ExperimentService; | |||
| import com.ruoyi.platform.utils.JsonUtils; | |||
| import com.ruoyi.system.api.model.LoginUser; | |||
| import io.swagger.models.auth.In; | |||
| import com.ruoyi.platform.service.ModelDependencyService; | |||
| import com.ruoyi.platform.utils.JacksonUtil; | |||
| import org.apache.commons.lang3.StringUtils; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.data.domain.Page; | |||
| import org.springframework.scheduling.annotation.Scheduled; | |||
| import org.springframework.stereotype.Component; | |||
| import javax.annotation.Resource; | |||
| import java.io.IOException; | |||
| import java.util.*; | |||
| import java.util.stream.Collectors; | |||
| import java.util.ArrayList; | |||
| import java.util.Date; | |||
| import java.util.List; | |||
| import java.util.Map; | |||
| @Component() | |||
| public class ExperimentInstanceStatusTask { | |||
| @@ -28,7 +30,8 @@ public class ExperimentInstanceStatusTask { | |||
| private ExperimentDao experimentDao; | |||
| @Resource | |||
| private ExperimentInsDao experimentInsDao; | |||
| @Resource | |||
| private ModelDependencyDao modelDependencyDao; | |||
| private List<Integer> experimentIds = new ArrayList<>(); | |||
| @Scheduled(cron = "0/30 * * * * ?") // 每30S执行一次 | |||
| @@ -55,12 +58,50 @@ public class ExperimentInstanceStatusTask { | |||
| updateList.add(experimentIns); | |||
| } | |||
| experimentInsDao.update(experimentIns); | |||
| // experimentInsDao.update(experimentIns); | |||
| } | |||
| } | |||
| if (updateList.size() > 0){ | |||
| experimentInsDao.insertOrUpdateBatch(updateList); | |||
| //遍历模型关系表,找到 | |||
| List<ModelDependency> modelDependencyList = new ArrayList<ModelDependency>(); | |||
| for (ExperimentIns experimentIns : updateList){ | |||
| ModelDependency modelDependencyquery = new ModelDependency(); | |||
| modelDependencyquery.setExpInsId(experimentIns.getId()); | |||
| modelDependencyquery.setState(2); | |||
| List<ModelDependency> modelDependencyListquery = modelDependencyDao.queryByModelDependency(modelDependencyquery); | |||
| if (modelDependencyListquery==null||modelDependencyListquery.size()==0){ | |||
| continue; | |||
| } | |||
| ModelDependency modelDependency = modelDependencyListquery.get(0); | |||
| //查看状态, | |||
| if (StringUtils.equals("Failed",experimentIns.getStatus())){ | |||
| //取出节点状态 | |||
| String trainTask = modelDependency.getTrainTask(); | |||
| Map<String, Object> trainMap = JacksonUtil.parseJSONStr2Map(trainTask); | |||
| String task_id = (String) trainMap.get("task_id"); | |||
| if (StringUtils.isEmpty(task_id)){ | |||
| continue; | |||
| } | |||
| String nodesStatus = experimentIns.getNodesStatus(); | |||
| Map<String, Object> nodeMaps = JacksonUtil.parseJSONStr2Map(nodesStatus); | |||
| Map<String, Object> nodeMap = JacksonUtil.parseJSONStr2Map(JacksonUtil.toJSONString(nodeMaps.get(task_id))); | |||
| if (nodeMap==null){ | |||
| continue; | |||
| } | |||
| if (!StringUtils.equals("Succeeded",(String)nodeMap.get("phase"))){ | |||
| modelDependency.setState(0); | |||
| modelDependencyList.add(modelDependency); | |||
| } | |||
| } | |||
| } | |||
| if (modelDependencyList.size()>0) { | |||
| modelDependencyDao.insertOrUpdateBatch(modelDependencyList); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,57 @@ | |||
| package com.ruoyi.platform.service; | |||
| import com.ruoyi.platform.domain.DevEnvironment; | |||
| import org.springframework.data.domain.Page; | |||
| import org.springframework.data.domain.PageRequest; | |||
| /** | |||
| * (DevEnvironment)表服务接口 | |||
| * | |||
| * @author Xidaray | |||
| * @since 2024-06-03 15:17:37 | |||
| */ | |||
| public interface DevEnvironmentService { | |||
| /** | |||
| * 通过ID查询单条数据 | |||
| * | |||
| * @param id 主键 | |||
| * @return 实例对象 | |||
| */ | |||
| DevEnvironment queryById(Integer id); | |||
| /** | |||
| * 分页查询 | |||
| * | |||
| * @param devEnvironment 筛选条件 | |||
| * @param pageRequest 分页对象 | |||
| * @return 查询结果 | |||
| */ | |||
| Page<DevEnvironment> queryByPage(DevEnvironment devEnvironment, PageRequest pageRequest); | |||
| /** | |||
| * 新增数据 | |||
| * | |||
| * @param devEnvironment 实例对象 | |||
| * @return 实例对象 | |||
| */ | |||
| DevEnvironment insert(DevEnvironment devEnvironment); | |||
| /** | |||
| * 修改数据 | |||
| * | |||
| * @param devEnvironment 实例对象 | |||
| * @return 实例对象 | |||
| */ | |||
| DevEnvironment update(DevEnvironment devEnvironment); | |||
| /** | |||
| * 通过主键删除数据 | |||
| * | |||
| * @param id 主键 | |||
| * @return 是否成功 | |||
| */ | |||
| boolean deleteById(Integer id); | |||
| String removeById(Integer id); | |||
| } | |||
| @@ -100,7 +100,7 @@ public interface ExperimentInsService { | |||
| /** | |||
| * 查询非终止态的实例 | |||
| * @return | |||
| * | |||
| */ | |||
| List<ExperimentIns> queryByExperimentIsNotTerminated(); | |||
| @@ -48,7 +48,7 @@ public interface ExperimentService { | |||
| * @param experiment 实例对象 | |||
| * @return 实例对象 | |||
| */ | |||
| Experiment update(Experiment experiment) throws IOException; | |||
| Experiment update(Experiment experiment) throws Exception; | |||
| /** | |||
| * 通过主键删除数据 | |||
| @@ -1,5 +1,7 @@ | |||
| package com.ruoyi.platform.service; | |||
| import com.ruoyi.platform.vo.FrameLogPathVo; | |||
| import java.io.InputStream; | |||
| public interface JupyterService { | |||
| @@ -8,4 +10,8 @@ public interface JupyterService { | |||
| void upload(InputStream inputStream); | |||
| void mlflow(); | |||
| String runJupyterService(Integer id); | |||
| String stopJupyterService(Integer id) throws Exception; | |||
| } | |||
| @@ -0,0 +1,65 @@ | |||
| package com.ruoyi.platform.service; | |||
| import com.ruoyi.platform.domain.ModelDependency; | |||
| import com.ruoyi.platform.vo.ModelDependcyTreeVo; | |||
| import org.springframework.data.domain.Page; | |||
| import org.springframework.data.domain.PageRequest; | |||
| import java.io.IOException; | |||
| import java.util.List; | |||
| /** | |||
| * (ModelDependency)表服务接口 | |||
| * | |||
| * @author Xidaray | |||
| * @since 2024-05-29 13:51:23 | |||
| */ | |||
| public interface ModelDependencyService { | |||
| /** | |||
| * 通过ID查询单条数据 | |||
| * | |||
| * @param id 主键 | |||
| * @return 实例对象 | |||
| */ | |||
| ModelDependency queryById(Integer id); | |||
| /** | |||
| * 分页查询 | |||
| * | |||
| * @param modelDependency 筛选条件 | |||
| * @param pageRequest 分页对象 | |||
| * @return 查询结果 | |||
| */ | |||
| Page<ModelDependency> queryByPage(ModelDependency modelDependency, PageRequest pageRequest); | |||
| /** | |||
| * 修改数据 | |||
| * | |||
| * @param modelDependency 实例对象 | |||
| * @return 实例对象 | |||
| */ | |||
| ModelDependency update(ModelDependency modelDependency); | |||
| /** | |||
| * 新增数据 | |||
| * | |||
| * @param modelDependency 实例对象 | |||
| * @return 实例对象 | |||
| */ | |||
| ModelDependency insert(ModelDependency modelDependency); | |||
| /** | |||
| * 通过主键删除数据 | |||
| * | |||
| * @param id 主键 | |||
| * @return 是否成功 | |||
| */ | |||
| boolean deleteById(Integer id); | |||
| String removeById(Integer id); | |||
| List<ModelDependency> queryByModelDependency(ModelDependency modelDependency) throws IOException; | |||
| ModelDependcyTreeVo getModelDependencyTree(ModelDependency modelDependency) throws Exception; | |||
| } | |||
| @@ -6,6 +6,7 @@ import com.ruoyi.platform.domain.ModelsVersion; | |||
| import org.springframework.data.domain.Page; | |||
| import org.springframework.data.domain.PageRequest; | |||
| import java.io.IOException; | |||
| import java.util.List; | |||
| import java.util.Map; | |||
| @@ -68,7 +69,7 @@ public interface ModelsVersionService { | |||
| Map<String,Object> queryByModelsIdAndVersion(Integer modelsId, String version); | |||
| Map<Integer, String> deleteModelsVersion(Integer modelsId, String version); | |||
| Map<Integer, String> deleteModelsVersion(Integer modelsId, String version) throws IOException; | |||
| String addModelVersions(List<ModelsVersion> modelsVersions) throws Exception; | |||
| @@ -45,7 +45,7 @@ public interface WorkflowService { | |||
| * @param workflow 实例对象 | |||
| * @return 实例对象 | |||
| */ | |||
| Workflow update(Workflow workflow); | |||
| Workflow update(Workflow workflow) throws Exception; | |||
| /** | |||
| * 通过主键删除数据 | |||
| @@ -51,7 +51,7 @@ public class ComponentServiceImpl implements ComponentService { | |||
| throw new RuntimeException("组件不存在"); | |||
| } | |||
| return this.componentDao.queryById(id); | |||
| return component; | |||
| } | |||
| @Override | |||
| @@ -149,6 +149,7 @@ public class ComponentServiceImpl implements ComponentService { | |||
| String inParameters= gson.toJson(componentVo.getInParameters(), LinkedHashMap.class); | |||
| String outParameters = gson.toJson(componentVo.getOutParameters(), LinkedHashMap.class); | |||
| String envVariable = gson.toJson(componentVo.getEnvVirables(), LinkedHashMap.class); | |||
| component.setEnvVirables(envVariable); | |||
| component.setInParameters(inParameters); | |||
| @@ -353,22 +353,15 @@ public class DatasetServiceImpl implements DatasetService { | |||
| public void checkDeclaredName(Dataset insert) throws Exception { | |||
| Dataset existingDataset = datasetDao.findByName(insert.getName()); | |||
| if (existingDataset != null) { | |||
| // Check if the found dataset 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(existingDataset.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 = Dataset.class.getDeclaredFields(); | |||
| for (Field field : fields) { | |||
| field.setAccessible(true); // Make private fields accessible | |||
| field.setAccessible(true); | |||
| 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()); | |||
| } | |||
| @@ -0,0 +1,125 @@ | |||
| package com.ruoyi.platform.service.impl; | |||
| import com.ruoyi.common.security.utils.SecurityUtils; | |||
| import com.ruoyi.platform.domain.DevEnvironment; | |||
| import com.ruoyi.platform.mapper.DevEnvironmentDao; | |||
| import com.ruoyi.platform.service.DevEnvironmentService; | |||
| import com.ruoyi.platform.service.JupyterService; | |||
| import com.ruoyi.platform.utils.JacksonUtil; | |||
| import com.ruoyi.system.api.model.LoginUser; | |||
| import io.kubernetes.client.openapi.models.V1PersistentVolumeClaim; | |||
| import org.apache.commons.lang3.StringUtils; | |||
| import org.springframework.stereotype.Service; | |||
| import org.springframework.data.domain.Page; | |||
| import org.springframework.data.domain.PageImpl; | |||
| import org.springframework.data.domain.PageRequest; | |||
| import javax.annotation.Resource; | |||
| import java.util.Date; | |||
| import java.util.Map; | |||
| /** | |||
| * (DevEnvironment)表服务实现类 | |||
| * | |||
| * @author Xidaray | |||
| * @since 2024-06-03 15:17:37 | |||
| */ | |||
| @Service("devEnvironmentService") | |||
| public class DevEnvironmentServiceImpl implements DevEnvironmentService { | |||
| @Resource | |||
| private DevEnvironmentDao devEnvironmentDao; | |||
| @Resource | |||
| private JupyterService jupyterService; | |||
| /** | |||
| * 通过ID查询单条数据 | |||
| * | |||
| * @param id 主键 | |||
| * @return 实例对象 | |||
| */ | |||
| @Override | |||
| public DevEnvironment queryById(Integer id) { | |||
| return this.devEnvironmentDao.queryById(id); | |||
| } | |||
| /** | |||
| * 分页查询 | |||
| * | |||
| * @param devEnvironment 筛选条件 | |||
| * @param pageRequest 分页对象 | |||
| * @return 查询结果 | |||
| */ | |||
| @Override | |||
| public Page<DevEnvironment> queryByPage(DevEnvironment devEnvironment, PageRequest pageRequest) { | |||
| long total = this.devEnvironmentDao.count(devEnvironment); | |||
| return new PageImpl<>(this.devEnvironmentDao.queryAllByLimit(devEnvironment, pageRequest), pageRequest, total); | |||
| } | |||
| /** | |||
| * 新增数据 | |||
| * | |||
| * @param devEnvironment 实例对象 | |||
| * @return 实例对象 | |||
| */ | |||
| @Override | |||
| public DevEnvironment insert(DevEnvironment devEnvironment) { | |||
| //插入预备,此时不需要判断版本重复 | |||
| LoginUser loginUser = SecurityUtils.getLoginUser(); | |||
| devEnvironment.setCreateBy(loginUser.getUsername()); | |||
| devEnvironment.setUpdateBy(loginUser.getUsername()); | |||
| devEnvironment.setUpdateTime(new Date()); | |||
| devEnvironment.setCreateTime(new Date()); | |||
| this.devEnvironmentDao.insert(devEnvironment); | |||
| return devEnvironment; | |||
| } | |||
| /** | |||
| * 修改数据 | |||
| * | |||
| * @param devEnvironment 实例对象 | |||
| * @return 实例对象 | |||
| */ | |||
| @Override | |||
| public DevEnvironment update(DevEnvironment devEnvironment) { | |||
| LoginUser loginUser = SecurityUtils.getLoginUser(); | |||
| devEnvironment.setUpdateBy(loginUser.getUsername()); | |||
| devEnvironment.setUpdateTime(new Date()); | |||
| this.devEnvironmentDao.update(devEnvironment); | |||
| return this.queryById(devEnvironment.getId()); | |||
| } | |||
| /** | |||
| * 通过主键删除数据 | |||
| * | |||
| * @param id 主键 | |||
| * @return 是否成功 | |||
| */ | |||
| @Override | |||
| public boolean deleteById(Integer id) { | |||
| return this.devEnvironmentDao.deleteById(id) > 0; | |||
| } | |||
| @Override | |||
| public String removeById(Integer id) { | |||
| DevEnvironment devEnvironment = this.devEnvironmentDao.queryById(id); | |||
| if (devEnvironment == null){ | |||
| return "开发环境信息不存在"; | |||
| } | |||
| //判断权限,只有admin和创建者本身可以删除该数据集 | |||
| LoginUser loginUser = SecurityUtils.getLoginUser(); | |||
| String username = loginUser.getUsername(); | |||
| String createdBy = devEnvironment.getCreateBy(); | |||
| if (!(StringUtils.equals(username,"admin") || StringUtils.equals(username,createdBy))){ | |||
| return "无权限删除该开发环境"; | |||
| } | |||
| devEnvironment.setState(0); | |||
| return this.devEnvironmentDao.update(devEnvironment)>0?"删除成功":"删除失败"; | |||
| } | |||
| } | |||
| @@ -427,7 +427,6 @@ public class ExperimentInsServiceImpl implements ExperimentInsService { | |||
| throw new RuntimeException("日志为空。"); | |||
| } | |||
| //返回日志内容 | |||
| return experimentInsLog; | |||
| } catch (Exception e) { | |||
| throw new RuntimeException("查询实验日志失败: " + e.getMessage(), e); | |||
| @@ -554,7 +553,7 @@ public class ExperimentInsServiceImpl implements ExperimentInsService { | |||
| // 查询具有相同状态的实例数量 | |||
| Long count = experimentInsDao.count(experimentIns); | |||
| // 将状态及其对应的实例数量放入映射中 | |||
| // 将状态及其对应的实例数量放入map中 | |||
| statusCountMap.put(status.toString(), count); | |||
| } | |||
| @@ -580,8 +579,9 @@ public class ExperimentInsServiceImpl implements ExperimentInsService { | |||
| flag = StringUtils.equals("Terminated", (String) workflowMap.get("phase")); | |||
| } | |||
| } | |||
| return flag; | |||
| } | |||
| } | |||
| @@ -2,14 +2,12 @@ package com.ruoyi.platform.service.impl; | |||
| import com.ruoyi.common.security.utils.SecurityUtils; | |||
| import com.ruoyi.platform.annotations.CheckDuplicate; | |||
| import com.ruoyi.platform.domain.Experiment; | |||
| import com.ruoyi.platform.domain.ExperimentIns; | |||
| import com.ruoyi.platform.domain.Workflow; | |||
| import com.ruoyi.platform.domain.*; | |||
| import com.ruoyi.platform.domain.dependencydomain.ProjectDepency; | |||
| import com.ruoyi.platform.domain.dependencydomain.TrainTaskDepency; | |||
| import com.ruoyi.platform.mapper.ExperimentDao; | |||
| import com.ruoyi.platform.mapper.ExperimentInsDao; | |||
| import com.ruoyi.platform.service.ExperimentInsService; | |||
| import com.ruoyi.platform.service.ExperimentService; | |||
| import com.ruoyi.platform.service.WorkflowService; | |||
| import com.ruoyi.platform.service.*; | |||
| import com.ruoyi.platform.utils.HttpUtils; | |||
| import com.ruoyi.platform.utils.JacksonUtil; | |||
| import com.ruoyi.platform.utils.JsonUtils; | |||
| @@ -42,8 +40,12 @@ public class ExperimentServiceImpl implements ExperimentService { | |||
| @Resource | |||
| private ExperimentInsDao experimentInsDao; | |||
| @Resource | |||
| private ModelsService modelsService; | |||
| @Resource | |||
| private DatasetService datasetService; | |||
| @Resource | |||
| private ModelDependencyService modelDependencyService; | |||
| @Resource | |||
| @Lazy | |||
| @@ -151,8 +153,9 @@ public class ExperimentServiceImpl implements ExperimentService { | |||
| * @return 实例对象 | |||
| */ | |||
| @Override | |||
| public Experiment update(Experiment experiment) throws IOException { | |||
| public Experiment update(Experiment experiment) throws Exception { | |||
| LoginUser loginUser = SecurityUtils.getLoginUser(); | |||
| checkDeclaredName(experiment); | |||
| experiment.setUpdateBy(loginUser.getUsername()); | |||
| experiment.setUpdateTime(new Date()); | |||
| this.experimentDao.update(experiment); | |||
| @@ -207,12 +210,9 @@ public class ExperimentServiceImpl implements ExperimentService { | |||
| public Experiment runExperiment(Integer id) throws Exception { | |||
| //先查出实验记录 | |||
| Experiment experiment = this.queryById(id); | |||
| if (experiment == null) { | |||
| System.out.println("No experiment"); | |||
| } | |||
| Workflow workflow = workflowService.queryById(experiment.getWorkflowId()); | |||
| if(workflow == null) { | |||
| throw new RuntimeException("流水线不存在,请先创建流水线"); | |||
| @@ -226,13 +226,14 @@ public class ExperimentServiceImpl implements ExperimentService { | |||
| throw new RuntimeException("转换流水线失败"); | |||
| } | |||
| Map<String, Object> converMap = JsonUtils.jsonToMap(convertRes); | |||
| // 组装运行接口json | |||
| Map<String, Object> runReqMap = new HashMap<>(); | |||
| runReqMap.put("data", converMap.get("data")); | |||
| //这里全局参数是一个json数组,需要转换成一个list<Map> | |||
| List<Map<String, Object>> params = JacksonUtil.parseJSONStr2MapList(StringUtils.isEmpty(experiment.getGlobalParam()) ? "[]" : experiment.getGlobalParam()); | |||
| runReqMap.put("params", params); | |||
| //// 实验字段的Map,不要写成一行!否则会返回null | |||
| // 实验字段的Map,不要写成一行!否则会返回null | |||
| Map<String, Object> experimentMap = new HashMap<>(); | |||
| experimentMap.put("name", "experiment-"+experiment.getId()); | |||
| runReqMap.put("experiment", experimentMap); | |||
| @@ -246,14 +247,11 @@ public class ExperimentServiceImpl implements ExperimentService { | |||
| } | |||
| Map<String, Object> runResMap = JsonUtils.jsonToMap(runRes); | |||
| Map<String, Object> data = (Map<String, Object>) runResMap.get("data"); | |||
| //判断data为空 | |||
| if (data == null || MapUtils.isEmpty(data)) { | |||
| throw new RuntimeException("Failed to run workflow."); | |||
| } | |||
| Map<String, Object> metadata = (Map<String, Object>) data.get("metadata"); | |||
| // 插入记录到实验实例表 | |||
| ExperimentIns experimentIns = new ExperimentIns(); | |||
| experimentIns.setExperimentId(experiment.getId()); | |||
| @@ -262,24 +260,237 @@ public class ExperimentServiceImpl implements ExperimentService { | |||
| experimentIns.setStatus("Pending"); | |||
| //传入实验全局参数 | |||
| experimentIns.setGlobalParam(experiment.getGlobalParam()); | |||
| //替换argoInsName | |||
| String outputString = JsonUtils.mapToJson(output); | |||
| experimentIns.setNodesResult(outputString.replace("{{workflow.name}}", (String) metadata.get("name"))); | |||
| //插入ExperimentIns表中 | |||
| experimentInsService.insert(experimentIns); | |||
| ExperimentIns insert = experimentInsService.insert(experimentIns); | |||
| //插入到模型依赖关系表 | |||
| //得到dependendcy | |||
| Map<String, Object> converMap2 = JsonUtils.jsonToMap(JacksonUtil.replaceInAarry(convertRes, params)); | |||
| Map<String ,Object> dependendcy = (Map<String, Object>)converMap2.get("model_dependency"); | |||
| Map<String ,Object> trainInfo = (Map<String, Object>)converMap2.get("component_info"); | |||
| insertModelDependency(dependendcy,trainInfo,insert.getId(),experiment.getName()); | |||
| }catch (Exception e){ | |||
| throw new RuntimeException(e); | |||
| } | |||
| List<ExperimentIns> updatedExperimentInsList = experimentInsService.getByExperimentId(id); | |||
| experiment.setExperimentInsList(updatedExperimentInsList); | |||
| return experiment; | |||
| } | |||
| private void insertModelDependency(Map<String ,Object> dependendcy,Map<String ,Object> trainInfo, Integer experimentInsId, String experimentName) throws Exception { | |||
| Iterator<Map.Entry<String, Object>> dependendcyIterator = dependendcy.entrySet().iterator(); | |||
| Map<String, Object> modelTrain = (Map<String, Object>) trainInfo.get("model_train"); | |||
| Map<String, Object> modelEvaluate = (Map<String, Object>) trainInfo.get("model_evaluate"); | |||
| Map<String, Object> modelExport = (Map<String, Object>) trainInfo.get("model_export"); | |||
| while (dependendcyIterator.hasNext()) { | |||
| ModelDependency modelDependency = new ModelDependency(); | |||
| Map.Entry<String, Object> entry = dependendcyIterator.next(); | |||
| Map<String, Object> modelDel = (Map<String, Object>) entry.getValue(); | |||
| Map<String, Object> source = (Map<String, Object>) modelDel.get("source"); | |||
| List<Map<String, Object>> test = (List<Map<String, Object>>) modelDel.get("test"); | |||
| List<Map<String, Object>> target = (List<Map<String, Object>>) modelDel.get("target"); | |||
| String sourceTaskId = (String) source.get("task_id"); | |||
| Map<String, Object> modelTrainMap = (Map<String, Object>)modelTrain.get(sourceTaskId); | |||
| //处理project数据 | |||
| Map<String, String> projectMap = (Map<String, String>) modelTrainMap.get("project"); | |||
| ProjectDepency projectDepency = new ProjectDepency(); | |||
| projectDepency.setBranch(projectMap.get("branch")); | |||
| String projectUrl = projectMap.get("url"); | |||
| projectDepency.setUrl(projectUrl); | |||
| projectDepency.setName(projectUrl.substring(projectUrl.lastIndexOf('/') + 1, projectUrl.length() - 4)); | |||
| //依赖项目 | |||
| modelDependency.setProjectDependency(JsonUtils.objectToJson(projectDepency)); | |||
| //处理镜像 | |||
| Map<String, String> imagesMap = (Map<String, String>) modelTrainMap.get("image"); | |||
| modelDependency.setTrainImage(imagesMap.get("name")); | |||
| List<Map<String, Object>> trainParamList = (List<Map<String, Object>>) modelTrainMap.get("params"); | |||
| modelDependency.setTrainParams(JsonUtils.objectToJson(trainParamList)); | |||
| //处理source数据 | |||
| List<Map<String, Object>> modelsList = (List<Map<String, Object>>) modelTrainMap.get("models"); | |||
| if (modelsList != null) { | |||
| for (int i = 0; i < modelsList.size(); i++) { | |||
| Map<String, Object> model = modelsList.get(i); | |||
| Models models = modelsService.queryById((Integer) model.get("model_id")); | |||
| if (models == null) { | |||
| throw new Exception("源模型不存在"); | |||
| } | |||
| model.put("model_name", models.getName()); | |||
| } | |||
| //父模型 | |||
| modelDependency.setParentModels(JsonUtils.objectToJson(modelsList)); | |||
| } | |||
| List<Map<String, Object>> datasetsList = (List<Map<String, Object>>) modelTrainMap.get("datasets"); | |||
| if (datasetsList != null) { | |||
| for (int i = 0; i < datasetsList.size(); i++) { | |||
| Map<String, Object> datasets = datasetsList.get(i); | |||
| Dataset dataset = datasetService.queryById((Integer) datasets.get("dataset_id")); | |||
| if (dataset == null) { | |||
| throw new Exception("源数据集不存在"); | |||
| } | |||
| datasets.put("dataset_name", dataset.getName()); | |||
| } | |||
| } | |||
| //训练数据集 | |||
| modelDependency.setTrainDataset(JsonUtils.objectToJson(datasetsList)); | |||
| TrainTaskDepency trainTaskDepency = new TrainTaskDepency(); | |||
| trainTaskDepency.setTaskId(sourceTaskId); | |||
| trainTaskDepency.setInsId(experimentInsId); | |||
| trainTaskDepency.setName(experimentName); | |||
| //训练任务 | |||
| modelDependency.setTrainTask(JsonUtils.objectToJson(trainTaskDepency)); | |||
| modelDependency.setExpInsId(experimentInsId); | |||
| List<Map<String, Object>> resultTestDatasets = new ArrayList<Map<String, Object>>(); | |||
| //处理test数据 | |||
| if (test != null) { | |||
| for(int i=0;i<test.size();i++){ | |||
| Map<String, Object> testMap = test.get(i); | |||
| String testTaskId = (String) testMap.get("task_id"); | |||
| Map<String, Object> evaluateMap = (Map<String, Object>) modelEvaluate.get(testTaskId); | |||
| List<Map<String, Object>> realDataSetList = (List<Map<String, Object>>) evaluateMap.get("datasets"); | |||
| for(int j=0;j<realDataSetList.size();j++){ | |||
| Map<String, Object> realDataSet = realDataSetList.get(j); | |||
| Dataset dataset = datasetService.queryById((Integer) realDataSet.get("dataset_id")); | |||
| if (dataset == null){ | |||
| throw new Exception("源数据集不存在"); | |||
| } | |||
| realDataSet.put("dataset_name", dataset.getName()); | |||
| resultTestDatasets.add(realDataSet); | |||
| } | |||
| } | |||
| //测试数据集 | |||
| modelDependency.setTestDataset(JsonUtils.objectToJson(resultTestDatasets)); | |||
| } | |||
| //处理target数据 | |||
| if (target != null) { | |||
| for (int i = 0; i < target.size(); i++) { | |||
| Map<String, Object> targetMap = target.get(i); | |||
| String targetaskId = (String) targetMap.get("task_id"); | |||
| Map<String, Object> exportMap = (Map<String, Object>) modelExport.get(targetaskId); | |||
| List<Map<String, Object>> modelTargetList = (List<Map<String, Object>>) exportMap.get("models"); | |||
| modelDependency.setState(2); | |||
| for (int j = 0; j < modelTargetList.size(); j++) { | |||
| Map<String, Object> model = modelTargetList.get(i); | |||
| modelDependency.setVersion((String) model.get("model_version")); | |||
| modelDependency.setCurrentModelId((Integer) model.get("model_id")); | |||
| //因为可能有多成果模型,多次插入 | |||
| modelDependencyService.insert(modelDependency); | |||
| } | |||
| } | |||
| }else { | |||
| modelDependency.setState(2); | |||
| modelDependencyService.insert(modelDependency); | |||
| } | |||
| } | |||
| } | |||
| /** | |||
| * 被废弃的旧JSON | |||
| * @param experiment | |||
| * @return | |||
| * @throws Exception | |||
| */ | |||
| // private void insertModelDependency(Map<String ,Object> dependendcy,Map<String ,Object> trainInfo, Integer experimentInsId, String experimentName, List<Map<String, Object>> params) throws Exception { | |||
| // Iterator<Map.Entry<String, Object>> dependendcyIterator = dependendcy.entrySet().iterator(); | |||
| // while (dependendcyIterator.hasNext()) { | |||
| // ModelDependency modelDependency = new ModelDependency(); | |||
| // Map.Entry<String, Object> entry = dependendcyIterator.next(); | |||
| // String key = entry.getKey(); | |||
| // Map<String, Object> modelDel = (Map<String, Object>) entry.getValue(); | |||
| // //处理project数据 | |||
| // Map<String, String> projectMap = (Map<String, String>) modelDel.get("project"); | |||
| // ProjectDepency projectDepency = new ProjectDepency(); | |||
| // projectDepency.setBranch(projectMap.get("branch")); | |||
| // String projectUrl = projectMap.get("url"); | |||
| // projectDepency.setUrl(projectUrl); | |||
| // projectDepency.setName(projectUrl.substring(projectUrl.lastIndexOf('/') + 1, projectUrl.length() - 4)); | |||
| // //依赖项目 | |||
| // modelDependency.setProjectDependency(JsonUtils.objectToJson(projectDepency)); | |||
| // //处理source数据 | |||
| // Map<String, Object> sourceMap = (Map<String, Object>) modelDel.get("source"); | |||
| // List<Map<String, Object>> modelsList = (List<Map<String, Object>>) sourceMap.get("models"); | |||
| // for(int i=0;i<modelsList.size();i++){ | |||
| // Map<String, Object> model = modelsList.get(i); | |||
| // Models models = modelsService.queryById((Integer) model.get("model_id")); | |||
| // if (models == null){ | |||
| // throw new Exception("源模型不存在"); | |||
| // } | |||
| // model.put("model_name", models.getName()); | |||
| // } | |||
| // //父模型 | |||
| // modelDependency.setParentModels(JsonUtils.objectToJson(modelsList)); | |||
| // | |||
| // List<Map<String, Object>> datasetsList = (List<Map<String, Object>>) sourceMap.get("datasets"); | |||
| // for(int i=0;i<datasetsList.size();i++){ | |||
| // Map<String, Object> datasets = datasetsList.get(i); | |||
| // Dataset dataset = datasetService.queryById((Integer) datasets.get("dataset_id")); | |||
| // if (dataset == null){ | |||
| // throw new Exception("源数据集不存在"); | |||
| // } | |||
| // datasets.put("dataset_name", dataset.getName()); | |||
| // } | |||
| // //训练数据集 | |||
| // modelDependency.setTrainDataset(JsonUtils.objectToJson(datasetsList)); | |||
| // | |||
| // TrainTaskDepency trainTaskDepency = new TrainTaskDepency(); | |||
| // trainTaskDepency.setTaskId(key); | |||
| // trainTaskDepency.setInsId(experimentInsId); | |||
| // trainTaskDepency.setName(experimentName); | |||
| // //训练任务 | |||
| // modelDependency.setTrainTask(JsonUtils.objectToJson(trainTaskDepency)); | |||
| // modelDependency.setExpInsId(experimentInsId); | |||
| // //处理test数据 | |||
| // List<Map<String, Object>> testDatasetsList = (List<Map<String, Object>>) modelDel.get("test"); | |||
| // List<Map<String, Object>> resultTestDatasets = new ArrayList<Map<String, Object>>(); | |||
| // for(int i=0;i<testDatasetsList.size();i++){ | |||
| // Map<String, Object> datasets = testDatasetsList.get(i); | |||
| // List<Map<String, Object>> realDataSetList = (List<Map<String, Object>>) datasets.get("datasets"); | |||
| // for(int j=0;j<realDataSetList.size();j++){ | |||
| // Map<String, Object> realDataSet = realDataSetList.get(j); | |||
| // Dataset dataset = datasetService.queryById((Integer) realDataSet.get("dataset_id")); | |||
| // if (dataset == null){ | |||
| // throw new Exception("源数据集不存在"); | |||
| // } | |||
| // realDataSet.put("dataset_name", dataset.getName()); | |||
| // resultTestDatasets.add(realDataSet); | |||
| // } | |||
| // | |||
| // } | |||
| // //测试数据集 | |||
| // modelDependency.setTestDataset(JsonUtils.objectToJson(resultTestDatasets)); | |||
| // | |||
| // //检查是否存在target,如果存在说明在流水线用了节点导入,如果没有说明没有导入,等待手动push | |||
| // List<Map<String, Object>> modelTargetList = (List<Map<String, Object>>) modelDel.get("target"); | |||
| // if (modelTargetList==null||modelTargetList.size()==0){ | |||
| // modelDependency.setState(1); | |||
| // modelDependencyService.insert(modelDependency); | |||
| // }else { | |||
| // modelDependency.setState(2); | |||
| // for(int i=0;i<modelTargetList.size();i++){ | |||
| // Map<String, Object> model = modelTargetList.get(i); | |||
| // String version = null; | |||
| // //可能是参数,必须从实验参数读取 | |||
| // if (params != null) { | |||
| // for (Map<String, Object> param : params) { | |||
| // if (param.containsKey("param_name") && StringUtils.equals("model_version",(String) param.get("param_name"))) { | |||
| // version = param.get("param_value").toString(); | |||
| // } | |||
| // } | |||
| // } | |||
| // modelDependency.setVersion(StringUtils.isEmpty(version)?(String)model.get("model_version"):version); | |||
| // modelDependency.setCurrentModelId((Integer) model.get("model_id")); | |||
| // //因为可能有多成果模型,多次插入 | |||
| // modelDependencyService.insert(modelDependency); | |||
| // } | |||
| // } | |||
| // } | |||
| // } | |||
| @Override | |||
| public Experiment addAndRunExperiment(Experiment experiment) throws Exception { | |||
| @@ -332,7 +543,7 @@ public class ExperimentServiceImpl implements ExperimentService { | |||
| // 现在我们知道还有另一个具有相同名称的流水线 | |||
| Field[] fields = Experiment.class.getDeclaredFields(); | |||
| for (Field field : fields) { | |||
| field.setAccessible(true); // 使私有字段可访问 | |||
| field.setAccessible(true); | |||
| if ("name".equals(field.getName()) && field.isAnnotationPresent(CheckDuplicate.class)) { | |||
| // 如果字段是“name”并且标记了CheckDuplicate注解 | |||
| CheckDuplicate annotation = field.getAnnotation(CheckDuplicate.class); | |||
| @@ -1,7 +1,12 @@ | |||
| package com.ruoyi.platform.service.impl; | |||
| import com.ruoyi.common.redis.service.RedisService; | |||
| import com.ruoyi.common.security.utils.SecurityUtils; | |||
| import com.ruoyi.platform.domain.DevEnvironment; | |||
| import com.ruoyi.platform.mapper.DevEnvironmentDao; | |||
| import com.ruoyi.platform.service.DevEnvironmentService; | |||
| import com.ruoyi.platform.service.JupyterService; | |||
| import com.ruoyi.platform.utils.JacksonUtil; | |||
| import com.ruoyi.platform.utils.K8sClientUtil; | |||
| import com.ruoyi.platform.utils.MinioUtil; | |||
| import com.ruoyi.platform.utils.MlflowUtil; | |||
| @@ -13,6 +18,7 @@ import org.springframework.stereotype.Service; | |||
| import javax.annotation.Resource; | |||
| import java.io.InputStream; | |||
| import java.util.List; | |||
| import java.util.Map; | |||
| @Service | |||
| public class JupyterServiceImpl implements JupyterService { | |||
| @@ -39,6 +45,15 @@ public class JupyterServiceImpl implements JupyterService { | |||
| @Resource | |||
| private MlflowUtil mlflowUtil; | |||
| @Resource | |||
| private DevEnvironmentDao devEnvironmentDao; | |||
| @Resource | |||
| private DevEnvironmentService devEnvironmentService; | |||
| @Resource | |||
| private RedisService redisService; | |||
| public JupyterServiceImpl(MinioUtil minioUtil) { | |||
| this.minioUtil = minioUtil; | |||
| } | |||
| @@ -53,6 +68,54 @@ public class JupyterServiceImpl implements JupyterService { | |||
| return masterIp + ":" + podPort; | |||
| } | |||
| @Override | |||
| public String runJupyterService(Integer id) { | |||
| DevEnvironment devEnvironment = this.devEnvironmentDao.queryById(id); | |||
| String envName = devEnvironment.getName(); | |||
| //TODO 设置环境变量 | |||
| // 提取数据集,模型信息,得到数据集模型的path | |||
| Map<String, Object> dataset = JacksonUtil.parseJSONStr2Map(devEnvironment.getDataset()); | |||
| String datasetPath = (String) dataset.get("path"); | |||
| Map<String, Object> model = JacksonUtil.parseJSONStr2Map(devEnvironment.getModel()); | |||
| String modelPath = (String) model.get("path"); | |||
| LoginUser loginUser = SecurityUtils.getLoginUser(); | |||
| String podName = loginUser.getUsername().toLowerCase() + "-editor-pod"; | |||
| String pvcName = loginUser.getUsername().toLowerCase() + "-editor-pvc"; | |||
| V1PersistentVolumeClaim pvc = k8sClientUtil.createPvc(namespace, pvcName, storage, storageClassName); | |||
| //TODO 设置镜像可配置,这里先用默认镜像启动pod | |||
| // 调用修改后的 createPod 方法,传入额外的参数 | |||
| Integer podPort = k8sClientUtil.createConfiguredPod(podName, namespace, port, mountPath, pvc, image, datasetPath, modelPath); | |||
| return masterIp + ":" + podPort; | |||
| } | |||
| @Override | |||
| public String stopJupyterService(Integer id) throws Exception { | |||
| DevEnvironment devEnvironment = this.devEnvironmentDao.queryById(id); | |||
| if (devEnvironment==null){ | |||
| throw new Exception("开发环境配置不存在"); | |||
| } | |||
| LoginUser loginUser = SecurityUtils.getLoginUser(); | |||
| String podName = loginUser.getUsername().toLowerCase() + "-editor-pod"; | |||
| // 使用 Kubernetes API 删除 Pod | |||
| String deleteResult = k8sClientUtil.deletePod(podName, namespace); | |||
| // 检查 Pod 是否存在 | |||
| boolean exists = k8sClientUtil.checkPodExists(podName, namespace); | |||
| if (exists) { | |||
| throw new Exception("Pod " + podName + " 删除失败"); | |||
| } | |||
| return deleteResult + ",编辑器已停止"; | |||
| } | |||
| @Override | |||
| public void upload(InputStream inputStream) { | |||
| try { | |||
| @@ -71,4 +134,6 @@ public class JupyterServiceImpl implements JupyterService { | |||
| } | |||
| } | |||
| @@ -0,0 +1,252 @@ | |||
| package com.ruoyi.platform.service.impl; | |||
| import com.ruoyi.common.security.utils.SecurityUtils; | |||
| import com.ruoyi.platform.domain.*; | |||
| import com.ruoyi.platform.mapper.ModelDependencyDao; | |||
| import com.ruoyi.platform.service.*; | |||
| import com.ruoyi.platform.utils.JacksonUtil; | |||
| import com.ruoyi.platform.vo.ModelDependcyTreeVo; | |||
| import com.ruoyi.platform.vo.ModelVersionDependcyVo; | |||
| import com.ruoyi.system.api.model.LoginUser; | |||
| import org.apache.commons.lang3.StringUtils; | |||
| import org.springframework.context.annotation.Lazy; | |||
| import org.springframework.stereotype.Service; | |||
| import org.springframework.data.domain.Page; | |||
| import org.springframework.data.domain.PageImpl; | |||
| import org.springframework.data.domain.PageRequest; | |||
| import javax.annotation.Resource; | |||
| import java.io.IOException; | |||
| import java.util.ArrayList; | |||
| import java.util.Date; | |||
| import java.util.List; | |||
| import java.util.Map; | |||
| import java.util.stream.Collectors; | |||
| /** | |||
| * (ModelDependency)表服务实现类 | |||
| * | |||
| * @author Xidaray | |||
| * @since 2024-05-29 13:51:23 | |||
| */ | |||
| @Service("modelDependencyService") | |||
| public class ModelDependencyServiceImpl implements ModelDependencyService { | |||
| @Resource | |||
| private ModelDependencyDao modelDependencyDao; | |||
| @Resource | |||
| private ModelsService modelsService; | |||
| @Resource | |||
| private ModelsVersionService modelsVersionService; | |||
| @Lazy | |||
| @Resource | |||
| private ExperimentService experimentService; | |||
| @Lazy | |||
| @Resource | |||
| private ExperimentInsService experimentInsService; | |||
| /** | |||
| * 通过ID查询单条数据 | |||
| * | |||
| * @param id 主键 | |||
| * @return 实例对象 | |||
| */ | |||
| @Override | |||
| public ModelDependency queryById(Integer id) { | |||
| return this.modelDependencyDao.queryById(id); | |||
| } | |||
| /** | |||
| * 分页查询 | |||
| * | |||
| * @param modelDependency 筛选条件 | |||
| * @param pageRequest 分页对象 | |||
| * @return 查询结果 | |||
| */ | |||
| @Override | |||
| public Page<ModelDependency> queryByPage(ModelDependency modelDependency, PageRequest pageRequest) { | |||
| long total = this.modelDependencyDao.count(modelDependency); | |||
| return new PageImpl<>(this.modelDependencyDao.queryAllByLimit(modelDependency, pageRequest), pageRequest, total); | |||
| } | |||
| /** | |||
| * 根据对象查询 | |||
| * | |||
| * @param modelDependency 筛选条件 | |||
| * @return 查询结果 | |||
| */ | |||
| @Override | |||
| public List<ModelDependency> queryByModelDependency(ModelDependency modelDependency) throws IOException { | |||
| List<ModelDependency> modelDependencyList = this.modelDependencyDao.queryByModelDependency(modelDependency); | |||
| return modelDependencyList; | |||
| } | |||
| @Override | |||
| public ModelDependcyTreeVo getModelDependencyTree(ModelDependency modelDependencyQuery) throws Exception { | |||
| //查询当前模型 | |||
| modelDependencyQuery.setState(1); | |||
| List<ModelDependency> modelDependencyList = this.queryByModelDependency(modelDependencyQuery); | |||
| if (modelDependencyList==null || modelDependencyList.size()==0){ | |||
| throw new Exception("当前模型依赖关系不存在"); | |||
| } | |||
| ModelDependency modelDependency = modelDependencyList.get(0); | |||
| ModelDependcyTreeVo modelDependcyTreeVo = ModelDependencyConvertToTree(modelDependency); | |||
| //递归父模型 | |||
| processParentModel(modelDependcyTreeVo); | |||
| //递归子模型 | |||
| processChildrenModel(modelDependcyTreeVo); | |||
| return modelDependcyTreeVo; | |||
| } | |||
| /** | |||
| * 递归父模型 | |||
| * @param modelDependcyTreeVo | |||
| */ | |||
| private void processParentModel(ModelDependcyTreeVo modelDependcyTreeVo) throws IOException { | |||
| if (modelDependcyTreeVo.getParentModelsMap() != null) { | |||
| List<Map<String, Object>> parentMaps = modelDependcyTreeVo.getParentModelsMap(); | |||
| List<ModelDependcyTreeVo> ps = new ArrayList<ModelDependcyTreeVo>(); | |||
| for (Map<String, Object> parent:parentMaps) { | |||
| Integer model_id = (Integer) parent.get("model_id"); | |||
| String version = (String) parent.get("model_version"); | |||
| ModelDependency modelDependencyQuery = new ModelDependency(); | |||
| modelDependencyQuery.setVersion(version); | |||
| modelDependencyQuery.setCurrentModelId(model_id); | |||
| List<ModelDependency> modelDependencyList = this.queryByModelDependency(modelDependencyQuery); | |||
| if (modelDependencyList!=null&&modelDependencyList.size()>=0){ | |||
| for (ModelDependency modelDependency:modelDependencyList){ | |||
| ModelDependcyTreeVo modelDependencyTreeVoIn = ModelDependencyConvertToTree(modelDependency); | |||
| processParentModel(modelDependencyTreeVoIn); | |||
| ps.add(modelDependencyTreeVoIn); | |||
| } | |||
| } | |||
| } | |||
| modelDependcyTreeVo.setParentModels(ps); | |||
| } | |||
| } | |||
| private void processChildrenModel(ModelDependcyTreeVo modelDependcyTreeVo) throws IOException { | |||
| String version = modelDependcyTreeVo.getVersion(); | |||
| Integer modelId = modelDependcyTreeVo.getCurrentModelId(); | |||
| List<ModelDependcyTreeVo> cs = new ArrayList<ModelDependcyTreeVo>(); | |||
| //查儿子们 | |||
| List<ModelDependency> modelDependencyList = modelDependencyDao.queryChildrenByVersionId("\"model_id\":"+modelId, "\"model_version\":\""+version+"\""); | |||
| if (modelDependencyList!=null&&modelDependencyList.size()>=0){ | |||
| for (ModelDependency modelDependency:modelDependencyList){ | |||
| ModelDependcyTreeVo modelDependencyTreeVoIn = ModelDependencyConvertToTree(modelDependency); | |||
| processChildrenModel(modelDependencyTreeVoIn); | |||
| cs.add(modelDependencyTreeVoIn); | |||
| } | |||
| } | |||
| modelDependcyTreeVo.setChildrenModels(cs); | |||
| } | |||
| private ModelDependcyTreeVo ModelDependencyConvertToTree(ModelDependency modelDependency) throws IOException { | |||
| ModelDependcyTreeVo modelDependcyTreeVo = new ModelDependcyTreeVo(); | |||
| modelDependcyTreeVo.setCurrentModelId(modelDependency.getCurrentModelId()); | |||
| modelDependcyTreeVo.setExpInsId(modelDependency.getExpInsId()); | |||
| modelDependcyTreeVo.setVersion(modelDependency.getVersion()); | |||
| modelDependcyTreeVo.setRefItem(modelDependency.getRefItem()); | |||
| modelDependcyTreeVo.setTrainTask(JacksonUtil.parseJSONStr2Map(modelDependency.getTrainTask())); | |||
| modelDependcyTreeVo.setTrainDataset(JacksonUtil.parseJSONStr2MapList(modelDependency.getTrainDataset())); | |||
| modelDependcyTreeVo.setTrainImage(modelDependency.getTrainImage()); | |||
| modelDependcyTreeVo.setTrainParams(JacksonUtil.parseJSONStr2TList(modelDependency.getTrainParams(),Object.class,null)); | |||
| modelDependcyTreeVo.setTestDataset(JacksonUtil.parseJSONStr2MapList(modelDependency.getTestDataset())); | |||
| modelDependcyTreeVo.setProjectDependency(JacksonUtil.parseJSONStr2Map(modelDependency.getProjectDependency())); | |||
| modelDependcyTreeVo.setParentModelsMap(JacksonUtil.parseJSONStr2MapList(modelDependency.getParentModels())); | |||
| /** | |||
| * 补充workFlow_id + 是否共有 | |||
| */ | |||
| Integer currentModelId = modelDependency.getCurrentModelId(); | |||
| Integer expInsId = modelDependency.getExpInsId(); | |||
| Models models = modelsService.queryById(currentModelId); | |||
| ModelsVersion modelsVersionquery = new ModelsVersion(); | |||
| modelsVersionquery.setModelsId(currentModelId); | |||
| modelsVersionquery.setVersion(modelDependency.getVersion()); | |||
| ModelsVersion modelsVersion = modelsVersionService.queryByModelsVersion(modelsVersionquery); | |||
| ExperimentIns experimentIns = experimentInsService.queryById(expInsId); | |||
| Experiment experiment = experimentService.queryById(experimentIns.getExperimentId()); | |||
| ModelVersionDependcyVo modelVersionDependcyVo = new ModelVersionDependcyVo(); | |||
| modelVersionDependcyVo.setName(models.getName()); | |||
| modelVersionDependcyVo.setAvailableRange(models.getAvailableRange()); | |||
| modelVersionDependcyVo.setDescription(models.getDescription()); | |||
| modelVersionDependcyVo.setModelTag(models.getModelTag()); | |||
| modelVersionDependcyVo.setModelType(models.getModelType()); | |||
| modelVersionDependcyVo.setModelTagName(models.getModelTagName()); | |||
| modelVersionDependcyVo.setModelTypeName(models.getModelTypeName()); | |||
| modelVersionDependcyVo.setFileName(modelsVersion.getFileName()); | |||
| modelVersionDependcyVo.setFileSize(modelsVersion.getFileSize()); | |||
| modelVersionDependcyVo.setUrl(modelsVersion.getUrl()); | |||
| modelDependcyTreeVo.setWorkflowId(experiment.getWorkflowId()); | |||
| modelDependcyTreeVo.setModelVersionDependcyVo(modelVersionDependcyVo); | |||
| return modelDependcyTreeVo; | |||
| } | |||
| /** | |||
| * 新增数据 | |||
| * | |||
| * @param modelDependency 实例对象 | |||
| * @return 实例对象 | |||
| */ | |||
| @Override | |||
| public ModelDependency insert(ModelDependency modelDependency) { | |||
| //插入预备,此时不需要判断版本重复 | |||
| LoginUser loginUser = SecurityUtils.getLoginUser(); | |||
| modelDependency.setCreateBy(loginUser.getUsername()); | |||
| modelDependency.setUpdateBy(loginUser.getUsername()); | |||
| modelDependency.setUpdateTime(new Date()); | |||
| modelDependency.setCreateTime(new Date()); | |||
| this.modelDependencyDao.insert(modelDependency); | |||
| return modelDependency; | |||
| } | |||
| /** | |||
| * 修改数据 | |||
| * | |||
| * @param modelDependency 实例对象 | |||
| * @return 实例对象 | |||
| */ | |||
| @Override | |||
| public ModelDependency update(ModelDependency modelDependency) { | |||
| LoginUser loginUser = SecurityUtils.getLoginUser(); | |||
| modelDependency.setUpdateBy(loginUser.getUsername()); | |||
| modelDependency.setUpdateTime(new Date()); | |||
| this.modelDependencyDao.update(modelDependency); | |||
| return this.queryById(modelDependency.getId()); | |||
| } | |||
| /** | |||
| * 通过主键删除数据 | |||
| * | |||
| * @param id 主键 | |||
| * @return 是否成功 | |||
| */ | |||
| @Override | |||
| public boolean deleteById(Integer id) { | |||
| return this.modelDependencyDao.deleteById(id) > 0; | |||
| } | |||
| @Override | |||
| public String removeById(Integer id) { | |||
| ModelDependency modelDependency = this.modelDependencyDao.queryById(id); | |||
| if (modelDependency == null){ | |||
| return "模型依赖信息不存在"; | |||
| } | |||
| //判断权限,只有admin和创建者本身可以删除该数据集 | |||
| LoginUser loginUser = SecurityUtils.getLoginUser(); | |||
| String username = loginUser.getUsername(); | |||
| String createdBy = modelDependency.getCreateBy(); | |||
| if (!(StringUtils.equals(username,"admin") || StringUtils.equals(username,createdBy))){ | |||
| return "无权限删除"; | |||
| } | |||
| modelDependency.setState(0); | |||
| return this.modelDependencyDao.update(modelDependency)>0?"删除成功":"删除失败"; | |||
| } | |||
| } | |||
| @@ -192,6 +192,7 @@ public class ModelsServiceImpl implements ModelsService { | |||
| * | |||
| * @param id models_version表的主键 | |||
| * @return 文件内容 | |||
| * | |||
| */ | |||
| @Override | |||
| @@ -3,20 +3,24 @@ package com.ruoyi.platform.service.impl; | |||
| import com.ruoyi.common.security.utils.SecurityUtils; | |||
| import com.ruoyi.platform.annotations.CheckDuplicate; | |||
| import com.ruoyi.platform.domain.Dataset; | |||
| import com.ruoyi.platform.domain.ModelDependency; | |||
| import com.ruoyi.platform.domain.Models; | |||
| import com.ruoyi.platform.domain.ModelsVersion; | |||
| import com.ruoyi.platform.mapper.ModelsDao; | |||
| import com.ruoyi.platform.mapper.ModelsVersionDao; | |||
| import com.ruoyi.platform.service.ModelDependencyService; | |||
| import com.ruoyi.platform.service.ModelsVersionService; | |||
| import com.ruoyi.system.api.model.LoginUser; | |||
| import org.apache.commons.lang3.StringUtils; | |||
| import org.springframework.beans.factory.annotation.Value; | |||
| import org.springframework.context.annotation.Lazy; | |||
| import org.springframework.data.domain.Page; | |||
| import org.springframework.data.domain.PageImpl; | |||
| import org.springframework.data.domain.PageRequest; | |||
| import org.springframework.stereotype.Service; | |||
| import javax.annotation.Resource; | |||
| import java.io.IOException; | |||
| import java.lang.reflect.Field; | |||
| import java.util.Date; | |||
| import java.util.HashMap; | |||
| @@ -36,7 +40,9 @@ public class ModelsVersionServiceImpl implements ModelsVersionService { | |||
| @Resource | |||
| private ModelsDao modelsDao; | |||
| @Resource | |||
| @Lazy | |||
| private ModelDependencyService modelDependencyService; | |||
| // 固定存储桶名 | |||
| @Value("${minio.dataReleaseBucketName}") | |||
| private String bucketName; | |||
| @@ -81,6 +87,7 @@ public class ModelsVersionServiceImpl implements ModelsVersionService { | |||
| modelsVersion.setCreateTime(new Date()); | |||
| modelsVersion.setState(1); | |||
| this.modelsVersionDao.insert(modelsVersion); | |||
| insertModelsDependency(modelsVersion); | |||
| return modelsVersion; | |||
| } | |||
| @@ -191,7 +198,7 @@ public class ModelsVersionServiceImpl implements ModelsVersionService { | |||
| } | |||
| @Override | |||
| public Map<Integer, String> deleteModelsVersion(Integer modelsId, String version) { | |||
| public Map<Integer, String> deleteModelsVersion(Integer modelsId, String version) throws IOException { | |||
| Map<Integer, String> results = new HashMap<Integer,String>(); | |||
| // 根据模型ID和版本查询所有模型版本 | |||
| List<ModelsVersion> versions = this.modelsVersionDao.queryAllByModelsVersion(modelsId, version); | |||
| @@ -200,6 +207,16 @@ public class ModelsVersionServiceImpl implements ModelsVersionService { | |||
| String result = this.removeById(modelsVersion.getId()); | |||
| results.put(modelsVersion.getId(), result); | |||
| } | |||
| // 删除依赖关系 | |||
| ModelDependency modelDependency = new ModelDependency(); | |||
| modelDependency.setCurrentModelId(modelsId); | |||
| modelDependency.setVersion(version); | |||
| modelDependency.setState(1); | |||
| List<ModelDependency> modelDependencyList = modelDependencyService.queryByModelDependency(modelDependency); | |||
| if (modelDependencyList.size()>0){ | |||
| ModelDependency modelDependency1 = modelDependencyList.get(0); | |||
| modelDependencyService.removeById(modelDependency1.getId()); | |||
| } | |||
| return results; | |||
| } | |||
| @@ -210,6 +227,7 @@ public class ModelsVersionServiceImpl implements ModelsVersionService { | |||
| for(ModelsVersion modelsVersion : modelsVersions) { | |||
| insertPrepare(modelsVersion); | |||
| } | |||
| insertModelsDependency(modelsVersions.get(0)); | |||
| this.modelsVersionDao.insertBatch(modelsVersions); | |||
| return "新增模型版本成功"; | |||
| } catch (Exception e) { | |||
| @@ -248,4 +266,23 @@ public class ModelsVersionServiceImpl implements ModelsVersionService { | |||
| } | |||
| //新增模型依赖关系 | |||
| private void insertModelsDependency(ModelsVersion modelsVersion) throws Exception { | |||
| ModelDependency modelDependency = new ModelDependency(); | |||
| modelDependency.setCurrentModelId(modelsVersion.getModelsId()); | |||
| modelDependency.setVersion(modelsVersion.getVersion()); | |||
| modelDependency.setState(2); | |||
| List<ModelDependency> modelDependencyList = modelDependencyService.queryByModelDependency(modelDependency); | |||
| if (modelDependencyList != null && modelDependencyList.size()>0){ | |||
| //查到2,说明是之前流水线推送的,你就直接该状态生效就完了 | |||
| ModelDependency modelDependency1 = modelDependencyList.get(0); | |||
| modelDependency1.setState(1); | |||
| modelDependencyService.update(modelDependency1); | |||
| }else { | |||
| modelDependency.setState(1); | |||
| modelDependencyService.insert(modelDependency); | |||
| } | |||
| } | |||
| } | |||
| @@ -110,8 +110,9 @@ public class WorkflowServiceImpl implements WorkflowService { | |||
| * @return 实例对象 | |||
| */ | |||
| @Override | |||
| public Workflow update(Workflow workflow) { | |||
| public Workflow update(Workflow workflow) throws Exception { | |||
| LoginUser loginUser = SecurityUtils.getLoginUser(); | |||
| checkDeclaredName(workflow); | |||
| workflow.setUpdateBy(loginUser.getUsername()); | |||
| workflow.setUpdateTime(new Date()); | |||
| this.workflowDao.update(workflow); | |||
| @@ -207,10 +208,9 @@ public class WorkflowServiceImpl implements WorkflowService { | |||
| // 这是相同的流水线,更新操作中没有重复名称问题 | |||
| return; | |||
| } | |||
| // 现在我们知道还有另一个具有相同名称的流水线 | |||
| Field[] fields = Workflow.class.getDeclaredFields(); | |||
| for (Field field : fields) { | |||
| field.setAccessible(true); // 使私有字段可访问 | |||
| field.setAccessible(true); | |||
| if ("name".equals(field.getName()) && field.isAnnotationPresent(CheckDuplicate.class)) { | |||
| // 如果字段是“name”并且标记了CheckDuplicate注解 | |||
| CheckDuplicate annotation = field.getAnnotation(CheckDuplicate.class); | |||
| @@ -103,6 +103,7 @@ public class WorkspaceServiceImpl implements WorkspaceService { | |||
| assetCountMap.put("image", imageCount); | |||
| //统计组件数量 | |||
| Component component = new Component(); | |||
| component.setAvailableRange(availableRange); | |||
| Integer componentCount = (int) this.componentDao.count(component); | |||
| assetCountMap.put("component", componentCount); | |||
| //统计流水线数量 | |||
| @@ -5,9 +5,12 @@ import com.fasterxml.jackson.databind.DeserializationFeature; | |||
| import com.fasterxml.jackson.databind.ObjectMapper; | |||
| import com.fasterxml.jackson.databind.SerializationFeature; | |||
| import com.fasterxml.jackson.databind.type.CollectionType; | |||
| import com.ruoyi.common.core.utils.StringUtils; | |||
| import org.apache.xmlbeans.impl.xb.xsdschema.Public; | |||
| import java.text.SimpleDateFormat; | |||
| import java.util.ArrayList; | |||
| import java.util.HashMap; | |||
| import java.util.List; | |||
| import java.util.Map; | |||
| @@ -56,6 +59,21 @@ public class JacksonUtil { | |||
| } | |||
| } | |||
| public static String replaceInAarry(String res, List<Map<String, Object>> params) { | |||
| // 解析 JSON 数组 | |||
| if (params == null) { | |||
| return res; | |||
| } | |||
| for (int i = 0; i < params.size(); i++) { | |||
| Map<String, Object> stringObjectMap = params.get(i); | |||
| if (res.contains("${" + stringObjectMap.get("param_name") + "}")) { | |||
| res = res.replace("${" + stringObjectMap.get("param_name") + "}", String.valueOf( stringObjectMap.get("param_value"))); | |||
| } | |||
| } | |||
| return res; | |||
| } | |||
| /** | |||
| * 获取ObjectMapper。其本身是线程安全的,可以作为成员变量,但传入的参数不可能每次都一样,所以不使用成员变量。 | |||
| * | |||
| @@ -140,6 +158,7 @@ public class JacksonUtil { | |||
| */ | |||
| public static Map<String, Object> parseJSONStr2Map(String jsonStr) { | |||
| try { | |||
| if (StringUtils.isEmpty(jsonStr)) {return new HashMap<String, Object>();} | |||
| // 对于json字符串新增的字段,由于返回的是map,不管 compatNewProps 设置成什么值都不会抛出异常 | |||
| ObjectMapper objectMapper = getObjectMapper(null, false, false, true); | |||
| return objectMapper.readValue(jsonStr, Map.class); | |||
| @@ -158,6 +177,7 @@ public class JacksonUtil { | |||
| */ | |||
| public static List<Map<String, Object>> parseJSONStr2MapList(String jsonStr) { | |||
| try { | |||
| if (StringUtils.isEmpty(jsonStr)) {return new ArrayList<>();} | |||
| // 对于json字符串新增的字段,由于返回的是map,不管 compatNewProps 设置成什么值都不会抛出异常 | |||
| ObjectMapper objectMapper = getObjectMapper(null, false, false, true); | |||
| CollectionType listType = objectMapper.getTypeFactory().constructCollectionType(ArrayList.class, Map.class); | |||
| @@ -22,9 +22,7 @@ import org.springframework.stereotype.Component; | |||
| import javax.annotation.PostConstruct; | |||
| import java.io.BufferedReader; | |||
| import java.io.InputStreamReader; | |||
| import java.util.HashMap; | |||
| import java.util.LinkedHashMap; | |||
| import java.util.Map; | |||
| import java.util.*; | |||
| /** | |||
| * k8s客户端 | |||
| @@ -282,13 +280,13 @@ public class K8sClientUtil { | |||
| .endSpec() | |||
| .build(); | |||
| try { | |||
| pod = api.createNamespacedPod(namespace, pod, null, null, null); | |||
| } catch (ApiException e) { | |||
| log.error("创建pod异常:" + e.getResponseBody(), e); | |||
| } catch (Exception e) { | |||
| log.error("创建pod系统异常:", e); | |||
| } | |||
| V1Service service = createService(namespace, podName + "-svc", port, selector); | |||
| @@ -324,7 +322,6 @@ public class K8sClientUtil { | |||
| for (V1Pod pod1 : v1PodList.getItems()) { | |||
| if (StringUtils.equals(pod1.getMetadata().getName(), podName)) { | |||
| // PVC 已存在 | |||
| V1Service service = createService(namespace, podName + "-svc", port, selector); | |||
| if (service != null) { | |||
| return service.getSpec().getPorts().get(0).getNodePort(); | |||
| @@ -378,6 +375,73 @@ public class K8sClientUtil { | |||
| return service.getSpec().getPorts().get(0).getNodePort(); | |||
| } | |||
| public Integer createConfiguredPod(String podName, String namespace, Integer port, String mountPath, V1PersistentVolumeClaim pvc, String image, String datasetPath, String modelPath) { | |||
| Map<String, String> selector = new LinkedHashMap<>(); | |||
| selector.put("k8s-jupyter", podName); | |||
| CoreV1Api api = new CoreV1Api(apiClient); | |||
| V1PodList v1PodList = null; | |||
| try { | |||
| v1PodList = api.listNamespacedPod(namespace, null, null, null, null, null, null, null, null, null, null); | |||
| } catch (ApiException e) { | |||
| log.error("获取 POD 异常:", e); | |||
| } | |||
| if (v1PodList != null) { | |||
| for (V1Pod pod1 : v1PodList.getItems()) { | |||
| // PVC 已存在 | |||
| if (StringUtils.equals(pod1.getMetadata().getName(), podName)) { | |||
| V1Service service = createService(namespace, podName + "-svc", port, selector); | |||
| if (service != null) { | |||
| return service.getSpec().getPorts().get(0).getNodePort(); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| // 配置卷和卷挂载 | |||
| List<V1VolumeMount> volumeMounts = new ArrayList<>(); | |||
| volumeMounts.add(new V1VolumeMount().name("workspace").mountPath(mountPath)); | |||
| volumeMounts.add(new V1VolumeMount().name("dataset").mountPath("/datasets").subPath(datasetPath).readOnly(true)); | |||
| volumeMounts.add(new V1VolumeMount().name("model").mountPath("/model").subPath(modelPath).readOnly(true)); | |||
| List<V1Volume> volumes = new ArrayList<>(); | |||
| volumes.add(new V1Volume().name("workspace").persistentVolumeClaim(new V1PersistentVolumeClaimVolumeSource().claimName(pvc.getMetadata().getName()))); | |||
| volumes.add(new V1Volume().name("dataset").persistentVolumeClaim(new V1PersistentVolumeClaimVolumeSource().claimName(pvc.getMetadata().getName()))); | |||
| volumes.add(new V1Volume().name("model").persistentVolumeClaim(new V1PersistentVolumeClaimVolumeSource().claimName(pvc.getMetadata().getName()))); | |||
| V1Pod pod = new V1PodBuilder() | |||
| .withNewMetadata() | |||
| .withName(podName) | |||
| .withLabels(selector) | |||
| .endMetadata() | |||
| .withNewSpec() | |||
| .addNewContainer() | |||
| .withName(podName) | |||
| .withImage(image) | |||
| .withPorts(new V1ContainerPort().containerPort(port).protocol("TCP")) | |||
| .withVolumeMounts(volumeMounts) | |||
| .endContainer() | |||
| .withVolumes(volumes) | |||
| .withTerminationGracePeriodSeconds(14400L) | |||
| .endSpec() | |||
| .build(); | |||
| try { | |||
| pod = api.createNamespacedPod(namespace, pod, null, null, null); | |||
| } catch (ApiException e) { | |||
| log.error("创建pod异常:" + e.getResponseBody(), e); | |||
| } catch (Exception e) { | |||
| log.error("创建pod系统异常:", e); | |||
| } | |||
| V1Service service = createService(namespace, podName + "-svc", port, selector); | |||
| return service.getSpec().getPorts().get(0).getNodePort(); | |||
| } | |||
| /** | |||
| * 根据获取namespace,deploymentName的Pod Name | |||
| * | |||
| @@ -495,4 +559,51 @@ public class K8sClientUtil { | |||
| } | |||
| return pod; | |||
| } | |||
| /** | |||
| * 删除 Pod | |||
| * | |||
| * @param podName Pod 名称 | |||
| * @param namespace 命名空间 | |||
| * @throws ApiException 异常 | |||
| */ | |||
| public String deletePod(String podName, String namespace) throws ApiException { | |||
| CoreV1Api api = new CoreV1Api(apiClient); | |||
| try { | |||
| V1Pod pod = api.deleteNamespacedPod(podName, namespace, null, null, null, null, null, null); | |||
| return "Pod " + podName + " 删除请求已发送"; | |||
| } catch (ApiException e) { | |||
| if (e.getCode() == 404) { | |||
| return "Pod " + podName + " 不存在"; | |||
| } else { | |||
| log.error("删除pod异常:" + e.getResponseBody(), e); | |||
| throw e; | |||
| } | |||
| } | |||
| } | |||
| /** | |||
| * 检查 Pod 是否存在 | |||
| * | |||
| * @param podName Pod 名称 | |||
| * @param namespace 命名空间 | |||
| * @return 是否存在 | |||
| * @throws ApiException 异常 | |||
| */ | |||
| public boolean checkPodExists(String podName, String namespace) throws ApiException { | |||
| CoreV1Api api = new CoreV1Api(apiClient); | |||
| try { | |||
| api.readNamespacedPod(podName, namespace, null,false,false); | |||
| return true; | |||
| } catch (ApiException e) { | |||
| if (e.getCode() == 404) { | |||
| return false; | |||
| } else { | |||
| log.error("检查pod存在性异常:" + e.getResponseBody(), e); | |||
| throw e; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,72 @@ | |||
| package com.ruoyi.platform.vo; | |||
| import com.fasterxml.jackson.databind.PropertyNamingStrategy; | |||
| import com.fasterxml.jackson.databind.annotation.JsonNaming; | |||
| import com.ruoyi.platform.domain.Models; | |||
| import lombok.Data; | |||
| import java.util.List; | |||
| import java.util.Map; | |||
| @Data | |||
| @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) | |||
| public class ModelDependcyTreeVo { | |||
| /** | |||
| * 当前模型id | |||
| */ | |||
| private Integer currentModelId; | |||
| /** | |||
| * 实验实例id | |||
| */ | |||
| private Integer expInsId; | |||
| /** | |||
| * 版本 | |||
| */ | |||
| private String version; | |||
| /** | |||
| * 引用项目 | |||
| */ | |||
| private String refItem; | |||
| /** | |||
| * 训练任务 | |||
| */ | |||
| private Map trainTask; | |||
| /** | |||
| * 训练数据集 | |||
| */ | |||
| private List<Map<String, Object>> trainDataset; | |||
| /** | |||
| * 训练参数 | |||
| */ | |||
| private List trainParams; | |||
| /** | |||
| * 训练镜像 | |||
| */ | |||
| private String trainImage; | |||
| /** | |||
| * 测试数据集 | |||
| */ | |||
| private List<Map<String, Object>> testDataset; | |||
| /** | |||
| * 依赖项目 | |||
| */ | |||
| private Map projectDependency; | |||
| private List<Map<String, Object>> parentModelsMap; | |||
| /** | |||
| * 父模型 | |||
| */ | |||
| private List<ModelDependcyTreeVo> parentModels; | |||
| /** | |||
| * 子模型 | |||
| */ | |||
| private List<ModelDependcyTreeVo> childrenModels; | |||
| private Long workflowId; | |||
| private ModelVersionDependcyVo modelVersionDependcyVo; | |||
| } | |||
| @@ -0,0 +1,48 @@ | |||
| package com.ruoyi.platform.vo; | |||
| import com.fasterxml.jackson.databind.PropertyNamingStrategy; | |||
| import com.fasterxml.jackson.databind.annotation.JsonNaming; | |||
| import com.ruoyi.platform.annotations.CheckDuplicate; | |||
| import io.swagger.annotations.ApiModelProperty; | |||
| import lombok.Data; | |||
| import java.io.Serializable; | |||
| @Data | |||
| @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) | |||
| public class ModelVersionDependcyVo implements Serializable { | |||
| @ApiModelProperty(name = "name") | |||
| private String name; | |||
| // private String version; | |||
| @ApiModelProperty(name = "description") | |||
| private String description; | |||
| @ApiModelProperty(value = "模型可见范围,1表示公开,0表示私有") | |||
| private int availableRange; | |||
| @ApiModelProperty(value = "模型类型(模型框架)") | |||
| private String modelType; | |||
| @ApiModelProperty(value = "模型标签") | |||
| private String modelTag; | |||
| @ApiModelProperty(value = "模型类型名") | |||
| private String modelTypeName; | |||
| @ApiModelProperty(value = "模型tag名") | |||
| private String modelTagName; | |||
| @ApiModelProperty(value = "模型存储地址") | |||
| private String url; | |||
| @ApiModelProperty(value = "文件名") | |||
| private String fileName; | |||
| @ApiModelProperty(value = "文件大小") | |||
| private String fileSize; | |||
| } | |||
| @@ -16,6 +16,7 @@ | |||
| <result property="mountPath" column="mount_path" jdbcType="VARCHAR"/> | |||
| <result property="inParameters" column="in_parameters" jdbcType="VARCHAR"/> | |||
| <result property="outParameters" column="out_parameters" jdbcType="VARCHAR"/> | |||
| <result property="availableRange" column="available_range" jdbcType="INTEGER"/> | |||
| <result property="description" column="description" jdbcType="VARCHAR"/> | |||
| <result property="iconPath" column="icon_path" jdbcType="VARCHAR"/> | |||
| <result property="createBy" column="create_by" jdbcType="VARCHAR"/> | |||
| @@ -28,7 +29,7 @@ | |||
| <!--查询单个--> | |||
| <select id="queryById" resultMap="ComponentMap"> | |||
| select | |||
| id,category_id,component_name,component_Label,images,working_directory,command,env_virables,resources_standard,control_strategy,mount_path,in_parameters,out_parameters,description,icon_path,create_by,create_time,update_by,update_time,state | |||
| id,category_id,component_name,component_Label,images,working_directory,command,env_virables,resources_standard,control_strategy,mount_path,in_parameters,out_parameters,available_range,description,icon_path,create_by,create_time,update_by,update_time,state | |||
| from component | |||
| where id = #{id} and state = 1 | |||
| </select> | |||
| @@ -42,7 +43,7 @@ | |||
| <!--查询指定行数据--> | |||
| <select id="queryAllByLimit" resultMap="ComponentMap"> | |||
| select | |||
| id,category_id,component_name,component_Label,images,working_directory,command,env_virables,resources_standard,control_strategy,mount_path,in_parameters,out_parameters,description,icon_path,create_by,create_time,update_by,update_time,state | |||
| id,category_id,component_name,component_Label,images,working_directory,command,env_virables,resources_standard,control_strategy,mount_path,in_parameters,out_parameters,available_range,description,icon_path,create_by,create_time,update_by,update_time,state | |||
| from component | |||
| <where> | |||
| state = 1 | |||
| @@ -85,6 +86,9 @@ | |||
| <if test="component.outParameters != null and component.outParameters != ''"> | |||
| and out_parameters = #{component.outParameters} | |||
| </if> | |||
| <if test="component.availableRange != null"> | |||
| and available_range = #{component.availableRange} | |||
| </if> | |||
| <if test="component.description != null and component.description != ''"> | |||
| and description = #{component.description} | |||
| </if> | |||
| @@ -155,6 +159,9 @@ | |||
| <if test="component.outParameters != null and component.outParameters != ''"> | |||
| and out_parameters = #{component.outParameters} | |||
| </if> | |||
| <if test="component.availableRange != null"> | |||
| and available_range = #{component.availableRange} | |||
| </if> | |||
| <if test="component.description != null and component.description != ''"> | |||
| and description = #{component.description} | |||
| </if> | |||
| @@ -190,23 +197,23 @@ | |||
| <!--新增所有列--> | |||
| <insert id="insert" keyProperty="id" useGeneratedKeys="true"> | |||
| insert into component(category_id,component_name,component_Label,images,working_directory,command,env_virables,resources_standard,control_strategy,mount_path,in_parameters,out_parameters,description,icon_path,create_by,create_time,update_by,update_time,state) | |||
| values (#{component.categoryId},#{component.componentName},#{component.componentLabel},#{component.images},#{component.workingDirectory},#{component.command},#{component.envVirables},#{component.resourcesStandard},#{component.controlStrategy},#{component.mountPath},#{component.inParameters},#{component.outParameters},#{component.description},#{component.iconPath},#{component.createBy},#{component.createTime},#{component.updateBy},#{component.updateTime},#{component.state}) | |||
| insert into component(category_id,component_name,component_Label,images,working_directory,command,env_virables,resources_standard,control_strategy,mount_path,in_parameters,out_parameters,available_range,description,icon_path,create_by,create_time,update_by,update_time,state) | |||
| values (#{component.categoryId},#{component.componentName},#{component.componentLabel},#{component.images},#{component.workingDirectory},#{component.command},#{component.envVirables},#{component.resourcesStandard},#{component.controlStrategy},#{component.mountPath},#{component.inParameters},#{component.outParameters},#{component.availableRange},#{component.description},#{component.iconPath},#{component.createBy},#{component.createTime},#{component.updateBy},#{component.updateTime},#{component.state}) | |||
| </insert> | |||
| <insert id="insertBatch" keyProperty="id" useGeneratedKeys="true"> | |||
| insert into component(category_idcomponent_namecomponent_labelimagesworking_directorycommandenv_virablesresources_standardcontrol_strategymount_pathin_parametersout_parameterscreate_bycreate_timeupdate_byupdate_timestate) | |||
| insert into component(category_id,component_name,component_Label,images,working_directory,command,env_virables,resources_standard,control_strategy,mount_path,in_parameters,out_parameters,available_range,description,icon_path,create_by,create_time,update_by,update_time,state) | |||
| values | |||
| <foreach collection="entities" item="entity" separator=","> | |||
| (#{entity.categoryId}#{entity.componentName}#{entity.componentLabel}#{entity.images}#{entity.workingDirectory}#{entity.command}#{entity.envVirables}#{entity.resourcesStandard}#{entity.controlStrategy}#{entity.mountPath}#{entity.inParameters}#{entity.outParameters}#{entity.createBy}#{entity.createTime}#{entity.updateBy}#{entity.updateTime}#{entity.state}) | |||
| (#{entity.categoryId},#{entity.componentName},#{entity.componentLabel},#{entity.images},#{entity.workingDirectory},#{entity.command},#{entity.envVirables},#{entity.resourcesStandard},#{entity.controlStrategy},#{entity.mountPath},#{entity.inParameters},#{entity.outParameters},#{entity.availableRange},#{entity.createBy},#{entity.createTime},#{entity.updateBy},#{entity.updateTime},#{entity.state}) | |||
| </foreach> | |||
| </insert> | |||
| <insert id="insertOrUpdateBatch" keyProperty="id" useGeneratedKeys="true"> | |||
| insert into component(category_idcomponent_namecomponent_labelimagesworking_directorycommandenv_virablesresources_standardcontrol_strategymount_pathin_parametersout_parameterscreate_bycreate_timeupdate_byupdate_timestate) | |||
| insert into component(category_id,component_name,component_Label,images,working_directory,command,env_virables,resources_standard,control_strategy,mount_path,in_parameters,out_parameters,available_range,description,icon_path,create_by,create_time,update_by,update_time,state) | |||
| values | |||
| <foreach collection="entities" item="entity" separator=","> | |||
| (#{entity.categoryId}#{entity.componentName}#{entity.componentId}#{entity.images}#{entity.workingDirectory}#{entity.command}#{entity.envVirables}#{entity.resourcesStandard}#{entity.controlStrategy}#{entity.mountPath}#{entity.inParameters}#{entity.outParameters}#{entity.createBy}#{entity.createTime}#{entity.updateBy}#{entity.updateTime}#{entity.state}) | |||
| (#{entity.categoryId},#{entity.componentName},#{entity.componentLabel},#{entity.images},#{entity.workingDirectory},#{entity.command},#{entity.envVirables},#{entity.resourcesStandard},#{entity.controlStrategy},#{entity.mountPath},#{entity.inParameters},#{entity.outParameters},#{entity.availableRange},#{entity.createBy},#{entity.createTime},#{entity.updateBy},#{entity.updateTime},#{entity.state}) | |||
| </foreach> | |||
| on duplicate key update | |||
| category_id = values(category_id)component_name = values(component_name)component_id = values(component_id)images = values(images)working_directory = values(working_directory)command = values(command)env_virables = values(env_virables)resources_standard = values(resources_standard)control_strategy = values(control_strategy)mount_path = values(mount_path)in_parameters = values(in_parameters)out_parameters = values(out_parameters)create_by = values(create_by)create_time = values(create_time)update_by = values(update_by)update_time = values(update_time)state = values(state) | |||
| @@ -255,6 +262,9 @@ category_id = values(category_id)component_name = values(component_name)componen | |||
| <if test="component.outParameters != null and component.outParameters != ''"> | |||
| out_parameters = #{component.outParameters}, | |||
| </if> | |||
| <if test="component.availableRange != null"> | |||
| available_range = #{component.availableRange}, | |||
| </if> | |||
| <if test="component.description != null and component.description != ''"> | |||
| description = #{component.description}, | |||
| </if> | |||
| @@ -0,0 +1,246 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | |||
| <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | |||
| <mapper namespace="com.ruoyi.platform.mapper.DevEnvironmentDao"> | |||
| <resultMap type="com.ruoyi.platform.domain.DevEnvironment" id="DevEnvironmentMap"> | |||
| <result property="id" column="id" jdbcType="INTEGER"/> | |||
| <result property="name" column="name" jdbcType="VARCHAR"/> | |||
| <result property="status" column="status" jdbcType="VARCHAR"/> | |||
| <result property="computingResource" column="computing_resource" jdbcType="VARCHAR"/> | |||
| <result property="standard" column="standard" jdbcType="VARCHAR"/> | |||
| <result property="envVariable" column="env_variable" jdbcType="VARCHAR"/> | |||
| <result property="image" column="image" jdbcType="VARCHAR"/> | |||
| <result property="dataset" column="dataset" jdbcType="VARCHAR"/> | |||
| <result property="model" column="model" jdbcType="VARCHAR"/> | |||
| <result property="altField1" column="alt_field1" jdbcType="VARCHAR"/> | |||
| <result property="altField2" column="alt_field2" jdbcType="VARCHAR"/> | |||
| <result property="createBy" column="create_by" jdbcType="VARCHAR"/> | |||
| <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/> | |||
| <result property="updateBy" column="update_by" jdbcType="VARCHAR"/> | |||
| <result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/> | |||
| <result property="state" column="state" jdbcType="INTEGER"/> | |||
| </resultMap> | |||
| <!--查询单个--> | |||
| <select id="queryById" resultMap="DevEnvironmentMap"> | |||
| select | |||
| id,name,status,computing_resource,standard,env_variable,image,dataset,model,alt_field1,alt_field2,create_by,create_time,update_by,update_time,state | |||
| from dev_environment | |||
| where id = #{id} | |||
| </select> | |||
| <!--查询指定行数据--> | |||
| <select id="queryAllByLimit" resultMap="DevEnvironmentMap"> | |||
| select | |||
| id,name,status,computing_resource,standard,env_variable,image,dataset,model,alt_field1,alt_field2,create_by,create_time,update_by,update_time,state | |||
| from dev_environment | |||
| <where> | |||
| <if test="devEnvironment.id != null"> | |||
| and id = #{devEnvironment.id} | |||
| </if> | |||
| <if test="devEnvironment.name != null and devEnvironment.name != ''"> | |||
| and name = #{devEnvironment.name} | |||
| </if> | |||
| <if test="devEnvironment.status != null and devEnvironment.status != ''"> | |||
| and status = #{devEnvironment.status} | |||
| </if> | |||
| <if test="devEnvironment.computingResource != null and devEnvironment.computingResource != ''"> | |||
| and computing_resource = #{devEnvironment.computingResource} | |||
| </if> | |||
| <if test="devEnvironment.standard != null and devEnvironment.standard != ''"> | |||
| and standard = #{devEnvironment.standard} | |||
| </if> | |||
| <if test="devEnvironment.envVariable != null and devEnvironment.envVariable != ''"> | |||
| and env_variable = #{devEnvironment.envVariable} | |||
| </if> | |||
| <if test="devEnvironment.image != null and devEnvironment.image != ''"> | |||
| and image = #{devEnvironment.image} | |||
| </if> | |||
| <if test="devEnvironment.dataset != null and devEnvironment.dataset != ''"> | |||
| and dataset = #{devEnvironment.dataset} | |||
| </if> | |||
| <if test="devEnvironment.model != null and devEnvironment.model != ''"> | |||
| and model = #{devEnvironment.model} | |||
| </if> | |||
| <if test="devEnvironment.altField1 != null and devEnvironment.altField1 != ''"> | |||
| and alt_field1 = #{devEnvironment.altField1} | |||
| </if> | |||
| <if test="devEnvironment.altField2 != null and devEnvironment.altField2 != ''"> | |||
| and alt_field2 = #{devEnvironment.altField2} | |||
| </if> | |||
| <if test="devEnvironment.createBy != null and devEnvironment.createBy != ''"> | |||
| and create_by = #{devEnvironment.createBy} | |||
| </if> | |||
| <if test="devEnvironment.createTime != null"> | |||
| and create_time = #{devEnvironment.createTime} | |||
| </if> | |||
| <if test="devEnvironment.updateBy != null and devEnvironment.updateBy != ''"> | |||
| and update_by = #{devEnvironment.updateBy} | |||
| </if> | |||
| <if test="devEnvironment.updateTime != null"> | |||
| and update_time = #{devEnvironment.updateTime} | |||
| </if> | |||
| <if test="devEnvironment.state != null"> | |||
| and state = #{devEnvironment.state} | |||
| </if> | |||
| </where> | |||
| limit #{pageable.offset}, #{pageable.pageSize} | |||
| </select> | |||
| <!--统计总行数--> | |||
| <select id="count" resultType="java.lang.Long"> | |||
| select count(1) | |||
| from dev_environment | |||
| <where> | |||
| <if test="devEnvironment.id != null"> | |||
| and id = #{devEnvironment.id} | |||
| </if> | |||
| <if test="devEnvironment.name != null and devEnvironment.name != ''"> | |||
| and name = #{devEnvironment.name} | |||
| </if> | |||
| <if test="devEnvironment.status != null and devEnvironment.status != ''"> | |||
| and status = #{devEnvironment.status} | |||
| </if> | |||
| <if test="devEnvironment.computingResource != null and devEnvironment.computingResource != ''"> | |||
| and computing_resource = #{devEnvironment.computingResource} | |||
| </if> | |||
| <if test="devEnvironment.standard != null and devEnvironment.standard != ''"> | |||
| and standard = #{devEnvironment.standard} | |||
| </if> | |||
| <if test="devEnvironment.envVariable != null and devEnvironment.envVariable != ''"> | |||
| and env_variable = #{devEnvironment.envVariable} | |||
| </if> | |||
| <if test="devEnvironment.image != null and devEnvironment.image != ''"> | |||
| and image = #{devEnvironment.image} | |||
| </if> | |||
| <if test="devEnvironment.dataset != null and devEnvironment.dataset != ''"> | |||
| and dataset = #{devEnvironment.dataset} | |||
| </if> | |||
| <if test="devEnvironment.model != null and devEnvironment.model != ''"> | |||
| and model = #{devEnvironment.model} | |||
| </if> | |||
| <if test="devEnvironment.altField1 != null and devEnvironment.altField1 != ''"> | |||
| and alt_field1 = #{devEnvironment.altField1} | |||
| </if> | |||
| <if test="devEnvironment.altField2 != null and devEnvironment.altField2 != ''"> | |||
| and alt_field2 = #{devEnvironment.altField2} | |||
| </if> | |||
| <if test="devEnvironment.createBy != null and devEnvironment.createBy != ''"> | |||
| and create_by = #{devEnvironment.createBy} | |||
| </if> | |||
| <if test="devEnvironment.createTime != null"> | |||
| and create_time = #{devEnvironment.createTime} | |||
| </if> | |||
| <if test="devEnvironment.updateBy != null and devEnvironment.updateBy != ''"> | |||
| and update_by = #{devEnvironment.updateBy} | |||
| </if> | |||
| <if test="devEnvironment.updateTime != null"> | |||
| and update_time = #{devEnvironment.updateTime} | |||
| </if> | |||
| <if test="devEnvironment.state != null"> | |||
| and state = #{devEnvironment.state} | |||
| </if> | |||
| </where> | |||
| </select> | |||
| <!--新增所有列--> | |||
| <insert id="insert" keyProperty="id" useGeneratedKeys="true"> | |||
| insert into dev_environment(name,status,computing_resource,standard,env_variable,image,dataset,model,alt_field1,alt_field2,create_by,create_time,update_by,update_time,state) | |||
| values (#{devEnvironment.name}, | |||
| #{devEnvironment.status}, | |||
| #{devEnvironment.computingResource}, | |||
| #{devEnvironment.standard}, | |||
| #{devEnvironment.envVariable}, | |||
| #{devEnvironment.image}, | |||
| #{devEnvironment.dataset}, | |||
| #{devEnvironment.model}, | |||
| #{devEnvironment.altField1}, | |||
| #{devEnvironment.altField2}, | |||
| #{devEnvironment.createBy}, | |||
| #{devEnvironment.createTime}, | |||
| #{devEnvironment.updateBy}, | |||
| #{devEnvironment.updateTime}, | |||
| #{devEnvironment.state} | |||
| ) | |||
| </insert> | |||
| <insert id="insertBatch" keyProperty="id" useGeneratedKeys="true"> | |||
| insert into dev_environment(name,status,computing_resource,standard,env_variable,image,dataset,model,alt_field1,alt_field2,create_by,create_time,update_by,update_time,state ) | |||
| values | |||
| <foreach collection="entities" item="entity" separator=","> | |||
| (#{entity.name},#{entity.status},#{entity.computingResource},#{entity.standard},#{entity.envVariable},#{entity.image},#{entity.dataset},#{entity.model},#{entity.altField1},#{entity.altField2},#{entity.createBy},#{entity.createTime},#{entity.updateBy},#{entity.updateTime},#{entity.state}) | |||
| </foreach> | |||
| </insert> | |||
| <insert id="insertOrUpdateBatch" keyProperty="id" useGeneratedKeys="true"> | |||
| insert into dev_environment(name,status,computing_resource,standard,env_variable,image,dataset,model,alt_field1,alt_field2,create_by,create_time,update_by,update_time,state) | |||
| values | |||
| <foreach collection="entities" item="entity" separator=","> | |||
| (#{entity.name}#{entity.status}#{entity.computingResource}#{entity.standard}#{entity.envVariable}#{entity.image}#{entity.dataset}#{entity.model}#{entity.altField1}#{entity.altField2}#{entity.createBy}#{entity.createTime}#{entity.updateBy}#{entity.updateTime}#{entity.state}) | |||
| </foreach> | |||
| on duplicate key update | |||
| name = values(name)status = values(status)computing_resource = values(computing_resource)standard = values(standard)env_variable = values(env_variable)image = values(image)dataset = values(dataset)model = values(model)alt_field1 = values(alt_field1)alt_field2 = values(alt_field2)create_by = values(create_by)create_time = values(create_time)update_by = values(update_by)update_time = values(update_time)state = values(state) | |||
| </insert> | |||
| <!--通过主键修改数据--> | |||
| <update id="update"> | |||
| update dev_environment | |||
| <set> | |||
| <if test="devEnvironment.name != null and devEnvironment.name != ''"> | |||
| name = #{devEnvironment.name}, | |||
| </if> | |||
| <if test="devEnvironment.status != null and devEnvironment.status != ''"> | |||
| status = #{devEnvironment.status}, | |||
| </if> | |||
| <if test="devEnvironment.computingResource != null and devEnvironment.computingResource != ''"> | |||
| computing_resource = #{devEnvironment.computingResource}, | |||
| </if> | |||
| <if test="devEnvironment.standard != null and devEnvironment.standard != ''"> | |||
| standard = #{devEnvironment.standard}, | |||
| </if> | |||
| <if test="devEnvironment.envVariable != null and devEnvironment.envVariable != ''"> | |||
| env_variable = #{devEnvironment.envVariable}, | |||
| </if> | |||
| <if test="devEnvironment.image != null and devEnvironment.image != ''"> | |||
| image = #{devEnvironment.image}, | |||
| </if> | |||
| <if test="devEnvironment.dataset != null and devEnvironment.dataset != ''"> | |||
| dataset = #{devEnvironment.dataset}, | |||
| </if> | |||
| <if test="devEnvironment.model != null and devEnvironment.model != ''"> | |||
| model = #{devEnvironment.model}, | |||
| </if> | |||
| <if test="devEnvironment.altField1 != null and devEnvironment.altField1 != ''"> | |||
| alt_field1 = #{devEnvironment.altField1}, | |||
| </if> | |||
| <if test="devEnvironment.altField2 != null and devEnvironment.altField2 != ''"> | |||
| alt_field2 = #{devEnvironment.altField2}, | |||
| </if> | |||
| <if test="devEnvironment.createBy != null and devEnvironment.createBy != ''"> | |||
| create_by = #{devEnvironment.createBy}, | |||
| </if> | |||
| <if test="devEnvironment.createTime != null"> | |||
| create_time = #{devEnvironment.createTime}, | |||
| </if> | |||
| <if test="devEnvironment.updateBy != null and devEnvironment.updateBy != ''"> | |||
| update_by = #{devEnvironment.updateBy}, | |||
| </if> | |||
| <if test="devEnvironment.updateTime != null"> | |||
| update_time = #{devEnvironment.updateTime}, | |||
| </if> | |||
| <if test="devEnvironment.state != null"> | |||
| state = #{devEnvironment.state}, | |||
| </if> | |||
| </set> | |||
| where id = #{devEnvironment.id} | |||
| </update> | |||
| <!--通过主键删除--> | |||
| <delete id="deleteById"> | |||
| delete from dev_environment where id = #{id} | |||
| </delete> | |||
| </mapper> | |||
| @@ -0,0 +1,333 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | |||
| <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | |||
| <mapper namespace="com.ruoyi.platform.mapper.ModelDependencyDao"> | |||
| <resultMap type="com.ruoyi.platform.domain.ModelDependency" id="ModelDependencyMap"> | |||
| <result property="id" column="id" jdbcType="INTEGER"/> | |||
| <result property="currentModelId" column="current_model_id" jdbcType="INTEGER"/> | |||
| <result property="expInsId" column="exp_ins_id" jdbcType="INTEGER"/> | |||
| <result property="parentModels" column="parent_models" jdbcType="VARCHAR"/> | |||
| <result property="refItem" column="ref_item" jdbcType="VARCHAR"/> | |||
| <result property="trainTask" column="train_task" jdbcType="VARCHAR"/> | |||
| <result property="trainDataset" column="train_dataset" jdbcType="VARCHAR"/> | |||
| <result property="trainParams" column="train_params" jdbcType="VARCHAR"/> | |||
| <result property="trainImage" column="train_image" jdbcType="VARCHAR"/> | |||
| <result property="testDataset" column="test_dataset" jdbcType="VARCHAR"/> | |||
| <result property="projectDependency" column="project_dependency" jdbcType="VARCHAR"/> | |||
| <result property="version" column="version" jdbcType="VARCHAR"/> | |||
| <result property="createBy" column="create_by" jdbcType="VARCHAR"/> | |||
| <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/> | |||
| <result property="updateBy" column="update_by" jdbcType="VARCHAR"/> | |||
| <result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/> | |||
| <result property="state" column="state" jdbcType="INTEGER"/> | |||
| </resultMap> | |||
| <select id="queryChildrenByVersionId" resultMap="ModelDependencyMap"> | |||
| select | |||
| id,current_model_id,exp_ins_id,parent_models,ref_item,train_task,train_dataset,train_params,train_image,test_dataset,project_dependency,version,create_by,create_time,update_by,update_time,state | |||
| from model_dependency | |||
| <where> | |||
| parent_models like concat('%', #{model_id}, '%') AND parent_models like concat('%', #{version}, '%') | |||
| </where> | |||
| </select> | |||
| <select id="queryByModelDependency" resultMap="ModelDependencyMap"> | |||
| select | |||
| id,current_model_id,exp_ins_id,parent_models,ref_item,train_task,train_dataset,train_params,train_image,test_dataset,project_dependency,version,create_by,create_time,update_by,update_time,state | |||
| from model_dependency | |||
| <where> | |||
| <if test="modelDependency.id != null"> | |||
| and id = #{modelDependency.id} | |||
| </if> | |||
| <if test="modelDependency.currentModelId != null"> | |||
| and current_model_id = #{modelDependency.currentModelId} | |||
| </if> | |||
| <if test="modelDependency.expInsId != null"> | |||
| and exp_ins_id = #{modelDependency.expInsId} | |||
| </if> | |||
| <if test="modelDependency.parentModels != null"> | |||
| and parent_models = #{modelDependency.parentModels} | |||
| </if> | |||
| <if test="modelDependency.refItem != null and modelDependency.refItem != ''"> | |||
| and ref_item = #{modelDependency.refItem} | |||
| </if> | |||
| <if test="modelDependency.trainTask != null and modelDependency.trainTask != ''"> | |||
| and train_task = #{modelDependency.trainTask} | |||
| </if> | |||
| <if test="modelDependency.trainDataset != null and modelDependency.trainDataset != ''"> | |||
| and train_dataset = #{modelDependency.trainDataset} | |||
| </if> | |||
| <if test="modelDependency.trainParams != null and modelDependency.trainParams != ''"> | |||
| and train_params = #{modelDependency.trainParams} | |||
| </if> | |||
| <if test="modelDependency.trainImage != null and modelDependency.trainImage != ''"> | |||
| and train_image = #{modelDependency.trainImage} | |||
| </if> | |||
| <if test="modelDependency.testDataset != null and modelDependency.testDataset != ''"> | |||
| and test_dataset = #{modelDependency.testDataset} | |||
| </if> | |||
| <if test="modelDependency.projectDependency != null and modelDependency.projectDependency != ''"> | |||
| and project_dependency = #{modelDependency.projectDependency} | |||
| </if> | |||
| <if test="modelDependency.version != null and modelDependency.version != ''"> | |||
| and version = #{modelDependency.version} | |||
| </if> | |||
| <if test="modelDependency.createBy != null and modelDependency.createBy != ''"> | |||
| and create_by = #{modelDependency.createBy} | |||
| </if> | |||
| <if test="modelDependency.createTime != null"> | |||
| and create_time = #{modelDependency.createTime} | |||
| </if> | |||
| <if test="modelDependency.updateBy != null and modelDependency.updateBy != ''"> | |||
| and update_by = #{modelDependency.updateBy} | |||
| </if> | |||
| <if test="modelDependency.updateTime != null"> | |||
| and update_time = #{modelDependency.updateTime} | |||
| </if> | |||
| <if test="modelDependency.state != null"> | |||
| and state = #{modelDependency.state} | |||
| </if> | |||
| </where> | |||
| </select> | |||
| <!--查询单个--> | |||
| <select id="queryById" resultMap="ModelDependencyMap"> | |||
| select | |||
| id, current_model_id, exp_ins_id, parent_models, ref_item, train_task, train_dataset, train_params, train_image, test_dataset, project_dependency, version, create_by, create_time, update_by, update_time, state | |||
| from model_dependency | |||
| where id = #{id} | |||
| </select> | |||
| <!--查询指定行数据--> | |||
| <select id="queryAllByLimit" resultMap="ModelDependencyMap"> | |||
| select | |||
| id, current_model_id, exp_ins_id, parent_models, ref_item, train_task, train_dataset, train_params, train_image, | |||
| test_dataset, project_dependency, version, create_by, create_time, update_by, update_time, state | |||
| from model_dependency | |||
| <where> | |||
| <if test="id != null"> | |||
| and id = #{id} | |||
| </if> | |||
| <if test="currentModelId != null"> | |||
| and current_model_id = #{currentModelId} | |||
| </if> | |||
| <if test="expInsId != null"> | |||
| and exp_ins_id = #{expInsId} | |||
| </if> | |||
| <if test="parentModels != null and parentModels != ''"> | |||
| and parent_models = #{parentModels} | |||
| </if> | |||
| <if test="refItem != null and refItem != ''"> | |||
| and ref_item = #{refItem} | |||
| </if> | |||
| <if test="trainTask != null and trainTask != ''"> | |||
| and train_task = #{trainTask} | |||
| </if> | |||
| <if test="trainDataset != null and trainDataset != ''"> | |||
| and train_dataset = #{trainDataset} | |||
| </if> | |||
| <if test="trainParams != null and trainParams != ''"> | |||
| and train_params = #{trainParams} | |||
| </if> | |||
| <if test="trainImage != null and trainImage != ''"> | |||
| and train_image = #{trainImage} | |||
| </if> | |||
| <if test="testDataset != null and testDataset != ''"> | |||
| and test_dataset = #{testDataset} | |||
| </if> | |||
| <if test="projectDependency != null and projectDependency != ''"> | |||
| and project_dependency = #{projectDependency} | |||
| </if> | |||
| <if test="version != null and version != ''"> | |||
| and version = #{version} | |||
| </if> | |||
| <if test="createBy != null and createBy != ''"> | |||
| and create_by = #{createBy} | |||
| </if> | |||
| <if test="createTime != null"> | |||
| and create_time = #{createTime} | |||
| </if> | |||
| <if test="updateBy != null and updateBy != ''"> | |||
| and update_by = #{updateBy} | |||
| </if> | |||
| <if test="updateTime != null"> | |||
| and update_time = #{updateTime} | |||
| </if> | |||
| <if test="state != null"> | |||
| and state = #{state} | |||
| </if> | |||
| </where> | |||
| limit #{pageable.offset}, #{pageable.pageSize} | |||
| </select> | |||
| <!--统计总行数--> | |||
| <select id="count" resultType="java.lang.Long"> | |||
| select count(1) | |||
| from model_dependency | |||
| <where> | |||
| <if test="id != null"> | |||
| and id = #{id} | |||
| </if> | |||
| <if test="currentModelId != null"> | |||
| and current_model_id = #{currentModelId} | |||
| </if> | |||
| <if test="expInsId != null"> | |||
| and exp_ins_id = #{expInsId} | |||
| </if> | |||
| <if test="parentModels != null and parentModels != ''"> | |||
| and parent_models = #{parentModels} | |||
| </if> | |||
| <if test="refItem != null and refItem != ''"> | |||
| and ref_item = #{refItem} | |||
| </if> | |||
| <if test="trainTask != null and trainTask != ''"> | |||
| and train_task = #{trainTask} | |||
| </if> | |||
| <if test="trainDataset != null and trainDataset != ''"> | |||
| and train_dataset = #{trainDataset} | |||
| </if> | |||
| <if test="trainParams != null and trainParams != ''"> | |||
| and train_params = #{trainParams} | |||
| </if> | |||
| <if test="trainImage != null and trainImage != ''"> | |||
| and train_image = #{trainImage} | |||
| </if> | |||
| <if test="testDataset != null and testDataset != ''"> | |||
| and test_dataset = #{testDataset} | |||
| </if> | |||
| <if test="projectDependency != null and projectDependency != ''"> | |||
| and project_dependency = #{projectDependency} | |||
| </if> | |||
| <if test="version != null and version != ''"> | |||
| and version = #{version} | |||
| </if> | |||
| <if test="createBy != null and createBy != ''"> | |||
| and create_by = #{createBy} | |||
| </if> | |||
| <if test="createTime != null"> | |||
| and create_time = #{createTime} | |||
| </if> | |||
| <if test="updateBy != null and updateBy != ''"> | |||
| and update_by = #{updateBy} | |||
| </if> | |||
| <if test="updateTime != null"> | |||
| and update_time = #{updateTime} | |||
| </if> | |||
| <if test="state != null"> | |||
| and state = #{state} | |||
| </if> | |||
| </where> | |||
| </select> | |||
| <!--新增所有列--> | |||
| <insert id="insert" keyProperty="id" useGeneratedKeys="true"> | |||
| insert into model_dependency(current_model_id, exp_ins_id, parent_models, ref_item, train_task, train_dataset, train_params, train_image, test_dataset, project_dependency, version, create_by, create_time, update_by, update_time, state) | |||
| values (#{currentModelId}, #{expInsId}, #{parentModels}, #{refItem}, #{trainTask}, #{trainDataset}, #{trainParams}, #{trainImage}, #{testDataset}, #{projectDependency}, #{version}, #{createBy}, #{createTime}, #{updateBy}, #{updateTime}, #{state}) | |||
| </insert> | |||
| <insert id="insertBatch" keyProperty="id" useGeneratedKeys="true"> | |||
| insert into model_dependency(current_model_id, exp_ins_id, parent_models, ref_item, train_task, train_dataset, | |||
| train_params, train_image, test_dataset, project_dependency, version, create_by, create_time, update_by, | |||
| update_time, state) | |||
| values | |||
| <foreach collection="entities" item="entity" separator=","> | |||
| (#{entity.currentModelId}, #{entity.expInsId}, #{entity.parentModels}, #{entity.refItem}, | |||
| #{entity.trainTask}, #{entity.trainDataset}, #{entity.trainParams}, #{entity.trainImage}, | |||
| #{entity.testDataset}, #{entity.projectDependency}, #{entity.version}, #{entity.createBy}, | |||
| #{entity.createTime}, #{entity.updateBy}, #{entity.updateTime}, #{entity.state}) | |||
| </foreach> | |||
| </insert> | |||
| <insert id="insertOrUpdateBatch" keyProperty="id" useGeneratedKeys="true"> | |||
| insert into model_dependency(current_model_id, exp_ins_id, parent_models, ref_item, train_task, train_dataset, | |||
| train_params, train_image, test_dataset, project_dependency, version, create_by, create_time, update_by, | |||
| update_time, state) | |||
| values | |||
| <foreach collection="entities" item="entity" separator=","> | |||
| (#{entity.currentModelId}, #{entity.expInsId}, #{entity.parentModels}, #{entity.refItem}, | |||
| #{entity.trainTask}, #{entity.trainDataset}, #{entity.trainParams}, #{entity.trainImage}, | |||
| #{entity.testDataset}, #{entity.projectDependency}, #{entity.version}, #{entity.createBy}, | |||
| #{entity.createTime}, #{entity.updateBy}, #{entity.updateTime}, #{entity.state}) | |||
| </foreach> | |||
| on duplicate key update | |||
| current_model_id = values(current_model_id), | |||
| exp_ins_id = values(exp_ins_id), | |||
| parent_models = values(parent_models), | |||
| ref_item = values(ref_item), | |||
| train_task = values(train_task), | |||
| train_dataset = values(train_dataset), | |||
| train_params = values(train_params), | |||
| train_image = values(train_image), | |||
| test_dataset = values(test_dataset), | |||
| project_dependency = values(project_dependency), | |||
| version = values(version), | |||
| create_by = values(create_by), | |||
| create_time = values(create_time), | |||
| update_by = values(update_by), | |||
| update_time = values(update_time), | |||
| state = values(state) | |||
| </insert> | |||
| <!--通过主键修改数据--> | |||
| <update id="update"> | |||
| update model_dependency | |||
| <set> | |||
| <if test="currentModelId != null"> | |||
| current_model_id = #{currentModelId}, | |||
| </if> | |||
| <if test="expInsId != null"> | |||
| exp_ins_id = #{expInsId}, | |||
| </if> | |||
| <if test="parentModels != null and parentModels != ''"> | |||
| parent_models = #{parentModels}, | |||
| </if> | |||
| <if test="refItem != null and refItem != ''"> | |||
| ref_item = #{refItem}, | |||
| </if> | |||
| <if test="trainTask != null and trainTask != ''"> | |||
| train_task = #{trainTask}, | |||
| </if> | |||
| <if test="trainDataset != null and trainDataset != ''"> | |||
| train_dataset = #{trainDataset}, | |||
| </if> | |||
| <if test="trainParams != null and trainParams != ''"> | |||
| train_params = #{trainParams}, | |||
| </if> | |||
| <if test="trainImage != null and trainImage != ''"> | |||
| train_image = #{trainImage}, | |||
| </if> | |||
| <if test="testDataset != null and testDataset != ''"> | |||
| test_dataset = #{testDataset}, | |||
| </if> | |||
| <if test="projectDependency != null and projectDependency != ''"> | |||
| project_dependency = #{projectDependency}, | |||
| </if> | |||
| <if test="version != null and version != ''"> | |||
| version = #{version}, | |||
| </if> | |||
| <if test="createBy != null and createBy != ''"> | |||
| create_by = #{createBy}, | |||
| </if> | |||
| <if test="createTime != null"> | |||
| create_time = #{createTime}, | |||
| </if> | |||
| <if test="updateBy != null and updateBy != ''"> | |||
| update_by = #{updateBy}, | |||
| </if> | |||
| <if test="updateTime != null"> | |||
| update_time = #{updateTime}, | |||
| </if> | |||
| <if test="state != null"> | |||
| state = #{state}, | |||
| </if> | |||
| </set> | |||
| where id = #{id} and state = 1 | |||
| </update> | |||
| <!--通过主键删除--> | |||
| <delete id="deleteById"> | |||
| delete from model_dependency where id = #{id} | |||
| </delete> | |||
| </mapper> | |||