| @@ -18,7 +18,11 @@ spec: | |||||
| image: ${k8s-7management-image} | image: ${k8s-7management-image} | ||||
| ports: | ports: | ||||
| - containerPort: 9213 | - containerPort: 9213 | ||||
| env: | |||||
| - name: http_proxy | |||||
| value: "http://172.20.32.253:3128" | |||||
| - name: https_proxy | |||||
| value: "http://172.20.32.253:3128" | |||||
| --- | --- | ||||
| apiVersion: v1 | apiVersion: v1 | ||||
| kind: Service | kind: Service | ||||
| @@ -9,6 +9,7 @@ import { | |||||
| } from '@/utils/sessionStorage'; | } from '@/utils/sessionStorage'; | ||||
| import classNames from 'classnames'; | import classNames from 'classnames'; | ||||
| import { useEffect, useState } from 'react'; | import { useEffect, useState } from 'react'; | ||||
| import { createPortal } from 'react-dom'; | |||||
| import './index.less'; | import './index.less'; | ||||
| export enum IframePageType { | export enum IframePageType { | ||||
| @@ -61,7 +62,7 @@ function IframePage({ type, className, style }: IframePageProps) { | |||||
| return ( | return ( | ||||
| <div className={classNames('kf-iframe-page', className)} style={style}> | <div className={classNames('kf-iframe-page', className)} style={style}> | ||||
| {loading && <KFSpin size="large" />} | |||||
| {loading && createPortal(<KFSpin size="large" />, document.body)} | |||||
| <FullScreenFrame url={iframeUrl} onload={hideLoading} onerror={hideLoading} /> | <FullScreenFrame url={iframeUrl} onload={hideLoading} onerror={hideLoading} /> | ||||
| </div> | </div> | ||||
| ); | ); | ||||
| @@ -14,7 +14,15 @@ const filterResourceStandard: SelectProps<string, ComputingResource>['filterOpti | |||||
| }; | }; | ||||
| // id 从 number 转换为 string | // id 从 number 转换为 string | ||||
| const convertId = (item: any) => ({ ...item, id: `${item.id}-${item.identifier}` }); | |||||
| const convertId = (item: any) => ({ | |||||
| ...item, | |||||
| id: JSON.stringify({ | |||||
| id: item.id, | |||||
| name: item.name, | |||||
| identifier: item.identifier, | |||||
| owner: item.owner, | |||||
| }), | |||||
| }); | |||||
| export type SelectPropsConfig = { | export type SelectPropsConfig = { | ||||
| getOptions: () => Promise<any>; // 获取下拉数据 | getOptions: () => Promise<any>; // 获取下拉数据 | ||||
| @@ -37,7 +37,7 @@ function ResourceSelect({ type, value, onChange, ...rest }: ResourceSelectProps) | |||||
| onOk: (res) => { | onOk: (res) => { | ||||
| setSelectedResource(res); | setSelectedResource(res); | ||||
| if (res) { | if (res) { | ||||
| const { activeTab, id, name, version, path } = res; | |||||
| const { activeTab, id, name, version, path, identifier, owner } = res; | |||||
| if (type === ResourceSelectorType.Mirror) { | if (type === ResourceSelectorType.Mirror) { | ||||
| onChange?.({ | onChange?.({ | ||||
| value: path, | value: path, | ||||
| @@ -50,8 +50,11 @@ function ResourceSelect({ type, value, onChange, ...rest }: ResourceSelectProps) | |||||
| } else { | } else { | ||||
| const jsonObj = { | const jsonObj = { | ||||
| id, | id, | ||||
| name, | |||||
| version, | version, | ||||
| path, | path, | ||||
| identifier, | |||||
| owner, | |||||
| }; | }; | ||||
| const jsonObjStr = JSON.stringify(jsonObj); | const jsonObjStr = JSON.stringify(jsonObj); | ||||
| const showValue = `${name}:${version}`; | const showValue = `${name}:${version}`; | ||||
| @@ -34,12 +34,19 @@ | |||||
| } | } | ||||
| &__bottom { | &__bottom { | ||||
| position: relative; | |||||
| height: calc(100% - 135px); | height: calc(100% - 135px); | ||||
| padding: 8px 30px 20px; | padding: 8px 30px 20px; | ||||
| background: #ffffff; | background: #ffffff; | ||||
| border-radius: 10px; | border-radius: 10px; | ||||
| box-shadow: 0px 2px 12px rgba(180, 182, 191, 0.09); | box-shadow: 0px 2px 12px rgba(180, 182, 191, 0.09); | ||||
| &__legend { | |||||
| position: absolute; | |||||
| top: 20px; | |||||
| right: 30px; | |||||
| } | |||||
| :global { | :global { | ||||
| .ant-tabs { | .ant-tabs { | ||||
| height: 100%; | height: 100%; | ||||
| @@ -11,14 +11,13 @@ import { | |||||
| ResourceVersionData, | ResourceVersionData, | ||||
| resourceConfig, | resourceConfig, | ||||
| } from '@/pages/Dataset/config'; | } from '@/pages/Dataset/config'; | ||||
| import GraphLegend from '@/pages/Model/components/GraphLegend'; | |||||
| import ModelEvolution from '@/pages/Model/components/ModelEvolution'; | import ModelEvolution from '@/pages/Model/components/ModelEvolution'; | ||||
| import { openAntdModal } from '@/utils/modal'; | import { openAntdModal } from '@/utils/modal'; | ||||
| import { to } from '@/utils/promise'; | import { to } from '@/utils/promise'; | ||||
| import { getSessionStorageItem, resourceItemKey } from '@/utils/sessionStorage'; | |||||
| import { modalConfirm } from '@/utils/ui'; | import { modalConfirm } from '@/utils/ui'; | ||||
| import { useParams, useSearchParams } from '@umijs/max'; | import { useParams, useSearchParams } from '@umijs/max'; | ||||
| import { App, Button, Flex, Select, Tabs } from 'antd'; | import { App, Button, Flex, Select, Tabs } from 'antd'; | ||||
| import { pick } from 'lodash'; | |||||
| import { useEffect, useState } from 'react'; | import { useEffect, useState } from 'react'; | ||||
| import AddVersionModal from '../AddVersionModal'; | import AddVersionModal from '../AddVersionModal'; | ||||
| import ResourceIntro from '../ResourceIntro'; | import ResourceIntro from '../ResourceIntro'; | ||||
| @@ -40,30 +39,32 @@ const ResourceInfo = ({ resourceType }: ResourceInfoProps) => { | |||||
| const [info, setInfo] = useState<ResourceData>({} as ResourceData); | const [info, setInfo] = useState<ResourceData>({} as ResourceData); | ||||
| const locationParams = useParams(); | const locationParams = useParams(); | ||||
| const [searchParams] = useSearchParams(); | const [searchParams] = useSearchParams(); | ||||
| const resourceId = Number(locationParams.id); | |||||
| // 模型演化传入的 tab | // 模型演化传入的 tab | ||||
| const defaultTab = searchParams.get('tab') || ResourceInfoTabKeys.Introduction; | const defaultTab = searchParams.get('tab') || ResourceInfoTabKeys.Introduction; | ||||
| // 模型演化传入的版本 | // 模型演化传入的版本 | ||||
| let versionParam = searchParams.get('version'); | let versionParam = searchParams.get('version'); | ||||
| const name = searchParams.get('name') || ''; | |||||
| const owner = searchParams.get('owner') || ''; | |||||
| const identifier = searchParams.get('identifier') || ''; | |||||
| const [versionList, setVersionList] = useState<ResourceVersionData[]>([]); | const [versionList, setVersionList] = useState<ResourceVersionData[]>([]); | ||||
| const [version, setVersion] = useState<string | undefined>(undefined); | const [version, setVersion] = useState<string | undefined>(undefined); | ||||
| const [activeTab, setActiveTab] = useState<string>(defaultTab); | const [activeTab, setActiveTab] = useState<string>(defaultTab); | ||||
| const resourceId = Number(locationParams.id); | |||||
| const config = resourceConfig[resourceType]; | const config = resourceConfig[resourceType]; | ||||
| const typeName = config.name; // 数据集/模型 | const typeName = config.name; // 数据集/模型 | ||||
| const { message } = App.useApp(); | const { message } = App.useApp(); | ||||
| useEffect(() => { | useEffect(() => { | ||||
| const info = getSessionStorageItem(resourceItemKey, true); | |||||
| if (info) { | |||||
| setInfo(info); | |||||
| getVersionList(pick(info, ['owner', 'identifier'])); | |||||
| } | |||||
| }, [resourceId]); | |||||
| getVersionList(); | |||||
| }, [resourceId, owner, identifier]); | |||||
| useEffect(() => { | useEffect(() => { | ||||
| if (version) { | if (version) { | ||||
| getResourceDetail({ | getResourceDetail({ | ||||
| ...pick(info, ['owner', 'name', 'id', 'identifier']), | |||||
| id: resourceId, | |||||
| owner, | |||||
| name, | |||||
| identifier, | |||||
| version, | version, | ||||
| }); | }); | ||||
| } | } | ||||
| @@ -85,9 +86,14 @@ const ResourceInfo = ({ resourceType }: ResourceInfoProps) => { | |||||
| }; | }; | ||||
| // 获取版本列表 | // 获取版本列表 | ||||
| const getVersionList = async (params: { owner: string; identifier: string }) => { | |||||
| const getVersionList = async () => { | |||||
| const request = config.getVersions; | const request = config.getVersions; | ||||
| const [res] = await to(request(params)); | |||||
| const [res] = await to( | |||||
| request({ | |||||
| owner, | |||||
| identifier, | |||||
| }), | |||||
| ); | |||||
| if (res && res.data && res.data.length > 0) { | if (res && res.data && res.data.length > 0) { | ||||
| setVersionList(res.data); | setVersionList(res.data); | ||||
| if ( | if ( | ||||
| @@ -112,7 +118,7 @@ const ResourceInfo = ({ resourceType }: ResourceInfoProps) => { | |||||
| resoureName: info.name, | resoureName: info.name, | ||||
| identifier: info.identifier, | identifier: info.identifier, | ||||
| onOk: () => { | onOk: () => { | ||||
| getVersionList(pick(info, ['owner', 'identifier'])); | |||||
| getVersionList(); | |||||
| close(); | close(); | ||||
| }, | }, | ||||
| }); | }); | ||||
| @@ -127,13 +133,16 @@ const ResourceInfo = ({ resourceType }: ResourceInfoProps) => { | |||||
| const deleteVersion = async () => { | const deleteVersion = async () => { | ||||
| const request = config.deleteVersion; | const request = config.deleteVersion; | ||||
| const params = { | const params = { | ||||
| ...pick(info, ['id', 'owner', 'identifier', 'relative_paths']), | |||||
| id: resourceId, | |||||
| owner, | |||||
| identifier, | |||||
| relative_paths: info.relative_paths, | |||||
| version, | version, | ||||
| }; | }; | ||||
| const [res] = await to(request(params)); | const [res] = await to(request(params)); | ||||
| if (res) { | if (res) { | ||||
| message.success('删除成功'); | message.success('删除成功'); | ||||
| getVersionList(pick(info, ['owner', 'identifier'])); | |||||
| getVersionList(); | |||||
| } | } | ||||
| }; | }; | ||||
| @@ -174,7 +183,7 @@ const ResourceInfo = ({ resourceType }: ResourceInfoProps) => { | |||||
| <ModelEvolution | <ModelEvolution | ||||
| resourceId={resourceId} | resourceId={resourceId} | ||||
| version={version} | version={version} | ||||
| identifier={info.identifier} | |||||
| identifier={identifier} | |||||
| isActive={activeTab === ResourceInfoTabKeys.Evolution} | isActive={activeTab === ResourceInfoTabKeys.Evolution} | ||||
| onVersionChange={handleVersionChange} | onVersionChange={handleVersionChange} | ||||
| ></ModelEvolution> | ></ModelEvolution> | ||||
| @@ -228,6 +237,9 @@ const ResourceInfo = ({ resourceType }: ResourceInfoProps) => { | |||||
| </div> | </div> | ||||
| <div className={styles['resource-info__bottom']}> | <div className={styles['resource-info__bottom']}> | ||||
| <Tabs activeKey={activeTab} items={items} onChange={(key) => setActiveTab(key)}></Tabs> | <Tabs activeKey={activeTab} items={items} onChange={(key) => setActiveTab(key)}></Tabs> | ||||
| <div className={styles['resource-info__bottom__legend']}> | |||||
| {activeTab === ResourceInfoTabKeys.Evolution && <GraphLegend />} | |||||
| </div> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| ); | ); | ||||
| @@ -4,7 +4,6 @@ import { CommonTabKeys } from '@/enums'; | |||||
| import AddModelModal from '@/pages/Dataset/components/AddModelModal'; | import AddModelModal from '@/pages/Dataset/components/AddModelModal'; | ||||
| import { openAntdModal } from '@/utils/modal'; | import { openAntdModal } from '@/utils/modal'; | ||||
| import { to } from '@/utils/promise'; | import { to } from '@/utils/promise'; | ||||
| import { resourceItemKey, setSessionStorageItem } from '@/utils/sessionStorage'; | |||||
| import { modalConfirm } from '@/utils/ui'; | import { modalConfirm } from '@/utils/ui'; | ||||
| import { useNavigate } from '@umijs/max'; | import { useNavigate } from '@umijs/max'; | ||||
| import { App, Button, Input, Pagination, PaginationProps } from 'antd'; | import { App, Button, Input, Pagination, PaginationProps } from 'antd'; | ||||
| @@ -138,8 +137,9 @@ function ResourceList( | |||||
| activeTag: dataTag, | activeTag: dataTag, | ||||
| }); | }); | ||||
| const prefix = config.prefix; | const prefix = config.prefix; | ||||
| setSessionStorageItem(resourceItemKey, record, true); | |||||
| navigate(`/dataset/${prefix}/info/${record.id}`); | |||||
| navigate( | |||||
| `/dataset/${prefix}/info/${record.id}?name=${record.name}&owner=${record.owner}&identifier=${record.identifier}`, | |||||
| ); | |||||
| }; | }; | ||||
| // 分页切换 | // 分页切换 | ||||
| @@ -1,16 +1,11 @@ | |||||
| .model-evolution { | .model-evolution { | ||||
| width: 100%; | width: 100%; | ||||
| height: 100%; | height: 100%; | ||||
| overflow-x: hidden; | |||||
| background-color: white; | background-color: white; | ||||
| &__top { | |||||
| padding: 30px 0; | |||||
| color: @text-color; | |||||
| font-size: @font-size-content; | |||||
| } | |||||
| &__graph { | &__graph { | ||||
| height: calc(100% - 92px); | |||||
| height: calc(100%); | |||||
| background-color: @background-color; | background-color: @background-color; | ||||
| background-image: url(@/assets/img/pipeline-canvas-bg.png); | background-image: url(@/assets/img/pipeline-canvas-bg.png); | ||||
| background-size: 100% 100%; | background-size: 100% 100%; | ||||
| @@ -9,9 +9,8 @@ import { getModelAtlasReq } from '@/services/dataset/index.js'; | |||||
| import themes from '@/styles/theme.less'; | import themes from '@/styles/theme.less'; | ||||
| import { to } from '@/utils/promise'; | import { to } from '@/utils/promise'; | ||||
| import G6, { G6GraphEvent, Graph, INode } from '@antv/g6'; | import G6, { G6GraphEvent, Graph, INode } from '@antv/g6'; | ||||
| import { Flex } from 'antd'; | |||||
| import { useEffect, useRef, useState } from 'react'; | import { useEffect, useRef, useState } from 'react'; | ||||
| import GraphLegend from '../GraphLegend'; | |||||
| import NodeTooltips from '../NodeTooltips'; | import NodeTooltips from '../NodeTooltips'; | ||||
| import styles from './index.less'; | import styles from './index.less'; | ||||
| import type { ModelDepsData, ProjectDependency, TrainDataset } from './utils'; | import type { ModelDepsData, ProjectDependency, TrainDataset } from './utils'; | ||||
| @@ -145,14 +144,15 @@ function ModelEvolution({ | |||||
| // 更加缩放,调整 tooltip 位置 | // 更加缩放,调整 tooltip 位置 | ||||
| const offsetX = (nodeWidth * zoom) / 4; | const offsetX = (nodeWidth * zoom) / 4; | ||||
| const offsetY = (nodeHeight * zoom) / 4; | const offsetY = (nodeHeight * zoom) / 4; | ||||
| point.x += offsetX; | |||||
| const canvasWidth = graphRef.current!.clientWidth; | const canvasWidth = graphRef.current!.clientWidth; | ||||
| if (point.x + 300 > canvasWidth) { | |||||
| point.x = canvasWidth - 300; | |||||
| if (point.x + 300 > canvasWidth + 30) { | |||||
| point.x = canvasWidth + 30 - 300; | |||||
| } | } | ||||
| setHoverNodeData(model); | setHoverNodeData(model); | ||||
| setNodeToolTipX(point.x + offsetX); | |||||
| setNodeToolTipX(point.x); | |||||
| setNodeToolTipY(graphRef.current!.clientHeight - point.y + offsetY); | setNodeToolTipY(graphRef.current!.clientHeight - point.y + offsetY); | ||||
| setShowNodeTooltip(true); | setShowNodeTooltip(true); | ||||
| }); | }); | ||||
| @@ -248,9 +248,6 @@ function ModelEvolution({ | |||||
| return ( | return ( | ||||
| <div className={styles['model-evolution']}> | <div className={styles['model-evolution']}> | ||||
| <Flex align="center" className={styles['model-evolution__top']}> | |||||
| <GraphLegend style={{ marginRight: 0, marginLeft: 'auto' }}></GraphLegend> | |||||
| </Flex> | |||||
| <div className={styles['model-evolution__graph']} id="canvas" ref={graphRef}></div> | <div className={styles['model-evolution__graph']} id="canvas" ref={graphRef}></div> | ||||
| {(showNodeTooltip || enterTooltip) && ( | {(showNodeTooltip || enterTooltip) && ( | ||||
| <NodeTooltips | <NodeTooltips | ||||
| @@ -38,9 +38,11 @@ export type TrainTask = { | |||||
| }; | }; | ||||
| export interface TrainDataset extends NodeConfig { | export interface TrainDataset extends NodeConfig { | ||||
| dataset_id: number; | |||||
| dataset_name: string; | |||||
| dataset_version: string; | |||||
| repo_id: number; | |||||
| name: string; | |||||
| version: string; | |||||
| identifier: string; | |||||
| owner: string; | |||||
| model_type: NodeType.TestDataset | NodeType.TrainDataset; | model_type: NodeType.TestDataset | NodeType.TrainDataset; | ||||
| } | } | ||||
| @@ -51,34 +53,33 @@ export interface ProjectDependency extends NodeConfig { | |||||
| model_type: NodeType.Project; | model_type: NodeType.Project; | ||||
| } | } | ||||
| export type ModalDetail = { | |||||
| export type ModelMeta = { | |||||
| train_datasets?: TrainDataset[]; | |||||
| test_datasets?: TrainDataset[]; | |||||
| project_depency?: ProjectDependency; | |||||
| train_task?: TrainTask; | |||||
| name: string; | name: string; | ||||
| available_range: number; | |||||
| file_name: string; | |||||
| file_size: string; | |||||
| description: string; | |||||
| model_type_name: string; | |||||
| model_tag_name: string; | |||||
| version: string; | |||||
| model_source: string; | |||||
| model_type: string; | |||||
| create_time: string; | create_time: string; | ||||
| file_size: string; | |||||
| is_public: boolean; | |||||
| }; | }; | ||||
| export interface ModelDepsAPIData { | export interface ModelDepsAPIData { | ||||
| current_model_id: number; | |||||
| repo_id: number; | |||||
| model_name: string; | |||||
| version: string; | version: string; | ||||
| workflow_id: number; | workflow_id: number; | ||||
| exp_ins_id: number; | exp_ins_id: number; | ||||
| model_type: NodeType.Children | NodeType.Current | NodeType.Parent; | model_type: NodeType.Children | NodeType.Current | NodeType.Parent; | ||||
| current_model_name: string; | |||||
| project_dependency?: ProjectDependency; | |||||
| test_dataset: TrainDataset[]; | |||||
| train_dataset: TrainDataset[]; | |||||
| train_task: TrainTask; | |||||
| model_version_dependcy_vo: ModalDetail; | |||||
| children_models: ModelDepsAPIData[]; | |||||
| parent_models: ModelDepsAPIData[]; | |||||
| model_meta: ModelMeta; | |||||
| child_model_list: ModelDepsAPIData[]; | |||||
| parent_model_vo?: ModelDepsAPIData; | |||||
| } | } | ||||
| export interface ModelDepsData extends Omit<ModelDepsAPIData, 'children_models'>, TreeGraphData { | |||||
| export interface ModelDepsData extends Omit<ModelDepsAPIData, 'child_model_list'>, TreeGraphData { | |||||
| children: ModelDepsData[]; | children: ModelDepsData[]; | ||||
| expanded: boolean; // 是否展开 | expanded: boolean; // 是否展开 | ||||
| level: number; // 层级,从 0 开始 | level: number; // 层级,从 0 开始 | ||||
| @@ -92,8 +93,11 @@ export function normalizeChildren(data: ModelDepsData[]) { | |||||
| item.model_type = NodeType.Children; | item.model_type = NodeType.Children; | ||||
| item.expanded = false; | item.expanded = false; | ||||
| item.level = 0; | item.level = 0; | ||||
| item.datasetLen = item.train_dataset.length + item.test_dataset.length; | |||||
| item.id = `$M_${item.current_model_id}_${item.version}`; | |||||
| item.datasetLen = getDatasetLen( | |||||
| item.model_meta.train_datasets, | |||||
| item.model_meta.test_datasets, | |||||
| ); | |||||
| item.id = `$M_${item.repo_id}_${item.version}`; | |||||
| item.label = getLabel(item); | item.label = getLabel(item); | ||||
| item.style = getStyle(NodeType.Children); | item.style = getStyle(NodeType.Children); | ||||
| normalizeChildren(item.children); | normalizeChildren(item.children); | ||||
| @@ -104,16 +108,17 @@ export function normalizeChildren(data: ModelDepsData[]) { | |||||
| // 获取 label | // 获取 label | ||||
| export function getLabel(node: ModelDepsData | ModelDepsAPIData) { | export function getLabel(node: ModelDepsData | ModelDepsAPIData) { | ||||
| return ( | return ( | ||||
| fittingString( | |||||
| `${node.model_version_dependcy_vo.name ?? ''}`, | |||||
| nodeWidth - labelPadding, | |||||
| nodeFontSize, | |||||
| ) + | |||||
| fittingString(`${node.model_name ?? ''}`, nodeWidth - labelPadding, nodeFontSize) + | |||||
| '\n' + | '\n' + | ||||
| fittingString(`${node.version}`, nodeWidth - labelPadding, nodeFontSize) | fittingString(`${node.version}`, nodeWidth - labelPadding, nodeFontSize) | ||||
| ); | ); | ||||
| } | } | ||||
| // 获取数据集数量 | |||||
| export function getDatasetLen(train?: TrainDataset[], test?: TrainDataset[]) { | |||||
| return (train?.length || 0) + (test?.length || 0); | |||||
| } | |||||
| // 获取 style | // 获取 style | ||||
| export function getStyle(model_type: NodeType) { | export function getStyle(model_type: NodeType) { | ||||
| let fill = ''; | let fill = ''; | ||||
| @@ -148,41 +153,43 @@ export function getStyle(model_type: NodeType) { | |||||
| export function normalizeTreeData(apiData: ModelDepsAPIData): ModelDepsData { | export function normalizeTreeData(apiData: ModelDepsAPIData): ModelDepsData { | ||||
| // 将 children_models 转换成 children | // 将 children_models 转换成 children | ||||
| let normalizedData = changePropertyName(apiData, { | let normalizedData = changePropertyName(apiData, { | ||||
| children_models: 'children', | |||||
| child_model_list: 'children', | |||||
| }) as ModelDepsData; | }) as ModelDepsData; | ||||
| // 设置当前模型的数据 | // 设置当前模型的数据 | ||||
| normalizedData.model_type = NodeType.Current; | normalizedData.model_type = NodeType.Current; | ||||
| normalizedData.id = `$M_${normalizedData.current_model_id}_${normalizedData.version}`; | |||||
| normalizedData.id = `$M_${normalizedData.repo_id}_${normalizedData.version}`; | |||||
| normalizedData.label = getLabel(normalizedData); | normalizedData.label = getLabel(normalizedData); | ||||
| normalizedData.style = getStyle(NodeType.Current); | normalizedData.style = getStyle(NodeType.Current); | ||||
| normalizedData.expanded = true; | normalizedData.expanded = true; | ||||
| normalizedData.datasetLen = | |||||
| normalizedData.train_dataset.length + normalizedData.test_dataset.length; | |||||
| normalizedData.datasetLen = getDatasetLen( | |||||
| normalizedData.model_meta.train_datasets, | |||||
| normalizedData.model_meta.test_datasets, | |||||
| ); | |||||
| normalizeChildren(normalizedData.children as ModelDepsData[]); | normalizeChildren(normalizedData.children as ModelDepsData[]); | ||||
| normalizedData.level = 0; | normalizedData.level = 0; | ||||
| // 将 parent_models 转换成树形结构 | // 将 parent_models 转换成树形结构 | ||||
| let parent_models = normalizedData.parent_models || []; | |||||
| while (parent_models.length > 0) { | |||||
| const parent = parent_models[0]; | |||||
| let parent_model = normalizedData.parent_model_vo; | |||||
| while (parent_model) { | |||||
| const parent = parent_model; | |||||
| normalizedData = { | normalizedData = { | ||||
| ...parent, | ...parent, | ||||
| expanded: false, | expanded: false, | ||||
| level: 0, | level: 0, | ||||
| datasetLen: parent.train_dataset.length + parent.test_dataset.length, | |||||
| datasetLen: getDatasetLen(parent.model_meta.train_datasets, parent.model_meta.test_datasets), | |||||
| model_type: NodeType.Parent, | model_type: NodeType.Parent, | ||||
| id: `$M_${parent.current_model_id}_${parent.version}`, | |||||
| id: `$M_${parent.repo_id}_${parent.version}`, | |||||
| label: getLabel(parent), | label: getLabel(parent), | ||||
| style: getStyle(NodeType.Parent), | style: getStyle(NodeType.Parent), | ||||
| children: [ | children: [ | ||||
| { | { | ||||
| ...normalizedData, | ...normalizedData, | ||||
| parent_models: [], | |||||
| parent_model: null, | |||||
| }, | }, | ||||
| ], | ], | ||||
| }; | }; | ||||
| parent_models = normalizedData.parent_models || []; | |||||
| parent_model = normalizedData.parent_model_vo; | |||||
| } | } | ||||
| return normalizedData; | return normalizedData; | ||||
| } | } | ||||
| @@ -195,11 +202,12 @@ export function getGraphData(data: ModelDepsData, hierarchyNodes: ModelDepsData[ | |||||
| getWidth: () => nodeWidth, | getWidth: () => nodeWidth, | ||||
| getVGap: (node: NodeConfig) => { | getVGap: (node: NodeConfig) => { | ||||
| const model = node as ModelDepsData; | const model = node as ModelDepsData; | ||||
| const { model_type, expanded, project_dependency } = model; | |||||
| const { model_type, expanded, model_meta } = model; | |||||
| const { project_depency } = model_meta; | |||||
| if (model_type === NodeType.Current || model_type === NodeType.Parent) { | if (model_type === NodeType.Current || model_type === NodeType.Parent) { | ||||
| return vGap / 2; | return vGap / 2; | ||||
| } | } | ||||
| const selfGap = expanded && project_dependency?.url ? nodeHeight + vGap : 0; | |||||
| const selfGap = expanded && project_depency?.url ? nodeHeight + vGap : 0; | |||||
| const nextNode = getSameHierarchyNextNode(model, hierarchyNodes); | const nextNode = getSameHierarchyNextNode(model, hierarchyNodes); | ||||
| if (!nextNode) { | if (!nextNode) { | ||||
| return vGap / 2; | return vGap / 2; | ||||
| @@ -254,28 +262,35 @@ const addDatasetDependency = ( | |||||
| nodes: NodeConfig[], | nodes: NodeConfig[], | ||||
| edges: EdgeConfig[], | edges: EdgeConfig[], | ||||
| ) => { | ) => { | ||||
| const { train_dataset, test_dataset, id } = data; | |||||
| train_dataset.forEach((item) => { | |||||
| item.id = `$DTrain_${id}_${item.dataset_id}_${item.dataset_version}`; | |||||
| const { repo_id, model_meta } = data; | |||||
| const { train_datasets, test_datasets } = model_meta; | |||||
| train_datasets?.forEach((item) => { | |||||
| if (!item.repo_id) { | |||||
| item.repo_id = item.id; | |||||
| } | |||||
| item.id = `$DTrain_${repo_id}_${item.repo_id}_${item.version}`; | |||||
| item.model_type = NodeType.TrainDataset; | item.model_type = NodeType.TrainDataset; | ||||
| item.style = getStyle(NodeType.TrainDataset); | item.style = getStyle(NodeType.TrainDataset); | ||||
| }); | }); | ||||
| test_dataset.forEach((item) => { | |||||
| item.id = `$DTest_${id}_${item.dataset_id}_${item.dataset_version}`; | |||||
| test_datasets?.forEach((item) => { | |||||
| if (!item.repo_id) { | |||||
| item.repo_id = item.id; | |||||
| } | |||||
| item.id = `$DTest_${repo_id}_${item.repo_id}_${item.version}`; | |||||
| item.model_type = NodeType.TestDataset; | item.model_type = NodeType.TestDataset; | ||||
| item.style = getStyle(NodeType.TestDataset); | item.style = getStyle(NodeType.TestDataset); | ||||
| }); | }); | ||||
| datasetNodes.length = 0; | datasetNodes.length = 0; | ||||
| const len = train_dataset.length + test_dataset.length; | |||||
| [...train_dataset, ...test_dataset].forEach((item, index) => { | |||||
| const len = getDatasetLen(train_datasets, test_datasets); | |||||
| [...(train_datasets ?? []), ...(test_datasets ?? [])].forEach((item, index) => { | |||||
| const node = { ...item }; | const node = { ...item }; | ||||
| node.type = 'ellipse'; | node.type = 'ellipse'; | ||||
| node.size = [ellipseWidth, nodeHeight]; | node.size = [ellipseWidth, nodeHeight]; | ||||
| node.label = | node.label = | ||||
| fittingString(node.dataset_name, ellipseWidth - labelPadding, nodeFontSize) + | |||||
| fittingString(node.name, ellipseWidth - labelPadding, nodeFontSize) + | |||||
| '\n' + | '\n' + | ||||
| fittingString(node.dataset_version, ellipseWidth - labelPadding, nodeFontSize); | |||||
| fittingString(node.version, ellipseWidth - labelPadding, nodeFontSize); | |||||
| const half = len / 2 - 0.5; | const half = len / 2 - 0.5; | ||||
| node.x = currentNode.x! - (half - index) * (ellipseWidth + datasetHGap); | node.x = currentNode.x! - (half - index) * (ellipseWidth + datasetHGap); | ||||
| @@ -299,10 +314,11 @@ const addProjectDependency = ( | |||||
| nodes: NodeConfig[], | nodes: NodeConfig[], | ||||
| edges: EdgeConfig[], | edges: EdgeConfig[], | ||||
| ) => { | ) => { | ||||
| const { project_dependency, id } = data; | |||||
| if (project_dependency?.url) { | |||||
| const node = { ...project_dependency }; | |||||
| node.id = `$P_${id}_${node.url}_${node.branch}`; | |||||
| const { repo_id, model_meta } = data; | |||||
| const { project_depency } = model_meta; | |||||
| if (project_depency?.url) { | |||||
| const node = { ...project_depency }; | |||||
| node.id = `$P_${repo_id}_${node.url}_${node.branch}`; | |||||
| node.model_type = NodeType.Project; | node.model_type = NodeType.Project; | ||||
| node.type = 'rect'; | node.type = 'rect'; | ||||
| node.label = fittingString(node.name, nodeWidth - labelPadding, nodeFontSize); | node.label = fittingString(node.name, nodeWidth - labelPadding, nodeFontSize); | ||||
| @@ -322,6 +338,7 @@ const addProjectDependency = ( | |||||
| } | } | ||||
| }; | }; | ||||
| /* | |||||
| // 判断两个矩形是否相交 | // 判断两个矩形是否相交 | ||||
| function isRectanglesOverlap(rect1: Rect, rect2: Rect) { | function isRectanglesOverlap(rect1: Rect, rect2: Rect) { | ||||
| const a2x = rect1.x + rect1.width / 2; | const a2x = rect1.x + rect1.width / 2; | ||||
| @@ -366,6 +383,7 @@ function adjustDatasetPosition(node: NodeConfig) { | |||||
| }); | }); | ||||
| } | } | ||||
| } | } | ||||
| */ | |||||
| // 层级遍历树结构 | // 层级遍历树结构 | ||||
| export function traverseHierarchically(data: ModelDepsData | undefined): ModelDepsData[] { | export function traverseHierarchically(data: ModelDepsData | undefined): ModelDepsData[] { | ||||
| @@ -2,6 +2,7 @@ | |||||
| position: absolute; | position: absolute; | ||||
| bottom: -100px; | bottom: -100px; | ||||
| left: -300px; | left: -300px; | ||||
| z-index: 10; | |||||
| width: 300px; | width: 300px; | ||||
| padding: 10px; | padding: 10px; | ||||
| background: white; | background: white; | ||||
| @@ -50,6 +51,7 @@ | |||||
| flex: 1; | flex: 1; | ||||
| min-width: 0; | min-width: 0; | ||||
| font-weight: 500; | font-weight: 500; | ||||
| word-break: break-all; | |||||
| &:hover { | &:hover { | ||||
| text-decoration: underline @underline-color; | text-decoration: underline @underline-color; | ||||
| @@ -14,9 +14,9 @@ function ModelInfo({ resourceId, data, onVersionChange }: ModelInfoProps) { | |||||
| const navigate = useNavigate(); | const navigate = useNavigate(); | ||||
| const gotoExperimentPage = () => { | const gotoExperimentPage = () => { | ||||
| if (data.train_task?.ins_id) { | |||||
| if (data.model_meta.train_task?.ins_id) { | |||||
| const { origin } = location; | const { origin } = location; | ||||
| const url = `${origin}/pipeline/experiment/instance/${data.workflow_id}/${data.train_task.ins_id}`; | |||||
| const url = `${origin}/pipeline/experiment/instance/${data.model_meta.train_task.task_id}/${data.model_meta.train_task.ins_id}`; | |||||
| window.open(url, '_blank'); | window.open(url, '_blank'); | ||||
| } | } | ||||
| }; | }; | ||||
| @@ -25,10 +25,10 @@ function ModelInfo({ resourceId, data, onVersionChange }: ModelInfoProps) { | |||||
| if (data.model_type === NodeType.Current) { | if (data.model_type === NodeType.Current) { | ||||
| return; | return; | ||||
| } | } | ||||
| if (data.current_model_id === resourceId) { | |||||
| if (data.repo_id === resourceId) { | |||||
| onVersionChange?.(data.version); | onVersionChange?.(data.version); | ||||
| } else { | } else { | ||||
| const path = `/dataset/model/info/${data.current_model_id}?tab=${ResourceInfoTabKeys.Evolution}&version=${data.version}`; | |||||
| const path = `/dataset/model/info/${data.repo_id}?tab=${ResourceInfoTabKeys.Evolution}&version=${data.version}&name=${data.model_name}&owner=${data.owner}&identifier=${data.identifier}`; | |||||
| navigate(path); | navigate(path); | ||||
| } | } | ||||
| }; | }; | ||||
| @@ -40,12 +40,10 @@ function ModelInfo({ resourceId, data, onVersionChange }: ModelInfoProps) { | |||||
| <div className={styles['node-tooltips__row']}> | <div className={styles['node-tooltips__row']}> | ||||
| <span className={styles['node-tooltips__row__title']}>模型名称:</span> | <span className={styles['node-tooltips__row__title']}>模型名称:</span> | ||||
| {data.model_type === NodeType.Current ? ( | {data.model_type === NodeType.Current ? ( | ||||
| <span className={styles['node-tooltips__row__value']}> | |||||
| {data.model_version_dependcy_vo?.name || '--'} | |||||
| </span> | |||||
| <span className={styles['node-tooltips__row__value']}>{data.model_name || '--'}</span> | |||||
| ) : ( | ) : ( | ||||
| <ValueLink | <ValueLink | ||||
| value={data.model_version_dependcy_vo?.name} | |||||
| value={data.model_name} | |||||
| className={styles['node-tooltips__row__link']} | className={styles['node-tooltips__row__link']} | ||||
| nullClassName={styles['node-tooltips__row__value']} | nullClassName={styles['node-tooltips__row__value']} | ||||
| onClick={gotoModelPage} | onClick={gotoModelPage} | ||||
| @@ -59,25 +57,25 @@ function ModelInfo({ resourceId, data, onVersionChange }: ModelInfoProps) { | |||||
| <div className={styles['node-tooltips__row']}> | <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']}> | <span className={styles['node-tooltips__row__value']}> | ||||
| {data.model_version_dependcy_vo?.model_type_name || '--'} | |||||
| {data.model_meta.model_type || '--'} | |||||
| </span> | </span> | ||||
| </div> | </div> | ||||
| <div className={styles['node-tooltips__row']}> | <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']}> | <span className={styles['node-tooltips__row__value']}> | ||||
| {data.model_version_dependcy_vo?.file_size || '--'} | |||||
| {data.model_meta.file_size || '--'} | |||||
| </span> | </span> | ||||
| </div> | </div> | ||||
| <div className={styles['node-tooltips__row']}> | <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']}> | <span className={styles['node-tooltips__row__value']}> | ||||
| {formatDate(data.model_version_dependcy_vo?.create_time)} | |||||
| {formatDate(data.model_meta.create_time || '--')} | |||||
| </span> | </span> | ||||
| </div> | </div> | ||||
| <div className={styles['node-tooltips__row']}> | <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']}> | <span className={styles['node-tooltips__row__value']}> | ||||
| {data.model_version_dependcy_vo?.available_range === 1 ? '公开' : '私有'} | |||||
| {data.model_meta.is_public ? '公开' : '私有'} | |||||
| </span> | </span> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| @@ -86,7 +84,7 @@ function ModelInfo({ resourceId, data, onVersionChange }: ModelInfoProps) { | |||||
| <div className={styles['node-tooltips__row']}> | <div className={styles['node-tooltips__row']}> | ||||
| <span className={styles['node-tooltips__row__title']}>训练任务:</span> | <span className={styles['node-tooltips__row__title']}>训练任务:</span> | ||||
| <ValueLink | <ValueLink | ||||
| value={data.train_task?.name} | |||||
| value={data.model_meta.train_task?.name} | |||||
| className={styles['node-tooltips__row__link']} | className={styles['node-tooltips__row__link']} | ||||
| nullClassName={styles['node-tooltips__row__value']} | nullClassName={styles['node-tooltips__row__value']} | ||||
| onClick={gotoExperimentPage} | onClick={gotoExperimentPage} | ||||
| @@ -100,7 +98,7 @@ function ModelInfo({ resourceId, data, onVersionChange }: ModelInfoProps) { | |||||
| function DatasetInfo({ data }: { data: TrainDataset }) { | function DatasetInfo({ data }: { data: TrainDataset }) { | ||||
| const gotoDatasetPage = () => { | const gotoDatasetPage = () => { | ||||
| const { origin } = location; | const { origin } = location; | ||||
| const url = `${origin}/dataset/dataset/info/${data.dataset_id}?tab=${ResourceInfoTabKeys.Version}&version=${data.dataset_version}`; | |||||
| const url = `${origin}/dataset/dataset/info/${data.repo_id}?tab=${ResourceInfoTabKeys.Version}&version=${data.version}&name=${data.name}&owner=${data.owner}&identifier=${data.identifier}`; | |||||
| window.open(url, '_blank'); | window.open(url, '_blank'); | ||||
| }; | }; | ||||
| @@ -111,7 +109,7 @@ function DatasetInfo({ data }: { data: TrainDataset }) { | |||||
| <div className={styles['node-tooltips__row']}> | <div className={styles['node-tooltips__row']}> | ||||
| <span className={styles['node-tooltips__row__title']}>数据集名称:</span> | <span className={styles['node-tooltips__row__title']}>数据集名称:</span> | ||||
| <ValueLink | <ValueLink | ||||
| value={data.dataset_name} | |||||
| value={data.name} | |||||
| className={styles['node-tooltips__row__link']} | className={styles['node-tooltips__row__link']} | ||||
| nullClassName={styles['node-tooltips__row__value']} | nullClassName={styles['node-tooltips__row__value']} | ||||
| onClick={gotoDatasetPage} | onClick={gotoDatasetPage} | ||||
| @@ -119,9 +117,7 @@ function DatasetInfo({ data }: { data: TrainDataset }) { | |||||
| </div> | </div> | ||||
| <div className={styles['node-tooltips__row']}> | <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.dataset_version || '--'} | |||||
| </span> | |||||
| <span className={styles['node-tooltips__row__value']}>{data.version || '--'}</span> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| </> | </> | ||||
| @@ -204,11 +204,14 @@ const PipelineNodeParameter = forwardRef(({ onFormChange }: PipelineNodeParamete | |||||
| }); | }); | ||||
| } | } | ||||
| } else { | } else { | ||||
| const { activeTab, id, name, version, path } = res; | |||||
| const { activeTab, id, name, version, path, identifier, owner } = res; | |||||
| const value = JSON.stringify({ | const value = JSON.stringify({ | ||||
| id, | id, | ||||
| name, | |||||
| version, | version, | ||||
| path, | path, | ||||
| identifier, | |||||
| owner, | |||||
| }); | }); | ||||
| const showValue = `${name}:${version}`; | const showValue = `${name}:${version}`; | ||||
| form.setFieldValue(formItemName, { | form.setFieldValue(formItemName, { | ||||
| @@ -74,121 +74,6 @@ const convertMirrorVersionToTreeData = ( | |||||
| })); | })); | ||||
| }; | }; | ||||
| // 从树形数据节点 id 中获取数据集版本列表的参数 | |||||
| // const parseDatasetVersionId = (id: string) => { | |||||
| // const list = id.split('-'); | |||||
| // return { | |||||
| // id: Number(list[0]), | |||||
| // name: list[1], | |||||
| // owner: list[2], | |||||
| // identifier: list[3], | |||||
| // version: list[4], | |||||
| // }; | |||||
| // }; | |||||
| // 从树形数据节点 id 中获取数据集版本列表的参数 | |||||
| // const parseMirrorVersionId = (id: string) => { | |||||
| // const list = id.split('-'); | |||||
| // return { | |||||
| // parentId: Number(list[0]), | |||||
| // id: list[1], | |||||
| // url: list[2], | |||||
| // }; | |||||
| // }; | |||||
| // export type MirrorVersion = { | |||||
| // id: number; // 镜像版本 id | |||||
| // status: MirrorVersionStatus; // 镜像版本状态 | |||||
| // tag_name: string; // 镜像版本 name | |||||
| // url: string; // 镜像版本路径 | |||||
| // }; | |||||
| // export type SelectorTypeInfo = { | |||||
| // getList: (params: any) => Promise<any>; // 获取资源列表 | |||||
| // getVersions: (params: any) => Promise<any>; // 获取资源版本列表 | |||||
| // getFiles: (params: any) => Promise<any>; // 获取资源文件列表 | |||||
| // handleVersionResponse: (res: any) => any[]; // 处理版本列表接口数据 | |||||
| // dataToTreeData: (data: any) => TreeDataNode[]; // 数据转树形结构 | |||||
| // parseTreeNodeId: (id: string) => any; // 获取版本列表请求参数 | |||||
| // modalIcon: string; // modal icon | |||||
| // buttonIcon: string; // button icon | |||||
| // name: string; // 名称 | |||||
| // litReqParamKey: 'available_range' | 'image_type'; // 表示是公开还是私有的参数名称,获取资源列表接口使用 | |||||
| // tabItems: TabsProps['items']; // tab 列表 | |||||
| // buttontTitle: string; // 按钮 title | |||||
| // }; | |||||
| // export const selectorTypeConfig: Record<ResourceSelectorType, SelectorTypeInfo> = { | |||||
| // [ResourceSelectorType.Model]: { | |||||
| // getList: getModelList, | |||||
| // getVersions: getModelVersionList, | |||||
| // getFiles: getModelVersionIdList, | |||||
| // name: '模型', | |||||
| // modalIcon: modelImg, | |||||
| // buttonIcon: 'icon-xuanzemoxing', | |||||
| // litReqParamKey: 'available_range', | |||||
| // tabItems: [ | |||||
| // { | |||||
| // key: CommonTabKeys.Private, | |||||
| // label: '我的模型', | |||||
| // }, | |||||
| // { | |||||
| // key: CommonTabKeys.Public, | |||||
| // label: '公开模型', | |||||
| // }, | |||||
| // ], | |||||
| // buttontTitle: '选择模型', | |||||
| // }, | |||||
| // [ResourceSelectorType.Dataset]: { | |||||
| // getList: getDatasetList, | |||||
| // getVersions: getDatasetVersionList, | |||||
| // getFiles: getDatasetInfo, | |||||
| // name: '数据集', | |||||
| // modalIcon: datasetImg, | |||||
| // buttonIcon: 'icon-xuanzeshujuji', | |||||
| // litReqParamKey: 'available_range', | |||||
| // tabItems: [ | |||||
| // { | |||||
| // key: CommonTabKeys.Private, | |||||
| // label: '我的数据集', | |||||
| // }, | |||||
| // { | |||||
| // key: CommonTabKeys.Public, | |||||
| // label: '公开数据集', | |||||
| // }, | |||||
| // ], | |||||
| // buttontTitle: '选择数据集', | |||||
| // }, | |||||
| // [ResourceSelectorType.Mirror]: { | |||||
| // getList: getMirrorListReq, | |||||
| // getVersions: (id: number) => getMirrorVersionListReq({ image_id: id, page: 0, size: 200 }), | |||||
| // getFiles: getMirrorFilesReq, | |||||
| // handleVersionResponse: (res) => | |||||
| // res.data?.content?.filter( | |||||
| // (v: MirrorVersionData) => v.status === MirrorVersionStatus.Available, | |||||
| // ) || [], | |||||
| // dataToTreeData: convertMirrorToTreeData, | |||||
| // parseTreeNodeId: (id: string) => id, | |||||
| // name: '镜像', | |||||
| // modalIcon: mirrorImg, | |||||
| // buttonIcon: 'icon-xuanzejingxiang', | |||||
| // litReqParamKey: 'image_type', | |||||
| // tabItems: [ | |||||
| // { | |||||
| // key: CommonTabKeys.Private, | |||||
| // label: '我的镜像', | |||||
| // }, | |||||
| // { | |||||
| // key: CommonTabKeys.Public, | |||||
| // label: '公开镜像', | |||||
| // }, | |||||
| // ], | |||||
| // buttontTitle: '选择镜像', | |||||
| // }, | |||||
| // }; | |||||
| interface SelectorTypeInfo { | interface SelectorTypeInfo { | ||||
| getList: (isPublic: boolean) => Promise<any>; // 获取资源列表 | getList: (isPublic: boolean) => Promise<any>; // 获取资源列表 | ||||
| getVersions: (parentKey: string, parentNode: any) => Promise<any>; // 获取资源版本列表 | getVersions: (parentKey: string, parentNode: any) => Promise<any>; // 获取资源版本列表 | ||||
| @@ -22,6 +22,8 @@ export type ResourceSelectorResponse = { | |||||
| name: string; // 数据集\模型\镜像 name | name: string; // 数据集\模型\镜像 name | ||||
| version: string; // 数据集\模型\镜像版本 | version: string; // 数据集\模型\镜像版本 | ||||
| path: string; // 数据集\模型\镜像版本路径 | path: string; // 数据集\模型\镜像版本路径 | ||||
| identifier: string; // 数据集\模型 identifier | |||||
| owner: string; // 数据集\模型 owner | |||||
| activeTab: CommonTabKeys; // 是我的还是公开的 | activeTab: CommonTabKeys; // 是我的还是公开的 | ||||
| }; | }; | ||||
| @@ -221,12 +223,17 @@ function ResourceSelectorModal({ | |||||
| if (checkedKeys.length > 0) { | if (checkedKeys.length > 0) { | ||||
| const last = checkedKeys[0] as string; | const last = checkedKeys[0] as string; | ||||
| const { id, version } = getIdAndVersion(last); | const { id, version } = getIdAndVersion(last); | ||||
| const name = (treeData.find((v) => v.key === id)?.title ?? '') as string; | |||||
| const treeNode = treeData.find((v) => v.key === id) as any; | |||||
| const name = (treeNode?.title ?? '') as string; | |||||
| const identifier = (treeNode?.identifier ?? '') as string; | |||||
| const owner = (treeNode?.owner ?? '') as string; | |||||
| const res = { | const res = { | ||||
| id, | id, | ||||
| name, | name, | ||||
| path: versionPath, | path: versionPath, | ||||
| version, | version, | ||||
| identifier, | |||||
| owner, | |||||
| activeTab: activeTab as CommonTabKeys, | activeTab: activeTab as CommonTabKeys, | ||||
| }; | }; | ||||
| onOk?.(res); | onOk?.(res); | ||||
| @@ -12,17 +12,17 @@ public interface GitService { | |||||
| String checkoutToken(); | String checkoutToken(); | ||||
| //输入token,项目名,tag,创建新项目,返回项目地址 | //输入token,项目名,tag,创建新项目,返回项目地址 | ||||
| Map createProject(GitProjectVo gitProjectVo) throws Exception; | |||||
| Map createProject(String token,GitProjectVo gitProjectVo) throws Exception; | |||||
| void createBranch(String owner, String projectName, String branchName, String oldBranchName) throws Exception; | |||||
| void createBranch(String token,String owner, String projectName, String branchName, String oldBranchName) throws Exception; | |||||
| void createTopic(Integer id, String topicName) throws Exception; | |||||
| void createTopic(String token,Integer id, String topicName) throws Exception; | |||||
| List<Map<String, Object>> getBrancheList(String owner, String projectName) throws Exception; | |||||
| List<Map<String, Object>> getBrancheList(String token,String owner, String projectName) throws Exception; | |||||
| void deleteProject(String owner, String projectName) throws Exception; | |||||
| void deleteProject(String token,String owner, String projectName) throws Exception; | |||||
| void deleteBranch(String owner, String projectName, String branchName, String localPath) throws Exception; | |||||
| void deleteBranch(String token,String owner, String projectName, String branchName, String localPath) throws Exception; | |||||
| Map getUserInfo(String token) throws Exception; | Map getUserInfo(String token) throws Exception; | ||||
| } | } | ||||
| @@ -165,7 +165,9 @@ public class DatasetVersionServiceImpl implements DatasetVersionService { | |||||
| .findFirst() | .findFirst() | ||||
| .ifPresent(datasetVersion -> { | .ifPresent(datasetVersion -> { | ||||
| String url = datasetVersion.getUrl(); | String url = datasetVersion.getUrl(); | ||||
| response.put("path", url); | |||||
| // response.put("path", url); | |||||
| String path = bucketName + '/' + url.substring(0, url.lastIndexOf('/')); | |||||
| response.put("path", path); | |||||
| }); | }); | ||||
| response.put("content", datasetVersionList); | response.put("content", datasetVersionList); | ||||
| @@ -28,7 +28,8 @@ public class GitServiceImpl implements GitService { | |||||
| @Value("${spring.redis.host}") | @Value("${spring.redis.host}") | ||||
| private String redisHost; | private String redisHost; | ||||
| @Value("${spring.redis.port}") | |||||
| private Integer redisPort; | |||||
| private static final Logger log = LoggerFactory.getLogger(GitServiceImpl.class); | private static final Logger log = LoggerFactory.getLogger(GitServiceImpl.class); | ||||
| @Override | @Override | ||||
| @@ -61,7 +62,7 @@ public class GitServiceImpl implements GitService { | |||||
| LoginUser loginUser = SecurityUtils.getLoginUser(); | LoginUser loginUser = SecurityUtils.getLoginUser(); | ||||
| String ci4sUsername = loginUser.getUsername(); | String ci4sUsername = loginUser.getUsername(); | ||||
| // 将access_token存入Redis | // 将access_token存入Redis | ||||
| Jedis jedis = new Jedis(redisHost); | |||||
| Jedis jedis = new Jedis(redisHost,redisPort); | |||||
| jedis.set(ci4sUsername + "_gitToken", accessToken); | jedis.set(ci4sUsername + "_gitToken", accessToken); | ||||
| jedis.set(ci4sUsername + "_gitUserInfo", userReq); | jedis.set(ci4sUsername + "_gitUserInfo", userReq); | ||||
| return accessToken; | return accessToken; | ||||
| @@ -72,7 +73,7 @@ public class GitServiceImpl implements GitService { | |||||
| } | } | ||||
| public String checkoutToken() { | public String checkoutToken() { | ||||
| Jedis jedis = new Jedis(redisHost); | |||||
| Jedis jedis = new Jedis(redisHost,redisPort); | |||||
| LoginUser loginUser = SecurityUtils.getLoginUser(); | LoginUser loginUser = SecurityUtils.getLoginUser(); | ||||
| String ci4sUsername = loginUser.getUsername(); | String ci4sUsername = loginUser.getUsername(); | ||||
| String token = jedis.get(ci4sUsername + "_gitToken"); | String token = jedis.get(ci4sUsername + "_gitToken"); | ||||
| @@ -98,20 +99,18 @@ public class GitServiceImpl implements GitService { | |||||
| } | } | ||||
| @Override | @Override | ||||
| public Map createProject(GitProjectVo gitProjectVo) throws Exception { | |||||
| String token = this.checkoutToken(); | |||||
| public Map createProject(String token,GitProjectVo gitProjectVo) throws Exception { | |||||
| String userReq = HttpUtils.sendPostWithToken("https://www.gitlink.org.cn/api/projects.json", JsonUtils.objectToJson(gitProjectVo), token); | String userReq = HttpUtils.sendPostWithToken("https://www.gitlink.org.cn/api/projects.json", JsonUtils.objectToJson(gitProjectVo), token); | ||||
| return JsonUtils.jsonToMap(userReq); | return JsonUtils.jsonToMap(userReq); | ||||
| } | } | ||||
| @Override | @Override | ||||
| public void createBranch(String owner, String projectName, String branchName, String oldBranchName) throws Exception { | |||||
| public void createBranch(String token,String owner, String projectName, String branchName, String oldBranchName) throws Exception { | |||||
| //https://www.gitlink.org.cn/api/v1/fanshuai/testdssa8755/branches.json | //https://www.gitlink.org.cn/api/v1/fanshuai/testdssa8755/branches.json | ||||
| // { | // { | ||||
| // "new_branch_name": "SsS", | // "new_branch_name": "SsS", | ||||
| // "old_branch_name": "master" | // "old_branch_name": "master" | ||||
| // } | // } | ||||
| String token = this.checkoutToken(); | |||||
| String createBranchUrl = "https://www.gitlink.org.cn/api/v1/" + owner + "/" + projectName + "/branches.json"; | String createBranchUrl = "https://www.gitlink.org.cn/api/v1/" + owner + "/" + projectName + "/branches.json"; | ||||
| Map<String, Object> resMap = new HashMap<>(); | Map<String, Object> resMap = new HashMap<>(); | ||||
| resMap.put("new_branch_name", branchName); | resMap.put("new_branch_name", branchName); | ||||
| @@ -121,9 +120,8 @@ public class GitServiceImpl implements GitService { | |||||
| } | } | ||||
| @Override | @Override | ||||
| public void createTopic(Integer id, String topicName) throws Exception { | |||||
| public void createTopic(String token,Integer id, String topicName) throws Exception { | |||||
| // https://www.gitlink.org.cn/api/v1/project_topics.json | // https://www.gitlink.org.cn/api/v1/project_topics.json | ||||
| String token = this.checkoutToken(); | |||||
| Map<String, Object> resMap = new HashMap<>(); | Map<String, Object> resMap = new HashMap<>(); | ||||
| resMap.put("project_id", id); | resMap.put("project_id", id); | ||||
| resMap.put("name", topicName); | resMap.put("name", topicName); | ||||
| @@ -131,8 +129,7 @@ public class GitServiceImpl implements GitService { | |||||
| } | } | ||||
| @Override | @Override | ||||
| public List<Map<String, Object>> getBrancheList(String owner, String projectName) throws Exception { | |||||
| String token = checkoutToken(); | |||||
| public List<Map<String, Object>> getBrancheList(String token,String owner, String projectName) throws Exception { | |||||
| String req = HttpUtils.sendGetWithToken("https://www.gitlink.org.cn/api/v1/" + owner + "/" + projectName + "/branches/all.json", null, token); | String req = HttpUtils.sendGetWithToken("https://www.gitlink.org.cn/api/v1/" + owner + "/" + projectName + "/branches/all.json", null, token); | ||||
| // 解析响应JSON | // 解析响应JSON | ||||
| if (StringUtils.isEmpty(req)) { | if (StringUtils.isEmpty(req)) { | ||||
| @@ -144,20 +141,18 @@ public class GitServiceImpl implements GitService { | |||||
| } | } | ||||
| @Override | @Override | ||||
| public void deleteProject(String owner, String projectName) throws Exception { | |||||
| String token = this.checkoutToken(); | |||||
| public void deleteProject(String token,String owner, String projectName) throws Exception { | |||||
| HttpUtils.sendDeleteRequest("https://www.gitlink.org.cn/api/" + owner + "/" + projectName + ".json", token); | HttpUtils.sendDeleteRequest("https://www.gitlink.org.cn/api/" + owner + "/" + projectName + ".json", token); | ||||
| } | } | ||||
| @Override | @Override | ||||
| public void deleteBranch(String owner, String projectName, String branchName, String localPath) throws Exception { | |||||
| public void deleteBranch(String token,String owner, String projectName, String branchName, String localPath) throws Exception { | |||||
| try (Git git = Git.open(new File(localPath))) { | try (Git git = Git.open(new File(localPath))) { | ||||
| git.checkout().setName("master").call(); | git.checkout().setName("master").call(); | ||||
| git.branchDelete().setBranchNames(branchName).setForce(true).call(); | git.branchDelete().setBranchNames(branchName).setForce(true).call(); | ||||
| } catch (IOException | GitAPIException e) { | } catch (IOException | GitAPIException e) { | ||||
| log.error("Exception occurred while creating local branch based on master",e); | log.error("Exception occurred while creating local branch based on master",e); | ||||
| } | } | ||||
| String token = this.checkoutToken(); | |||||
| HttpUtils.sendDeleteRequest("https://www.gitlink.org.cn/api/v1/" + owner + "/" + projectName + "/branches/" + branchName + ".json", token); | HttpUtils.sendDeleteRequest("https://www.gitlink.org.cn/api/v1/" + owner + "/" + projectName + "/branches/" + branchName + ".json", token); | ||||
| } | } | ||||
| @@ -61,7 +61,9 @@ public class ImageServiceImpl implements ImageService { | |||||
| @Resource | @Resource | ||||
| private MinioService minioService; | private MinioService minioService; | ||||
| @Value("${minio.dataReleaseBucketName}") | |||||
| // @Value("${minio.dataReleaseBucketName}") | |||||
| // private String bucketName; | |||||
| @Value("${harbor.bucketName}") | |||||
| private String bucketName; | private String bucketName; | ||||
| @Value("${harbor.repository}") | @Value("${harbor.repository}") | ||||
| private String repository; | private String repository; | ||||
| @@ -90,23 +90,25 @@ public class JupyterServiceImpl implements JupyterService { | |||||
| // 提取数据集,模型信息,得到数据集模型的path | // 提取数据集,模型信息,得到数据集模型的path | ||||
| Map<String, Object> dataset = JacksonUtil.parseJSONStr2Map(devEnvironment.getDataset()); | Map<String, Object> dataset = JacksonUtil.parseJSONStr2Map(devEnvironment.getDataset()); | ||||
| String datasetPath = (String) dataset.get("path"); | |||||
| String datasetPath = "argo-workflow" + "/" + dataset.get("path"); | |||||
| // String datasetPath = (String) dataset.get("path"); | |||||
| Map<String, Object> model = JacksonUtil.parseJSONStr2Map(devEnvironment.getModel()); | Map<String, Object> model = JacksonUtil.parseJSONStr2Map(devEnvironment.getModel()); | ||||
| String modelPath = (String) model.get("path"); | |||||
| String modelPath = "argo-workflow" + "/" + model.get("path"); | |||||
| // String modelPath = (String) model.get("path"); | |||||
| LoginUser loginUser = SecurityUtils.getLoginUser(); | LoginUser loginUser = SecurityUtils.getLoginUser(); | ||||
| //构造pod名称 | //构造pod名称 | ||||
| String podName = loginUser.getUsername().toLowerCase() + "-editor-pod" + "-" + id; | String podName = loginUser.getUsername().toLowerCase() + "-editor-pod" + "-" + id; | ||||
| //新建编辑器的pvc | //新建编辑器的pvc | ||||
| // String pvcName = loginUser.getUsername().toLowerCase() + "-editor-pvc"; | |||||
| // V1PersistentVolumeClaim pvc = k8sClientUtil.createPvc(namespace, pvcName, storage, storageClassName); | |||||
| String pvcName = loginUser.getUsername().toLowerCase() + "-editor-pvc"; | |||||
| V1PersistentVolumeClaim pvc = k8sClientUtil.createPvc(namespace, pvcName, storage, storageClassName); | |||||
| //TODO 设置镜像可配置,这里先用默认镜像启动pod | //TODO 设置镜像可配置,这里先用默认镜像启动pod | ||||
| // 调用修改后的 createPod 方法,传入额外的参数 | // 调用修改后的 createPod 方法,传入额外的参数 | ||||
| // Integer podPort = k8sClientUtil.createConfiguredPod(podName, namespace, port, mountPath, pvc, devEnvironment, minioPvcName, datasetPath, modelPath); | |||||
| Integer podPort = k8sClientUtil.createConfiguredPod(podName, namespace, port, mountPath, null, devEnvironment, minioPvcName, datasetPath, modelPath); | |||||
| Integer podPort = k8sClientUtil.createConfiguredPod(podName, namespace, port, mountPath, pvc, devEnvironment, minioPvcName, datasetPath, modelPath); | |||||
| // Integer podPort = k8sClientUtil.createConfiguredPod(podName, namespace, port, mountPath, null, devEnvironment, minioPvcName, datasetPath, modelPath); | |||||
| String url = masterIp + ":" + podPort; | String url = masterIp + ":" + podPort; | ||||
| redisService.setCacheObject(podName, masterIp + ":" + podPort); | redisService.setCacheObject(podName, masterIp + ":" + podPort); | ||||
| devEnvironment.setStatus("Pending"); | devEnvironment.setStatus("Pending"); | ||||
| @@ -86,6 +86,8 @@ public class ModelsServiceImpl implements ModelsService { | |||||
| @Value("${spring.redis.host}") | @Value("${spring.redis.host}") | ||||
| private String redisHost; | private String redisHost; | ||||
| @Value("${spring.redis.port}") | |||||
| private Integer redisPort; | |||||
| @Value("${git.endpoint}") | @Value("${git.endpoint}") | ||||
| String gitendpoint; | String gitendpoint; | ||||
| @Value("${git.localPath}") | @Value("${git.localPath}") | ||||
| @@ -540,6 +542,7 @@ public class ModelsServiceImpl implements ModelsService { | |||||
| @Override | @Override | ||||
| public String newCreateModel(ModelsVo modelsVo) { | public String newCreateModel(ModelsVo modelsVo) { | ||||
| try { | try { | ||||
| String token = gitService.checkoutToken(); | |||||
| LoginUser loginUser = SecurityUtils.getLoginUser(); | LoginUser loginUser = SecurityUtils.getLoginUser(); | ||||
| String ci4sUsername = loginUser.getUsername(); | String ci4sUsername = loginUser.getUsername(); | ||||
| String gitLinkUsername = loginUser.getSysUser().getGitLinkUsername(); | String gitLinkUsername = loginUser.getSysUser().getGitLinkUsername(); | ||||
| @@ -571,17 +574,17 @@ public class ModelsServiceImpl implements ModelsService { | |||||
| gitProjectVo.setUserId(userId); | gitProjectVo.setUserId(userId); | ||||
| // 创建项目 | // 创建项目 | ||||
| Map project = gitService.createProject(gitProjectVo); | |||||
| Map project = gitService.createProject(token,gitProjectVo); | |||||
| Integer gitlinIid = (Integer) project.get("id"); | Integer gitlinIid = (Integer) project.get("id"); | ||||
| if (gitlinIid == null) { | if (gitlinIid == null) { | ||||
| throw new Exception("创建模型失败:" + project.get("message")); | throw new Exception("创建模型失败:" + project.get("message")); | ||||
| } | } | ||||
| // 创建分支 | // 创建分支 | ||||
| gitService.createBranch((String) userInfo.get("login"), repositoryName, modelsVo.getVersion(), "master"); | |||||
| gitService.createBranch(token,(String) userInfo.get("login"), repositoryName, modelsVo.getVersion(), "master"); | |||||
| // 定义标签 标签1:ci4s_model 标签2:ModelTag 标签3:ModelType | // 定义标签 标签1:ci4s_model 标签2:ModelTag 标签3:ModelType | ||||
| gitService.createTopic(gitlinIid, "ci4s_model"); | |||||
| gitService.createTopic(gitlinIid, "modeltag_" + modelsVo.getModelTag()); | |||||
| gitService.createTopic(gitlinIid, "modeltype_" + modelsVo.getModelType()); | |||||
| gitService.createTopic(token,gitlinIid, "ci4s_model"); | |||||
| gitService.createTopic(token,gitlinIid, "modeltag_" + modelsVo.getModelTag()); | |||||
| gitService.createTopic(token,gitlinIid, "modeltype_" + modelsVo.getModelType()); | |||||
| String branchName = modelsVo.getVersion(); | String branchName = modelsVo.getVersion(); | ||||
| String owner = (String) userInfo.get("login"); | String owner = (String) userInfo.get("login"); | ||||
| @@ -882,7 +885,8 @@ public class ModelsServiceImpl implements ModelsService { | |||||
| @Override | @Override | ||||
| public List<Map<String, Object>> getVersionList(String identifier, String owner) throws Exception { | public List<Map<String, Object>> getVersionList(String identifier, String owner) throws Exception { | ||||
| List<Map<String, Object>> brancheList = gitService.getBrancheList(owner, identifier); | |||||
| String token = gitService.checkoutToken(); | |||||
| List<Map<String, Object>> brancheList = gitService.getBrancheList(token,owner, identifier); | |||||
| return brancheList.stream() | return brancheList.stream() | ||||
| .filter(branch -> !"master".equals(branch.get("name"))) | .filter(branch -> !"master".equals(branch.get("name"))) | ||||
| .collect(Collectors.toList()); | .collect(Collectors.toList()); | ||||
| @@ -949,7 +953,8 @@ public class ModelsServiceImpl implements ModelsService { | |||||
| @Override | @Override | ||||
| public void deleteModel(Integer repoId, String identifier, String owner) throws Exception { | public void deleteModel(Integer repoId, String identifier, String owner) throws Exception { | ||||
| gitService.deleteProject(owner, identifier); | |||||
| String token = gitService.checkoutToken(); | |||||
| gitService.deleteProject(token,owner, identifier); | |||||
| //删除模型依赖 | //删除模型依赖 | ||||
| modelDependency1Dao.deleteModel(repoId, identifier, owner, null); | modelDependency1Dao.deleteModel(repoId, identifier, owner, null); | ||||
| @@ -962,7 +967,8 @@ public class ModelsServiceImpl implements ModelsService { | |||||
| @Override | @Override | ||||
| public void deleteVersion(Integer repoId, String identifier, String owner, String version, String relativePath) throws Exception { | public void deleteVersion(Integer repoId, String identifier, String owner, String version, String relativePath) throws Exception { | ||||
| gitService.deleteBranch(owner, identifier, version, localPath + relativePath); | |||||
| String token = gitService.checkoutToken(); | |||||
| gitService.deleteBranch(token,owner, identifier, version, localPath + relativePath); | |||||
| //删除模型依赖 | //删除模型依赖 | ||||
| modelDependency1Dao.deleteModel(repoId, identifier, owner, version); | modelDependency1Dao.deleteModel(repoId, identifier, owner, version); | ||||
| HashMap<String, Object> map = new HashMap<>(); | HashMap<String, Object> map = new HashMap<>(); | ||||
| @@ -1053,7 +1059,7 @@ public class ModelsServiceImpl implements ModelsService { | |||||
| } | } | ||||
| Map<String, Object> getUserInfo(String ci4sUsername, String gitLinkUsername, String gitLinkPassword) throws IOException { | Map<String, Object> getUserInfo(String ci4sUsername, String gitLinkUsername, String gitLinkPassword) throws IOException { | ||||
| Jedis jedis = new Jedis(redisHost); | |||||
| Jedis jedis = new Jedis(redisHost,redisPort); | |||||
| String userReq = jedis.get(ci4sUsername + "_gitUserInfo"); | String userReq = jedis.get(ci4sUsername + "_gitUserInfo"); | ||||
| if (userReq == null) { | if (userReq == null) { | ||||
| gitService.login(gitLinkUsername, gitLinkPassword); | gitService.login(gitLinkUsername, gitLinkPassword); | ||||
| @@ -50,6 +50,8 @@ public class NewDatasetServiceImpl implements NewDatasetService { | |||||
| private DvcService dvcService; | private DvcService dvcService; | ||||
| @Value("${spring.redis.host}") | @Value("${spring.redis.host}") | ||||
| private String redisHost; | private String redisHost; | ||||
| @Value("${spring.redis.port}") | |||||
| private Integer redisPort; | |||||
| @Value("${minio.accessKey}") | @Value("${minio.accessKey}") | ||||
| String accessKeyId; | String accessKeyId; | ||||
| @Value("${minio.secretKey}") | @Value("${minio.secretKey}") | ||||
| @@ -64,7 +66,8 @@ public class NewDatasetServiceImpl implements NewDatasetService { | |||||
| private DatasetTempStorageService datasetTempStorageService; | private DatasetTempStorageService datasetTempStorageService; | ||||
| @Override | @Override | ||||
| public String newCreateDataset(NewDatasetVo datasetVo) throws Exception { | public String newCreateDataset(NewDatasetVo datasetVo) throws Exception { | ||||
| Jedis jedis = new Jedis(redisHost); | |||||
| String token = gitService.checkoutToken(); | |||||
| Jedis jedis = new Jedis(redisHost,redisPort); | |||||
| LoginUser loginUser = SecurityUtils.getLoginUser(); | LoginUser loginUser = SecurityUtils.getLoginUser(); | ||||
| String ci4sUsername = loginUser.getUsername(); | String ci4sUsername = loginUser.getUsername(); | ||||
| String gitLinkUsername = loginUser.getSysUser().getGitLinkUsername(); | String gitLinkUsername = loginUser.getSysUser().getGitLinkUsername(); | ||||
| @@ -82,18 +85,18 @@ public class NewDatasetServiceImpl implements NewDatasetService { | |||||
| gitProjectVo.setPrivate(!datasetVo.getIsPublic()); | gitProjectVo.setPrivate(!datasetVo.getIsPublic()); | ||||
| gitProjectVo.setUserId(userId); | gitProjectVo.setUserId(userId); | ||||
| // 创建项目 | // 创建项目 | ||||
| Map project = gitService.createProject(gitProjectVo); | |||||
| Map project = gitService.createProject(token,gitProjectVo); | |||||
| Integer gitlinIid = (Integer) project.get("id"); | Integer gitlinIid = (Integer) project.get("id"); | ||||
| if (gitlinIid == null){ | if (gitlinIid == null){ | ||||
| throw new Exception("创建数据集失败:"+project.get("message")); | throw new Exception("创建数据集失败:"+project.get("message")); | ||||
| } | } | ||||
| // 创建分支 | // 创建分支 | ||||
| String branchName = datasetVo.getVersion(); | String branchName = datasetVo.getVersion(); | ||||
| gitService.createBranch((String) userInfo.get("login"), repositoryName, branchName, "master"); | |||||
| gitService.createBranch(token,(String) userInfo.get("login"), repositoryName, branchName, "master"); | |||||
| // 定义标签 标签1:ci4s_dataset 标签2:DataTag 标签3:DataType | // 定义标签 标签1:ci4s_dataset 标签2:DataTag 标签3:DataType | ||||
| gitService.createTopic(gitlinIid, "ci4s_dataset"); | |||||
| gitService.createTopic(gitlinIid, "DataTag_" + datasetVo.getDataTag()); | |||||
| gitService.createTopic( gitlinIid, "DataType_" + datasetVo.getDataType()); | |||||
| gitService.createTopic(token,gitlinIid, "ci4s_dataset"); | |||||
| gitService.createTopic(token,gitlinIid, "DataTag_" + datasetVo.getDataTag()); | |||||
| gitService.createTopic(token, gitlinIid, "DataType_" + datasetVo.getDataType()); | |||||
| // 得到项目地址 | // 得到项目地址 | ||||
| String projectUrl = gitendpoint + "/" + (String) userInfo.get("login") + "/"+ repositoryName + ".git"; | String projectUrl = gitendpoint + "/" + (String) userInfo.get("login") + "/"+ repositoryName + ".git"; | ||||
| @@ -145,10 +148,10 @@ public class NewDatasetServiceImpl implements NewDatasetService { | |||||
| } | } | ||||
| public String newCreateVersion(NewDatasetVo datasetVo) throws Exception { | public String newCreateVersion(NewDatasetVo datasetVo) throws Exception { | ||||
| Jedis jedis = new Jedis(redisHost); | |||||
| String token = gitService.checkoutToken(); | |||||
| Jedis jedis = new Jedis(redisHost,redisPort); | |||||
| LoginUser loginUser = SecurityUtils.getLoginUser(); | LoginUser loginUser = SecurityUtils.getLoginUser(); | ||||
| String ci4sUsername = loginUser.getUsername(); | String ci4sUsername = loginUser.getUsername(); | ||||
| String token = jedis.get(ci4sUsername + "_gitToken"); | |||||
| String gitLinkUsername = loginUser.getSysUser().getGitLinkUsername(); | String gitLinkUsername = loginUser.getSysUser().getGitLinkUsername(); | ||||
| String gitLinkPassword = loginUser.getSysUser().getGitLinkPassword(); | String gitLinkPassword = loginUser.getSysUser().getGitLinkPassword(); | ||||
| String userReq = jedis.get(ci4sUsername + "_gitUserInfo"); | String userReq = jedis.get(ci4sUsername + "_gitUserInfo"); | ||||
| @@ -215,10 +218,10 @@ public class NewDatasetServiceImpl implements NewDatasetService { | |||||
| @Override | @Override | ||||
| public Page<NewDatasetVo> newPersonalQueryByPage(Dataset dataset, PageRequest pageRequest) throws Exception { | public Page<NewDatasetVo> newPersonalQueryByPage(Dataset dataset, PageRequest pageRequest) throws Exception { | ||||
| Jedis jedis = new Jedis(redisHost); | |||||
| String token = gitService.checkoutToken(); | |||||
| Jedis jedis = new Jedis(redisHost,redisPort); | |||||
| LoginUser loginUser = SecurityUtils.getLoginUser(); | LoginUser loginUser = SecurityUtils.getLoginUser(); | ||||
| String ci4sUsername = loginUser.getUsername(); | String ci4sUsername = loginUser.getUsername(); | ||||
| String token = jedis.get(ci4sUsername + "_gitToken"); | |||||
| String userReq = jedis.get(ci4sUsername + "_gitUserInfo"); | String userReq = jedis.get(ci4sUsername + "_gitUserInfo"); | ||||
| Map<String, Object> userInfo = JsonUtils.jsonToMap(userReq); | Map<String, Object> userInfo = JsonUtils.jsonToMap(userReq); | ||||
| // 拼接查询url | // 拼接查询url | ||||
| @@ -242,10 +245,10 @@ public class NewDatasetServiceImpl implements NewDatasetService { | |||||
| @Override | @Override | ||||
| public Page<NewDatasetVo> newPubilcQueryByPage(Dataset dataset, PageRequest pageRequest) throws Exception { | public Page<NewDatasetVo> newPubilcQueryByPage(Dataset dataset, PageRequest pageRequest) throws Exception { | ||||
| Jedis jedis = new Jedis(redisHost); | |||||
| String token = gitService.checkoutToken(); | |||||
| Jedis jedis = new Jedis(redisHost,redisPort); | |||||
| LoginUser loginUser = SecurityUtils.getLoginUser(); | LoginUser loginUser = SecurityUtils.getLoginUser(); | ||||
| String ci4sUsername = loginUser.getUsername(); | String ci4sUsername = loginUser.getUsername(); | ||||
| String token = jedis.get(ci4sUsername + "_gitToken"); | |||||
| String userReq = jedis.get(ci4sUsername + "_gitUserInfo"); | String userReq = jedis.get(ci4sUsername + "_gitUserInfo"); | ||||
| Map<String, Object> userInfo = JsonUtils.jsonToMap(userReq); | Map<String, Object> userInfo = JsonUtils.jsonToMap(userReq); | ||||
| Integer userId = (Integer) userInfo.get("user_id"); | Integer userId = (Integer) userInfo.get("user_id"); | ||||
| @@ -305,7 +308,8 @@ public class NewDatasetServiceImpl implements NewDatasetService { | |||||
| @Override | @Override | ||||
| public List<Map<String, Object>> getVersionList(String repo, String owner) throws Exception { | public List<Map<String, Object>> getVersionList(String repo, String owner) throws Exception { | ||||
| List<Map<String, Object>> brancheList = gitService.getBrancheList(owner, repo); | |||||
| String token = gitService.checkoutToken(); | |||||
| List<Map<String, Object>> brancheList = gitService.getBrancheList(token,owner, repo); | |||||
| return brancheList.stream() | return brancheList.stream() | ||||
| .filter(branch -> !"master".equals(branch.get("name"))) | .filter(branch -> !"master".equals(branch.get("name"))) | ||||
| .collect(Collectors.toList()); | .collect(Collectors.toList()); | ||||
| @@ -313,20 +317,14 @@ public class NewDatasetServiceImpl implements NewDatasetService { | |||||
| @Override | @Override | ||||
| public void deleteDatasetNew(String repo, String owner) throws Exception { | public void deleteDatasetNew(String repo, String owner) throws Exception { | ||||
| Jedis jedis = new Jedis(redisHost); | |||||
| LoginUser loginUser = SecurityUtils.getLoginUser(); | |||||
| String ci4sUsername = loginUser.getUsername(); | |||||
| String token = jedis.get(ci4sUsername+"_gitToken"); | |||||
| gitService.deleteProject(owner, repo); | |||||
| String token = gitService.checkoutToken(); | |||||
| gitService.deleteProject(token,owner, repo); | |||||
| } | } | ||||
| @Override | @Override | ||||
| public void deleteDatasetVersionNew(String repo, String owner, String version, String relativePath) throws Exception { | public void deleteDatasetVersionNew(String repo, String owner, String version, String relativePath) throws Exception { | ||||
| Jedis jedis = new Jedis(redisHost); | |||||
| LoginUser loginUser = SecurityUtils.getLoginUser(); | |||||
| String ci4sUsername = loginUser.getUsername(); | |||||
| String token = jedis.get(ci4sUsername+"_gitToken"); | |||||
| gitService.deleteBranch(owner, repo, version, localPathlocal + relativePath); | |||||
| String token = gitService.checkoutToken(); | |||||
| gitService.deleteBranch(token,owner, repo, version, localPathlocal + relativePath); | |||||
| } | } | ||||
| @Override | @Override | ||||
| @@ -341,6 +339,7 @@ public class NewDatasetServiceImpl implements NewDatasetService { | |||||
| long sizeInBytes = file.getSize(); | long sizeInBytes = file.getSize(); | ||||
| String formattedSize = FileUtil.formatFileSize(sizeInBytes); | String formattedSize = FileUtil.formatFileSize(sizeInBytes); | ||||
| File targetFile = new File(path, file.getOriginalFilename()); | File targetFile = new File(path, file.getOriginalFilename()); | ||||
| // 确保目录存在 | // 确保目录存在 | ||||
| targetFile.getParentFile().mkdirs(); | targetFile.getParentFile().mkdirs(); | ||||
| // 保存文件到目标路径 | // 保存文件到目标路径 | ||||
| @@ -381,24 +380,11 @@ public class NewDatasetServiceImpl implements NewDatasetService { | |||||
| public ResponseEntity<InputStreamResource> downloadAllDatasetFilesNew(String name,Integer id, String version) throws Exception { | public ResponseEntity<InputStreamResource> downloadAllDatasetFilesNew(String name,Integer id, String version) throws Exception { | ||||
| // 命令行操作 git clone 项目地址 | // 命令行操作 git clone 项目地址 | ||||
| LoginUser loginUser = SecurityUtils.getLoginUser(); | LoginUser loginUser = SecurityUtils.getLoginUser(); | ||||
| String gitLinkUsername = loginUser.getSysUser().getGitLinkUsername(); | |||||
| String gitLinkPassword = loginUser.getSysUser().getGitLinkPassword(); | |||||
| String ci4sUsername = loginUser.getUsername(); | String ci4sUsername = loginUser.getUsername(); | ||||
| Jedis jedis = new Jedis(redisHost); | |||||
| Jedis jedis = new Jedis(redisHost,redisPort); | |||||
| String userReq = jedis.get(ci4sUsername + "_gitUserInfo"); | String userReq = jedis.get(ci4sUsername + "_gitUserInfo"); | ||||
| Map<String, Object> userInfo = JsonUtils.jsonToMap(userReq); | Map<String, Object> userInfo = JsonUtils.jsonToMap(userReq); | ||||
| String localPath = localPathlocal+ loginUser.getUsername()+"/datasets/"+id+"/"+name; | String localPath = localPathlocal+ loginUser.getUsername()+"/datasets/"+id+"/"+name; | ||||
| //不需要,没意义,我查看详情已经是最新的了 | |||||
| // if(folder.exists() && folder.isDirectory()){ | |||||
| // //切换分支 | |||||
| // DVCUtils.gitCheckoutBranch(localPath, version); | |||||
| // //pull | |||||
| // DVCUtils.gitPull(localPath,gitLinkUsername, gitLinkPassword); | |||||
| // //dvc pull | |||||
| // DVCUtils.dvcPull(localPath); | |||||
| // }else { | |||||
| // DVCUtils.gitClone(localPath, projectUrl, version, gitLinkUsername, gitLinkPassword); | |||||
| // } | |||||
| // 打包 data 文件夹 | // 打包 data 文件夹 | ||||
| String dataFolderPath = localPath + "/data"; | String dataFolderPath = localPath + "/data"; | ||||
| @@ -59,13 +59,17 @@ public class TensorBoardServiceImpl implements TensorBoardService { | |||||
| @Override | @Override | ||||
| public String runTensorBoard(FrameLogPathVo frameLogPathVo) throws Exception { | public String runTensorBoard(FrameLogPathVo frameLogPathVo) throws Exception { | ||||
| if (StringUtils.isEmpty(frameLogPathVo.getPath())) { | |||||
| throw new Exception("存储路径为空"); | |||||
| if (StringUtils.isEmpty(frameLogPathVo.getPath())||StringUtils.isEmpty(frameLogPathVo.getPvcName())){ | |||||
| throw new Exception("存储路径或存储为空"); | |||||
| } | } | ||||
| // if (StringUtils.isEmpty(frameLogPathVo.getPath())) { | |||||
| // throw new Exception("存储路径为空"); | |||||
| // } | |||||
| LoginUser loginUser = SecurityUtils.getLoginUser(); | LoginUser loginUser = SecurityUtils.getLoginUser(); | ||||
| String podName = loginUser.getUsername().toLowerCase()+"-"+frameLogPathVo.getPath().split("/")[2]+ "-tensorboard-pod"; | String podName = loginUser.getUsername().toLowerCase()+"-"+frameLogPathVo.getPath().split("/")[2]+ "-tensorboard-pod"; | ||||
| Integer podPort = k8sClientUtil.createPodWithSubPath(podName, StringUtils.isEmpty(frameLogPathVo.getNamespace()) ? "default" : frameLogPathVo.getNamespace(), port, mountPath, frameLogPathVo.getPath(), image); | |||||
| Integer podPort = k8sClientUtil.createPodWithSubPath(podName, StringUtils.isEmpty(frameLogPathVo.getNamespace()) ? "default" : frameLogPathVo.getNamespace(), port, mountPath, frameLogPathVo.getPath(), frameLogPathVo.getPvcName(), image); | |||||
| // Integer podPort = k8sClientUtil.createPodWithSubPath(podName, StringUtils.isEmpty(frameLogPathVo.getNamespace()) ? "default" : frameLogPathVo.getNamespace(), port, mountPath, frameLogPathVo.getPath(), image); | |||||
| redisService.setCacheObject(podName, masterIp + ":" + podPort); | redisService.setCacheObject(podName, masterIp + ":" + podPort); | ||||
| return masterIp + ":" + podPort; | return masterIp + ":" + podPort; | ||||
| } | } | ||||
| @@ -34,8 +34,8 @@ import java.util.*; | |||||
| @Component | @Component | ||||
| public class K8sClientUtil { | public class K8sClientUtil { | ||||
| @Value("${jupyter.hostPath}") | |||||
| private String hostPath; | |||||
| // @Value("${jupyter.hostPath}") | |||||
| // private String hostPath; | |||||
| private String http; | private String http; | ||||
| private String token; | private String token; | ||||
| @@ -314,8 +314,8 @@ public class K8sClientUtil { | |||||
| * @param image 镜像 | * @param image 镜像 | ||||
| * @return 创建成功的pod,的nodePort端口 | * @return 创建成功的pod,的nodePort端口 | ||||
| */ | */ | ||||
| public Integer createPodWithSubPath(String podName, String namespace, Integer port, String mountPath, String subPath, String image) { | |||||
| public Integer createPodWithSubPath(String podName, String namespace, Integer port, String mountPath, String subPath, String pvcName, String image) { | |||||
| // public Integer createPodWithSubPath(String podName, String namespace, Integer port, String mountPath, String subPath, String image) { | |||||
| Map<String, String> selector = new LinkedHashMap<>(); | Map<String, String> selector = new LinkedHashMap<>(); | ||||
| selector.put("k8s-jupyter", podName); | selector.put("k8s-jupyter", podName); | ||||
| @@ -366,8 +366,8 @@ public class K8sClientUtil { | |||||
| .endContainer() | .endContainer() | ||||
| .addNewVolume() | .addNewVolume() | ||||
| .withName("workspace") | .withName("workspace") | ||||
| .withHostPath(new V1HostPathVolumeSource().path(hostPath).type("DirectoryOrCreate")) | |||||
| // .withPersistentVolumeClaim(new V1PersistentVolumeClaimVolumeSource().claimName(pvcName)) | |||||
| // .withHostPath(new V1HostPathVolumeSource().path(hostPath).type("DirectoryOrCreate")) | |||||
| .withPersistentVolumeClaim(new V1PersistentVolumeClaimVolumeSource().claimName(pvcName)) | |||||
| .endVolume() | .endVolume() | ||||
| .withTerminationGracePeriodSeconds(14400L) | .withTerminationGracePeriodSeconds(14400L) | ||||
| .endSpec() | .endSpec() | ||||
| @@ -449,25 +449,25 @@ public class K8sClientUtil { | |||||
| } | } | ||||
| } | } | ||||
| // 配置卷和卷挂载 | |||||
| List<V1VolumeMount> volumeMounts = new ArrayList<>(); | |||||
| volumeMounts.add(new V1VolumeMount().name("workspace").mountPath("/opt/notebooks")); | |||||
| volumeMounts.add(new V1VolumeMount().name("data").mountPath("/opt/dataset").subPath(datasetPath).readOnly(true)); | |||||
| volumeMounts.add(new V1VolumeMount().name("data").mountPath("/opt/model").subPath(modelPath).readOnly(true)); | |||||
| List<V1Volume> volumes = new ArrayList<>(); | |||||
| volumes.add(new V1Volume().name("workspace").hostPath(new V1HostPathVolumeSource().path(hostPath + "/" + podName + "/notebooks").type("DirectoryOrCreate"))); | |||||
| volumes.add(new V1Volume().name("data").hostPath(new V1HostPathVolumeSource().path(hostPath).type("DirectoryOrCreate"))); | |||||
| // 配置卷和卷挂载 | // 配置卷和卷挂载 | ||||
| // List<V1VolumeMount> volumeMounts = new ArrayList<>(); | // List<V1VolumeMount> volumeMounts = new ArrayList<>(); | ||||
| // volumeMounts.add(new V1VolumeMount().name("workspace").mountPath(mountPath)); | |||||
| // volumeMounts.add(new V1VolumeMount().name("minio-pvc").mountPath("/opt/data").subPath(datasetPath).readOnly(true)); | |||||
| // volumeMounts.add(new V1VolumeMount().name("minio-pvc").mountPath("/opt/model").subPath(modelPath).readOnly(true)); | |||||
| // volumeMounts.add(new V1VolumeMount().name("workspace").mountPath("/opt/notebooks")); | |||||
| // volumeMounts.add(new V1VolumeMount().name("data").mountPath("/opt/dataset").subPath(datasetPath).readOnly(true)); | |||||
| // volumeMounts.add(new V1VolumeMount().name("data").mountPath("/opt/model").subPath(modelPath).readOnly(true)); | |||||
| // | // | ||||
| // List<V1Volume> volumes = new ArrayList<>(); | // List<V1Volume> volumes = new ArrayList<>(); | ||||
| // volumes.add(new V1Volume().name("workspace").persistentVolumeClaim(new V1PersistentVolumeClaimVolumeSource().claimName(pvc.getMetadata().getName()))); | |||||
| // volumes.add(new V1Volume().name("minio-pvc").persistentVolumeClaim(new V1PersistentVolumeClaimVolumeSource().claimName(dataPvcName))); | |||||
| // volumes.add(new V1Volume().name("workspace").hostPath(new V1HostPathVolumeSource().path(hostPath + "/" + podName + "/notebooks").type("DirectoryOrCreate"))); | |||||
| // volumes.add(new V1Volume().name("data").hostPath(new V1HostPathVolumeSource().path(hostPath).type("DirectoryOrCreate"))); | |||||
| // 配置卷和卷挂载 | |||||
| List<V1VolumeMount> volumeMounts = new ArrayList<>(); | |||||
| volumeMounts.add(new V1VolumeMount().name("workspace").mountPath(mountPath)); | |||||
| volumeMounts.add(new V1VolumeMount().name("minio-pvc").mountPath("/opt/data").subPath(datasetPath).readOnly(true)); | |||||
| volumeMounts.add(new V1VolumeMount().name("minio-pvc").mountPath("/opt/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("minio-pvc").persistentVolumeClaim(new V1PersistentVolumeClaimVolumeSource().claimName(dataPvcName))); | |||||
| //配置资源 | //配置资源 | ||||
| @@ -10,6 +10,7 @@ public class FrameLogPathVo implements Serializable { | |||||
| String path; | String path; | ||||
| String namespace; | String namespace; | ||||
| String pvcName; | |||||
| public String getPath() { | public String getPath() { | ||||
| return path; | return path; | ||||
| } | } | ||||
| @@ -25,4 +26,12 @@ public class FrameLogPathVo implements Serializable { | |||||
| public void setNamespace(String namespace) { | public void setNamespace(String namespace) { | ||||
| this.namespace = namespace; | this.namespace = namespace; | ||||
| } | } | ||||
| public String getPvcName() { | |||||
| return pvcName; | |||||
| } | |||||
| public void setPvcName(String pvcName) { | |||||
| this.pvcName = pvcName; | |||||
| } | |||||
| } | } | ||||