| @@ -77,7 +77,7 @@ export default [ | |||||
| }, | }, | ||||
| { | { | ||||
| name: '流水线详情', | name: '流水线详情', | ||||
| path: ':id/:name', | |||||
| path: ':id', | |||||
| component: './Pipeline/editPipeline/index', | component: './Pipeline/editPipeline/index', | ||||
| }, | }, | ||||
| ], | ], | ||||
| @@ -1,12 +1,12 @@ | |||||
| export default { | export default { | ||||
| 'pages.layouts.userLayout.title': 'Ant Design 是西湖区最具影响力的 Web 设计规范', | 'pages.layouts.userLayout.title': 'Ant Design 是西湖区最具影响力的 Web 设计规范', | ||||
| 'pages.login.accountLogin.tab': '账户密码登录', | 'pages.login.accountLogin.tab': '账户密码登录', | ||||
| 'pages.login.accountLogin.errorMessage': '错误的用户名和密码(admin/admin123)', | |||||
| 'pages.login.accountLogin.errorMessage': '错误的用户名和密码', | |||||
| 'pages.login.failure': '登录失败,请重试!', | 'pages.login.failure': '登录失败,请重试!', | ||||
| 'pages.login.success': '登录成功!', | 'pages.login.success': '登录成功!', | ||||
| 'pages.login.username.placeholder': '用户名: admin', | |||||
| 'pages.login.username.placeholder': '用户名', | |||||
| 'pages.login.username.required': '用户名是必填项!', | 'pages.login.username.required': '用户名是必填项!', | ||||
| 'pages.login.password.placeholder': '密码: admin123', | |||||
| 'pages.login.password.placeholder': '密码', | |||||
| 'pages.login.password.required': '密码是必填项!', | 'pages.login.password.required': '密码是必填项!', | ||||
| 'pages.login.phoneLogin.tab': '手机号登录', | 'pages.login.phoneLogin.tab': '手机号登录', | ||||
| 'pages.login.phoneLogin.errorMessage': '验证码错误', | 'pages.login.phoneLogin.errorMessage': '验证码错误', | ||||
| @@ -1,12 +1,12 @@ | |||||
| export default { | export default { | ||||
| 'pages.layouts.userLayout.title': 'Ant Design 是西湖區最具影響力的 Web 設計規範', | 'pages.layouts.userLayout.title': 'Ant Design 是西湖區最具影響力的 Web 設計規範', | ||||
| 'pages.login.accountLogin.tab': '賬戶密碼登錄', | 'pages.login.accountLogin.tab': '賬戶密碼登錄', | ||||
| 'pages.login.accountLogin.errorMessage': '錯誤的用戶名和密碼(admin/admin123)', | |||||
| 'pages.login.accountLogin.errorMessage': '錯誤的用戶名和密碼', | |||||
| 'pages.login.failure': '登錄失敗,請重試!', | 'pages.login.failure': '登錄失敗,請重試!', | ||||
| 'pages.login.success': '登錄成功!', | 'pages.login.success': '登錄成功!', | ||||
| 'pages.login.username.placeholder': '用戶名: admin', | |||||
| 'pages.login.username.placeholder': '用戶名', | |||||
| 'pages.login.username.required': '用戶名是必填項!', | 'pages.login.username.required': '用戶名是必填項!', | ||||
| 'pages.login.password.placeholder': '密碼: admin123', | |||||
| 'pages.login.password.placeholder': '密碼', | |||||
| 'pages.login.password.required': '密碼是必填項!', | 'pages.login.password.required': '密碼是必填項!', | ||||
| 'pages.login.phoneLogin.tab': '手機號登錄', | 'pages.login.phoneLogin.tab': '手機號登錄', | ||||
| 'pages.login.phoneLogin.errorMessage': '驗證碼錯誤', | 'pages.login.phoneLogin.errorMessage': '驗證碼錯誤', | ||||
| @@ -198,7 +198,7 @@ function Experiment() { | |||||
| }; | }; | ||||
| const routeToEdit = (e, record) => { | const routeToEdit = (e, record) => { | ||||
| e.stopPropagation(); | e.stopPropagation(); | ||||
| navgite({ pathname: `/pipeline/template/${record.workflow_id}/${record.workflow_name}` }); | |||||
| navgite({ pathname: `/pipeline/template/${record.workflow_id}` }); | |||||
| }; | }; | ||||
| // 创建或者编辑实验接口请求 | // 创建或者编辑实验接口请求 | ||||
| const handleAddExperiment = async (values) => { | const handleAddExperiment = async (values) => { | ||||
| @@ -23,24 +23,12 @@ function ExperimentText() { | |||||
| const [paramsModalOpen, openParamsModal, closeParamsModal] = useVisible(false); | const [paramsModalOpen, openParamsModal, closeParamsModal] = useVisible(false); | ||||
| const graphRef = useRef(); | 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 getGraphData = (data) => { | const getGraphData = (data) => { | ||||
| if (graph) { | if (graph) { | ||||
| // 修改历史数据有蓝色边框的问题 | |||||
| data.nodes.forEach((item) => { | |||||
| item.style.stroke = '#fff'; | |||||
| }); | |||||
| graph.data(data); | graph.data(data); | ||||
| graph.render(); | graph.render(); | ||||
| } else { | } else { | ||||
| @@ -92,9 +80,11 @@ function ExperimentText() { | |||||
| getAnchorPoints(cfg) { | getAnchorPoints(cfg) { | ||||
| return ( | return ( | ||||
| cfg.anchorPoints || [ | cfg.anchorPoints || [ | ||||
| // 上下各3,左右各1 | |||||
| // 四个,上下左右 | |||||
| [0.5, 0], | [0.5, 0], | ||||
| [0.5, 1], | [0.5, 1], | ||||
| [0, 0.5], | |||||
| [1, 0.5], | |||||
| ] | ] | ||||
| ); | ); | ||||
| }, | }, | ||||
| @@ -120,6 +110,7 @@ function ExperimentText() { | |||||
| textAlign: 'left', | textAlign: 'left', | ||||
| textBaseline: 'middle', | textBaseline: 'middle', | ||||
| fill: '#000', | fill: '#000', | ||||
| cursor: 'pointer', | |||||
| }, | }, | ||||
| name: 'text-shape', | name: 'text-shape', | ||||
| draggable: true, | draggable: true, | ||||
| @@ -166,8 +157,12 @@ function ExperimentText() { | |||||
| width: graphRef.current.clientWidth || 500, | width: graphRef.current.clientWidth || 500, | ||||
| height: graphRef.current.clientHeight || 760, | height: graphRef.current.clientHeight || 760, | ||||
| animate: false, | animate: false, | ||||
| groupByTypes: false, | |||||
| enabledStack: true, | |||||
| groupByTypes: true, | |||||
| enabledStack: false, | |||||
| fitView: true, | |||||
| minZoom: 0.5, | |||||
| maxZoom: 5, | |||||
| fitViewPadding: 300, | |||||
| modes: { | modes: { | ||||
| default: [ | default: [ | ||||
| // config the shouldBegin for drag-node to avoid node moving while dragging on the anchor-point circles | // config the shouldBegin for drag-node to avoid node moving while dragging on the anchor-point circles | ||||
| @@ -181,15 +176,6 @@ function ExperimentText() { | |||||
| // config the shouldBegin and shouldEnd to make sure the create-edge is began and ended at anchor-point circles | // config the shouldBegin and shouldEnd to make sure the create-edge is began and ended at anchor-point circles | ||||
| 'drag-canvas', | 'drag-canvas', | ||||
| 'zoom-canvas', | 'zoom-canvas', | ||||
| // 'brush-select', | |||||
| 'drag-combo', | |||||
| ], | |||||
| altSelect: [ | |||||
| { | |||||
| type: 'brush-select', | |||||
| trigger: 'drag', | |||||
| }, | |||||
| 'drag-node', | |||||
| ], | ], | ||||
| }, | }, | ||||
| @@ -217,7 +203,7 @@ function ExperimentText() { | |||||
| }, | }, | ||||
| defaultEdge: { | defaultEdge: { | ||||
| // type: 'quadratic', | // type: 'quadratic', | ||||
| type: 'cubic-vertical', | |||||
| // type: 'cubic-vertical', | |||||
| style: { | style: { | ||||
| endArrow: { | endArrow: { | ||||
| @@ -232,15 +218,8 @@ function ExperimentText() { | |||||
| stroke: '#a2a6b5', | stroke: '#a2a6b5', | ||||
| radius: 1, | radius: 1, | ||||
| }, | }, | ||||
| nodeStateStyle: { | |||||
| hover: { | |||||
| opacity: 1, | |||||
| stroke: '#8fe8ff', | |||||
| }, | |||||
| }, | |||||
| labelCfg: { | labelCfg: { | ||||
| autoRotate: true, | autoRotate: true, | ||||
| // refY: 10, | |||||
| style: { | style: { | ||||
| fontSize: 10, | fontSize: 10, | ||||
| fill: '#FFF', | fill: '#FFF', | ||||
| @@ -257,11 +236,6 @@ function ExperimentText() { | |||||
| cursor: 'pointer', | cursor: 'pointer', | ||||
| }, | }, | ||||
| }, | }, | ||||
| // linkCenter: true, | |||||
| fitView: true, | |||||
| minZoom: 0.5, | |||||
| maxZoom: 5, | |||||
| fitViewPadding: 300, | |||||
| }); | }); | ||||
| graph.on('node:click', (e) => { | graph.on('node:click', (e) => { | ||||
| if (e.target.get('name') !== 'anchor-point' && e.item) { | if (e.target.get('name') !== 'anchor-point' && e.item) { | ||||
| @@ -12,7 +12,14 @@ 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'; | ||||
| import { NodeType, getGraphData, nodeHeight, nodeWidth, normalizeTreeData } from './utils'; | |||||
| import { | |||||
| NodeType, | |||||
| getGraphData, | |||||
| nodeFontSize, | |||||
| nodeHeight, | |||||
| nodeWidth, | |||||
| normalizeTreeData, | |||||
| } from './utils'; | |||||
| type modeModelEvolutionProps = { | type modeModelEvolutionProps = { | ||||
| resourceId: number; | resourceId: number; | ||||
| @@ -73,7 +80,7 @@ function ModelEvolution({ | |||||
| width: graphRef.current!.clientWidth, | width: graphRef.current!.clientWidth, | ||||
| height: graphRef.current!.clientHeight, | height: graphRef.current!.clientHeight, | ||||
| fitView: true, | fitView: true, | ||||
| fitViewPadding: [50, 100, 50, 100], | |||||
| fitViewPadding: [100, 100, 100, 100], | |||||
| minZoom: 0.5, | minZoom: 0.5, | ||||
| maxZoom: 5, | maxZoom: 5, | ||||
| defaultNode: { | defaultNode: { | ||||
| @@ -95,7 +102,7 @@ function ModelEvolution({ | |||||
| position: 'center', | position: 'center', | ||||
| style: { | style: { | ||||
| fill: '#ffffff', | fill: '#ffffff', | ||||
| fontSize: 8, | |||||
| fontSize: nodeFontSize, | |||||
| textAlign: 'center', | textAlign: 'center', | ||||
| cursor: 'pointer', | cursor: 'pointer', | ||||
| }, | }, | ||||
| @@ -107,7 +114,7 @@ function ModelEvolution({ | |||||
| autoRotate: true, | autoRotate: true, | ||||
| }, | }, | ||||
| style: { | style: { | ||||
| stroke: '#a2c1ff', | |||||
| stroke: '#DEE0E5', | |||||
| lineWidth: 1, | lineWidth: 1, | ||||
| }, | }, | ||||
| }, | }, | ||||
| @@ -163,28 +170,32 @@ function ModelEvolution({ | |||||
| graph.on('node:click', (e: G6GraphEvent) => { | graph.on('node:click', (e: G6GraphEvent) => { | ||||
| const nodeItem = e.item; | const nodeItem = e.item; | ||||
| const model = nodeItem.getModel(); | |||||
| const model = nodeItem.getModel() as ModelDepsData | ProjectDependency | TrainDataset; | |||||
| const { model_type } = model; | const { model_type } = model; | ||||
| const { origin } = location; | const { origin } = location; | ||||
| let url: string = ''; | let url: string = ''; | ||||
| switch (model_type) { | switch (model_type) { | ||||
| case NodeType.children: | case NodeType.children: | ||||
| case NodeType.parent: { | case NodeType.parent: { | ||||
| const { current_model_id, version } = model as ModelDepsData; | |||||
| const { current_model_id, version } = model; | |||||
| url = `${origin}/dataset/model/${current_model_id}?tab=${ResourceInfoTabKeys.Evolution}&version=${version}`; | url = `${origin}/dataset/model/${current_model_id}?tab=${ResourceInfoTabKeys.Evolution}&version=${version}`; | ||||
| break; | break; | ||||
| } | } | ||||
| case NodeType.project: { | case NodeType.project: { | ||||
| const { url: projectUrl } = model as ProjectDependency; | |||||
| const { url: projectUrl } = model; | |||||
| url = projectUrl; | url = projectUrl; | ||||
| break; | break; | ||||
| } | } | ||||
| case NodeType.trainDataset: | case NodeType.trainDataset: | ||||
| case NodeType.testDataset: { | case NodeType.testDataset: { | ||||
| const { dataset_id, dataset_version } = model as TrainDataset; | |||||
| const { dataset_id, dataset_version } = model; | |||||
| url = `${origin}/dataset/dataset/${dataset_id}?tab=${ResourceInfoTabKeys.Version}&version=${dataset_version}`; | url = `${origin}/dataset/dataset/${dataset_id}?tab=${ResourceInfoTabKeys.Version}&version=${dataset_version}`; | ||||
| break; | break; | ||||
| } | } | ||||
| case NodeType.current: { | |||||
| // TODO: 隐藏数据集和项目 | |||||
| break; | |||||
| } | |||||
| default: | default: | ||||
| break; | break; | ||||
| } | } | ||||
| @@ -6,8 +6,10 @@ import Hierarchy from '@antv/hierarchy'; | |||||
| export const nodeWidth = 110; | export const nodeWidth = 110; | ||||
| export const nodeHeight = 50; | export const nodeHeight = 50; | ||||
| export const vGap = nodeHeight + 20; | export const vGap = nodeHeight + 20; | ||||
| export const hGap = nodeHeight + 20; | |||||
| export const hGap = nodeWidth; | |||||
| export const ellipseWidth = nodeWidth; | export const ellipseWidth = nodeWidth; | ||||
| export const labelPadding = 30; | |||||
| export const nodeFontSize = 8; | |||||
| // 数据集节点 | // 数据集节点 | ||||
| const datasetNodes: NodeConfig[] = []; | const datasetNodes: NodeConfig[] = []; | ||||
| @@ -38,14 +40,14 @@ export interface TrainDataset extends NodeConfig { | |||||
| dataset_id: number; | dataset_id: number; | ||||
| dataset_name: string; | dataset_name: string; | ||||
| dataset_version: string; | dataset_version: string; | ||||
| model_type: NodeType; | |||||
| model_type: NodeType.testDataset | NodeType.trainDataset; | |||||
| } | } | ||||
| export interface ProjectDependency extends NodeConfig { | export interface ProjectDependency extends NodeConfig { | ||||
| url: string; | url: string; | ||||
| name: string; | name: string; | ||||
| branch: string; | branch: string; | ||||
| model_type: NodeType; | |||||
| model_type: NodeType.project; | |||||
| } | } | ||||
| export type ModalDetail = { | export type ModalDetail = { | ||||
| @@ -63,7 +65,7 @@ export interface ModelDepsAPIData { | |||||
| current_model_id: number; | current_model_id: number; | ||||
| version: string; | version: string; | ||||
| exp_ins_id: number; | exp_ins_id: number; | ||||
| model_type: NodeType; | |||||
| model_type: NodeType.children | NodeType.current | NodeType.parent; | |||||
| current_model_name: string; | current_model_name: string; | ||||
| project_dependency: ProjectDependency; | project_dependency: ProjectDependency; | ||||
| test_dataset: TrainDataset[]; | test_dataset: TrainDataset[]; | ||||
| @@ -94,9 +96,13 @@ 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 - 12, 8) + | |||||
| fittingString( | |||||
| `${node.model_version_dependcy_vo.name ?? ''}`, | |||||
| nodeWidth - labelPadding, | |||||
| nodeFontSize, | |||||
| ) + | |||||
| '\n' + | '\n' + | ||||
| fittingString(`${node.version}`, nodeWidth - 12, 8) | |||||
| fittingString(`${node.version}`, nodeWidth - labelPadding, nodeFontSize) | |||||
| ); | ); | ||||
| } | } | ||||
| @@ -231,12 +237,12 @@ const addDatasetDependency = ( | |||||
| node.type = 'ellipse'; | node.type = 'ellipse'; | ||||
| node.size = [ellipseWidth, nodeHeight]; | node.size = [ellipseWidth, nodeHeight]; | ||||
| node.label = | node.label = | ||||
| fittingString(node.dataset_name, ellipseWidth - 12, 8) + | |||||
| fittingString(node.dataset_name, ellipseWidth - labelPadding, nodeFontSize) + | |||||
| '\n' + | '\n' + | ||||
| fittingString(node.dataset_version, ellipseWidth - 12, 8); | |||||
| fittingString(node.dataset_version, ellipseWidth - labelPadding, nodeFontSize); | |||||
| const half = len / 2 - 0.5; | const half = len / 2 - 0.5; | ||||
| node.x = currentNode.x! - (half - index) * (ellipseWidth + hGap / 2); | |||||
| node.x = currentNode.x! - (half - index) * (ellipseWidth + 20); | |||||
| node.y = currentNode.y! - nodeHeight - vGap; | node.y = currentNode.y! - nodeHeight - vGap; | ||||
| nodes.push(node); | nodes.push(node); | ||||
| datasetNodes.push(node); | datasetNodes.push(node); | ||||
| @@ -263,7 +269,7 @@ const addProjectDependency = ( | |||||
| node.id = `$P_${node.url}_${node.branch}`; | node.id = `$P_${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 - 12, 8); | |||||
| node.label = fittingString(node.name, nodeWidth - labelPadding, nodeFontSize); | |||||
| node.style = getStyle(NodeType.project); | node.style = getStyle(NodeType.project); | ||||
| node.style.radius = nodeHeight / 2; | node.style.radius = nodeHeight / 2; | ||||
| node.x = currentNode.x; | node.x = currentNode.x; | ||||
| @@ -311,15 +317,13 @@ function adjustDatasetPosition(node: NodeConfig) { | |||||
| }; | }; | ||||
| const overlapRect = isChildrenOverlapDataset(datasetNodes, nodeRect); | const overlapRect = isChildrenOverlapDataset(datasetNodes, nodeRect); | ||||
| if (overlapRect) { | if (overlapRect) { | ||||
| console.log(node); | |||||
| const adjustRect = { | const adjustRect = { | ||||
| x: overlapRect.x - nodeWidth - hGap / 2, | x: overlapRect.x - nodeWidth - hGap / 2, | ||||
| y: overlapRect.y, | y: overlapRect.y, | ||||
| width: overlapRect.width, | width: overlapRect.width, | ||||
| height: overlapRect.height, | height: overlapRect.height, | ||||
| }; | }; | ||||
| const lastNode = datasetNodes[datasetNodes.length - 1] as NodeConfig; | |||||
| const lastNode = datasetNodes[datasetNodes.length - 1]; | |||||
| const distance = lastNode.x! - adjustRect.x; | const distance = lastNode.x! - adjustRect.x; | ||||
| datasetNodes.forEach((item) => { | datasetNodes.forEach((item) => { | ||||
| item.x = item.x! - distance; | item.x = item.x! - distance; | ||||
| @@ -118,14 +118,18 @@ function ProjectInfo({ data }: { data: ProjectDependency }) { | |||||
| function NodeTooltips({ data, x, y, onMouseEnter, onMouseLeave }: NodeTooltipsProps) { | function NodeTooltips({ data, x, y, onMouseEnter, onMouseLeave }: NodeTooltipsProps) { | ||||
| if (!data) return null; | if (!data) return null; | ||||
| let Component; | |||||
| let Component = null; | |||||
| const { model_type } = data; | const { model_type } = data; | ||||
| if (model_type === NodeType.testDataset || model_type === NodeType.trainDataset) { | if (model_type === NodeType.testDataset || model_type === NodeType.trainDataset) { | ||||
| Component = <DatasetInfo data={data as TrainDataset} />; | |||||
| Component = <DatasetInfo data={data} />; | |||||
| } else if (model_type === NodeType.project) { | } else if (model_type === NodeType.project) { | ||||
| Component = <ProjectInfo data={data as ProjectDependency} />; | |||||
| } else { | |||||
| Component = <ModelInfo data={data as ModelDepsData} />; | |||||
| Component = <ProjectInfo data={data} />; | |||||
| } else if ( | |||||
| model_type === NodeType.children || | |||||
| model_type === NodeType.parent || | |||||
| model_type === NodeType.current | |||||
| ) { | |||||
| Component = <ModelInfo data={data} />; | |||||
| } | } | ||||
| return ( | return ( | ||||
| <div | <div | ||||
| @@ -27,7 +27,8 @@ const EditPipeline = () => { | |||||
| const [paramsDrawerOpen, openParamsDrawer, closeParamsDrawer] = useVisible(false); | const [paramsDrawerOpen, openParamsDrawer, closeParamsDrawer] = useVisible(false); | ||||
| const [globalParam, setGlobalParam, globalParamRef] = useStateRef([]); | const [globalParam, setGlobalParam, globalParamRef] = useStateRef([]); | ||||
| const { message } = App.useApp(); | const { message } = App.useApp(); | ||||
| let sourceAnchorIdx, targetAnchorIdx; | |||||
| let sourceAnchorIdx, targetAnchorIdx, dropAnchorIdx; | |||||
| let dragSourceNode; | |||||
| useEffect(() => { | useEffect(() => { | ||||
| initMenu(); | initMenu(); | ||||
| @@ -35,9 +36,8 @@ const EditPipeline = () => { | |||||
| }, []); | }, []); | ||||
| const onDragEnd = (val) => { | const onDragEnd = (val) => { | ||||
| const _x = val.x; | |||||
| const _y = val.y; | |||||
| const point = graph.getPointByClient(_x, _y); | |||||
| const { x, y } = val; | |||||
| const point = graph.getPointByClient(x, y); | |||||
| // 元模型 | // 元模型 | ||||
| const model = { | const model = { | ||||
| ...val, | ...val, | ||||
| @@ -46,8 +46,8 @@ const EditPipeline = () => { | |||||
| id: val.component_name + '-' + s8(), | id: val.component_name + '-' + s8(), | ||||
| isCluster: false, | isCluster: false, | ||||
| }; | }; | ||||
| console.log('model', model); | |||||
| graph.addItem('node', model, true); | |||||
| // console.log('model', model); | |||||
| graph.addItem('node', model, false); | |||||
| }; | }; | ||||
| const formChange = (val) => { | const formChange = (val) => { | ||||
| if (graph) { | if (graph) { | ||||
| @@ -83,11 +83,11 @@ const EditPipeline = () => { | |||||
| return; | return; | ||||
| } | } | ||||
| const [propsRes, propsError] = await to(propsRef.current.getFieldsValue()); | |||||
| if (propsError) { | |||||
| message.error('基本信息必填项需配置'); | |||||
| return; | |||||
| } | |||||
| // const [propsRes, propsError] = await to(propsRef.current.getFieldsValue()); | |||||
| // if (propsError) { | |||||
| // message.error('基本信息必填项需配置'); | |||||
| // return; | |||||
| // } | |||||
| propsRef.current.propClose(); | propsRef.current.propClose(); | ||||
| setTimeout(() => { | setTimeout(() => { | ||||
| const data = graph.save(); | const data = graph.save(); | ||||
| @@ -110,6 +110,10 @@ const EditPipeline = () => { | |||||
| }; | }; | ||||
| const getGraphData = (data) => { | const getGraphData = (data) => { | ||||
| if (graph) { | if (graph) { | ||||
| // 修改历史数据有蓝色边框的问题 | |||||
| data.nodes.forEach((item) => { | |||||
| item.style.stroke = '#fff'; | |||||
| }); | |||||
| graph.data(data); | graph.data(data); | ||||
| graph.render(); | graph.render(); | ||||
| } else { | } else { | ||||
| @@ -118,7 +122,6 @@ const EditPipeline = () => { | |||||
| }, 500); | }, 500); | ||||
| } | } | ||||
| }; | }; | ||||
| const processParallelEdgesOnAnchorPoint = ( | const processParallelEdgesOnAnchorPoint = ( | ||||
| edges, | edges, | ||||
| offsetDiff = 15, | offsetDiff = 15, | ||||
| @@ -230,6 +233,15 @@ const EditPipeline = () => { | |||||
| } | } | ||||
| return edges; | return edges; | ||||
| }; | }; | ||||
| // 判断两个节点之间是否有边 | |||||
| const hasEdge = (source, target) => { | |||||
| const neighbors = source.getNeighbors(); | |||||
| for (const node of neighbors) { | |||||
| // 新建边的时候,获取的 neighbors 的数据有问题,不全是 INode 类型,可能没有 getID 方法 | |||||
| if (node.getID?.() === target.getID?.()) return true; | |||||
| } | |||||
| return false; | |||||
| }; | |||||
| const cloneElement = (item) => { | const cloneElement = (item) => { | ||||
| console.log(item); | console.log(item); | ||||
| let data = graph.save(); | let data = graph.save(); | ||||
| @@ -254,15 +266,13 @@ const EditPipeline = () => { | |||||
| } | } | ||||
| }); | }); | ||||
| }; | }; | ||||
| const handlerContextMenu = (e) => { | |||||
| e.stopPropagation(); | |||||
| // this.menuType = e.item._cfg.type; | |||||
| }; | |||||
| // 上下文菜单 | // 上下文菜单 | ||||
| const initMenu = () => { | const initMenu = () => { | ||||
| // const selectedNodes = this.selectedNodes; | // const selectedNodes = this.selectedNodes; | ||||
| contextMenu = new G6.Menu({ | contextMenu = new G6.Menu({ | ||||
| getContent(evt) { | getContent(evt) { | ||||
| const type = evt.item.getType(); | |||||
| const cloneDisplay = type === 'node' ? 'block' : 'none'; | |||||
| return ` | return ` | ||||
| <ul style="position: absolute; | <ul style="position: absolute; | ||||
| width: 100px; | width: 100px; | ||||
| @@ -276,8 +286,7 @@ const EditPipeline = () => { | |||||
| font-size: 14px; | font-size: 14px; | ||||
| color: #333333; | color: #333333; | ||||
| overflow-y: auto;"> | overflow-y: auto;"> | ||||
| <li style="padding: 10px 20px;cursor: pointer;" code="clone">复制</li> | |||||
| <li style="padding: 10px 20px;cursor: pointer; display: ${cloneDisplay}" code="clone">复制</li> | |||||
| <li style="padding: 10px 20px;cursor: pointer;" code="delete">删除</li> | <li style="padding: 10px 20px;cursor: pointer;" code="delete">删除</li> | ||||
| </ul>`; | </ul>`; | ||||
| }, | }, | ||||
| @@ -314,11 +323,11 @@ const EditPipeline = () => { | |||||
| getAnchorPoints(cfg) { | getAnchorPoints(cfg) { | ||||
| return ( | return ( | ||||
| cfg.anchorPoints || [ | cfg.anchorPoints || [ | ||||
| // 四个 | |||||
| // 四个,上下左右 | |||||
| [0.5, 0], | [0.5, 0], | ||||
| [0.5, 1], | [0.5, 1], | ||||
| // [0, 0.5], | |||||
| // [1, 0.5], | |||||
| [0, 0.5], | |||||
| [1, 0.5], | |||||
| ] | ] | ||||
| ); | ); | ||||
| }, | }, | ||||
| @@ -344,6 +353,7 @@ const EditPipeline = () => { | |||||
| textAlign: 'left', | textAlign: 'left', | ||||
| textBaseline: 'middle', | textBaseline: 'middle', | ||||
| fill: '#000', | fill: '#000', | ||||
| cursor: 'pointer', | |||||
| }, | }, | ||||
| name: 'text-shape', | name: 'text-shape', | ||||
| draggable: true, | draggable: true, | ||||
| @@ -360,6 +370,7 @@ const EditPipeline = () => { | |||||
| fill: '#fff', | fill: '#fff', | ||||
| stroke: '#a4a4a5', | stroke: '#a4a4a5', | ||||
| cursor: 'crosshair', | cursor: 'crosshair', | ||||
| lineWidth: 1, | |||||
| }, | }, | ||||
| name: `anchor-point`, // the name, for searching by group.find(ele => ele.get('name') === 'anchor-point') | 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 | anchorPointIdx: i, // flag the idx of the anchor-point circle | ||||
| @@ -380,10 +391,9 @@ const EditPipeline = () => { | |||||
| // if (value || point.get('links') > 0) point.show(); | // if (value || point.get('links') > 0) point.show(); | ||||
| // else point.hide(); | // else point.hide(); | ||||
| // }); | // }); | ||||
| const group = item.getContainer(); | const group = item.getContainer(); | ||||
| const shape = group.get('children')[0]; | const shape = group.get('children')[0]; | ||||
| const anchorPoints = group.findAll((ele) => ele.get('name') === 'anchor-point'); | |||||
| const anchorPoints = group.findAll((item) => item.get('name') === 'anchor-point'); | |||||
| if (name === 'hover') { | if (name === 'hover') { | ||||
| if (value) { | if (value) { | ||||
| shape.attr('stroke', themes['primaryColor']); | shape.attr('stroke', themes['primaryColor']); | ||||
| @@ -396,6 +406,18 @@ const EditPipeline = () => { | |||||
| point.hide(); | point.hide(); | ||||
| }); | }); | ||||
| } | } | ||||
| } else if (name === 'drag') { | |||||
| if (sourceAnchorIdx !== null && sourceAnchorIdx !== undefined) { | |||||
| const anchorPoint = anchorPoints[sourceAnchorIdx]; | |||||
| anchorPoint.attr('stroke', value ? themes['primaryColor'] : '#a4a4a5'); | |||||
| anchorPoint.attr('lineWidth', value ? 2 : 1); | |||||
| } | |||||
| } else if (name === 'drop') { | |||||
| if (dropAnchorIdx !== null && dropAnchorIdx !== undefined) { | |||||
| const anchorPoint = anchorPoints[dropAnchorIdx]; | |||||
| anchorPoint.attr('stroke', value ? themes['primaryColor'] : '#a4a4a5'); | |||||
| anchorPoint.attr('lineWidth', value ? 2 : 1); | |||||
| } | |||||
| } | } | ||||
| }, | }, | ||||
| }, | }, | ||||
| @@ -407,10 +429,14 @@ const EditPipeline = () => { | |||||
| width: graphRef.current.clientWidth || 500, | width: graphRef.current.clientWidth || 500, | ||||
| height: graphRef.current.clientHeight || '100%', | height: graphRef.current.clientHeight || '100%', | ||||
| animate: false, | animate: false, | ||||
| groupByTypes: false, | |||||
| groupByTypes: true, | |||||
| fitView: true, | fitView: true, | ||||
| plugins: [contextMenu], | plugins: [contextMenu], | ||||
| enabledStack: true, | |||||
| enabledStack: false, | |||||
| fitView: true, | |||||
| minZoom: 0.5, | |||||
| maxZoom: 5, | |||||
| fitViewPadding: 300, | |||||
| modes: { | modes: { | ||||
| default: [ | default: [ | ||||
| // config the shouldBegin for drag-node to avoid node moving while dragging on the anchor-point circles | // config the shouldBegin for drag-node to avoid node moving while dragging on the anchor-point circles | ||||
| @@ -420,10 +446,6 @@ const EditPipeline = () => { | |||||
| if (e.target.get('name') === 'anchor-point') return false; | if (e.target.get('name') === 'anchor-point') return false; | ||||
| return true; | 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 | // config the shouldBegin and shouldEnd to make sure the create-edge is began and ended at anchor-point circles | ||||
| { | { | ||||
| @@ -434,11 +456,17 @@ const EditPipeline = () => { | |||||
| if (e.target && e.target.get('name') !== 'anchor-point') return false; | if (e.target && e.target.get('name') !== 'anchor-point') return false; | ||||
| sourceAnchorIdx = e.target.get('anchorPointIdx'); | sourceAnchorIdx = e.target.get('anchorPointIdx'); | ||||
| e.target.set('links', e.target.get('links') + 1); // cache the number of edge connected to this anchor-point circle | e.target.set('links', e.target.get('links') + 1); // cache the number of edge connected to this anchor-point circle | ||||
| dragSourceNode = e.item; | |||||
| return true; | return true; | ||||
| }, | }, | ||||
| shouldEnd: (e) => { | shouldEnd: (e) => { | ||||
| // avoid ending at other shapes on the node | // avoid ending at other shapes on the node | ||||
| if (e.target && e.target.get('name') !== 'anchor-point') return false; | if (e.target && e.target.get('name') !== 'anchor-point') return false; | ||||
| if (!dragSourceNode || !e.item) return false; | |||||
| // 不允许连接自己 | |||||
| if (dragSourceNode.getID() === e.item.getID()) return false; | |||||
| // 两个节点不允许多条边 | |||||
| if (hasEdge(dragSourceNode, e.item)) return false; | |||||
| if (e.target) { | if (e.target) { | ||||
| targetAnchorIdx = e.target.get('anchorPointIdx'); | targetAnchorIdx = e.target.get('anchorPointIdx'); | ||||
| e.target.set('links', e.target.get('links') + 1); // cache the number of edge connected to this anchor-point circle | e.target.set('links', e.target.get('links') + 1); // cache the number of edge connected to this anchor-point circle | ||||
| @@ -450,22 +478,11 @@ const EditPipeline = () => { | |||||
| }, | }, | ||||
| 'drag-canvas', | 'drag-canvas', | ||||
| 'zoom-canvas', | 'zoom-canvas', | ||||
| // 'brush-select', | |||||
| 'drag-combo', | |||||
| ], | |||||
| altSelect: [ | |||||
| { | |||||
| type: 'brush-select', | |||||
| trigger: 'drag', | |||||
| }, | |||||
| 'drag-node', | |||||
| ], | ], | ||||
| }, | }, | ||||
| defaultNode: { | defaultNode: { | ||||
| type: 'rect-node', | type: 'rect-node', | ||||
| size: [110, 36], | size: [110, 36], | ||||
| labelCfg: { | labelCfg: { | ||||
| style: { | style: { | ||||
| fill: 'transparent', | fill: 'transparent', | ||||
| @@ -488,8 +505,7 @@ const EditPipeline = () => { | |||||
| }, | }, | ||||
| }, | }, | ||||
| defaultEdge: { | defaultEdge: { | ||||
| //type: 'cubic-vertical', | |||||
| // type: 'cubic-vertical', | |||||
| style: { | style: { | ||||
| endArrow: { | endArrow: { | ||||
| // 设置终点箭头 | // 设置终点箭头 | ||||
| @@ -503,15 +519,8 @@ const EditPipeline = () => { | |||||
| stroke: '#CDD0DC', | stroke: '#CDD0DC', | ||||
| radius: 1, | radius: 1, | ||||
| }, | }, | ||||
| nodeStateStyle: { | |||||
| hover: { | |||||
| opacity: 1, | |||||
| stroke: '#8fe8ff', | |||||
| }, | |||||
| }, | |||||
| labelCfg: { | labelCfg: { | ||||
| autoRotate: true, | autoRotate: true, | ||||
| // refY: 10, | |||||
| style: { | style: { | ||||
| fontSize: 10, | fontSize: 10, | ||||
| fill: '#FFF', | fill: '#FFF', | ||||
| @@ -528,20 +537,16 @@ const EditPipeline = () => { | |||||
| cursor: 'pointer', | cursor: 'pointer', | ||||
| }, | }, | ||||
| }, | }, | ||||
| // linkCenter: true, | |||||
| fitView: true, | |||||
| minZoom: 0.5, | |||||
| maxZoom: 5, | |||||
| fitViewPadding: 300, | |||||
| }); | }); | ||||
| graph.on('node:click', (e) => { | graph.on('node:click', (e) => { | ||||
| e.stopPropagation(); | e.stopPropagation(); | ||||
| if (e.target.get('name') !== 'anchor-point' && e.item) { | if (e.target.get('name') !== 'anchor-point' && e.item) { | ||||
| // graph.setItemState(e.item, 'nodeClicked', true); | |||||
| // 获取所有的上游节点 | |||||
| const parentNodes = findAllParentNodes(graph, e.item); | const parentNodes = findAllParentNodes(graph, e.item); | ||||
| // 如果没有打开过全局参数抽屉,获取不到全局参数 | // 如果没有打开过全局参数抽屉,获取不到全局参数 | ||||
| const globalParams = | const globalParams = | ||||
| paramsDrawerRef.current.getFieldsValue().global_param || globalParamRef.current; | paramsDrawerRef.current.getFieldsValue().global_param || globalParamRef.current; | ||||
| // 打开节点编辑抽屉 | |||||
| propsRef.current.showDrawer(e, globalParams, parentNodes); | propsRef.current.showDrawer(e, globalParams, parentNodes); | ||||
| } | } | ||||
| }); | }); | ||||
| @@ -550,23 +555,26 @@ const EditPipeline = () => { | |||||
| graph.updateItem(e.edge, { | graph.updateItem(e.edge, { | ||||
| sourceAnchor: sourceAnchorIdx, | sourceAnchor: sourceAnchorIdx, | ||||
| targetAnchor: targetAnchorIdx, | targetAnchor: targetAnchorIdx, | ||||
| type: | |||||
| targetAnchorIdx === 0 || targetAnchorIdx === 1 ? 'cubic-vertical' : 'cubic-horizontal', | |||||
| }); | }); | ||||
| // update the curveOffset for parallel edges | // update the curveOffset for parallel edges | ||||
| const edges = graph.save().edges; | |||||
| processParallelEdgesOnAnchorPoint(edges); | |||||
| graph.getEdges().forEach((edge, i) => { | |||||
| graph.updateItem(edge, { | |||||
| curveOffset: edges[i].curveOffset, | |||||
| curvePosition: edges[i].curvePosition, | |||||
| }); | |||||
| }); | |||||
| // const edges = graph.save().edges; | |||||
| // processParallelEdgesOnAnchorPoint(edges); | |||||
| // graph.getEdges().forEach((edge, i) => { | |||||
| // graph.updateItem(edge, { | |||||
| // curveOffset: edges[i].curveOffset, | |||||
| // curvePosition: edges[i].curvePosition, | |||||
| // }); | |||||
| // }); | |||||
| }); | }); | ||||
| // 删除边时,修改 anchor-point 的 links 值 | |||||
| graph.on('afterremoveitem', (e) => { | graph.on('afterremoveitem', (e) => { | ||||
| if (e.item && e.item.source && e.item.target) { | if (e.item && e.item.source && e.item.target) { | ||||
| const sourceNode = graph.findById(e.item.source); | |||||
| const targetNode = graph.findById(e.item.target); | |||||
| const { sourceAnchor, targetAnchor } = e.item; | |||||
| const { source, target, sourceAnchor, targetAnchor } = e.item; | |||||
| const sourceNode = graph.findById(source); | |||||
| const targetNode = graph.findById(target); | |||||
| if (sourceNode && !isNaN(sourceAnchor)) { | if (sourceNode && !isNaN(sourceAnchor)) { | ||||
| const sourceAnchorShape = sourceNode | const sourceAnchorShape = sourceNode | ||||
| .getContainer() | .getContainer() | ||||
| @@ -587,9 +595,10 @@ const EditPipeline = () => { | |||||
| } | } | ||||
| } | } | ||||
| }); | }); | ||||
| // after clicking on the first node, the edge is created, update the sourceAnchor | |||||
| // after drag on the first node, the edge is created, update the sourceAnchor | |||||
| graph.on('afteradditem', (e) => { | graph.on('afteradditem', (e) => { | ||||
| if (e.item && e.item.getType() === 'edge') { | |||||
| const sourceAnchor = e.item.getModel().sourceAnchor; | |||||
| if (e.item && e.item.getType() === 'edge' && !sourceAnchor) { | |||||
| graph.updateItem(e.item, { | graph.updateItem(e.item, { | ||||
| sourceAnchor: sourceAnchorIdx, | sourceAnchor: sourceAnchorIdx, | ||||
| }); | }); | ||||
| @@ -601,17 +610,34 @@ const EditPipeline = () => { | |||||
| graph.on('node:mouseleave', (e) => { | graph.on('node:mouseleave', (e) => { | ||||
| graph.setItemState(e.item, 'hover', false); | graph.setItemState(e.item, 'hover', false); | ||||
| }); | }); | ||||
| graph.on('node:dragenter', (e) => { | |||||
| graph.on('node:dragstart', (e) => { | |||||
| graph.setItemState(e.item, 'hover', true); | graph.setItemState(e.item, 'hover', true); | ||||
| graph.setItemState(e.item, 'drag', true); | |||||
| }); | }); | ||||
| graph.on('node:dragleave', (e) => { | |||||
| graph.on('node:dragend', (e) => { | |||||
| graph.setItemState(e.item, 'hover', false); | graph.setItemState(e.item, 'hover', false); | ||||
| graph.setItemState(e.item, 'drag', false); | |||||
| }); | }); | ||||
| graph.on('node:dragstart', (e) => { | |||||
| graph.on('node:dragenter', (e) => { | |||||
| if (e.item?.getID() === dragSourceNode?.getID()) return; | |||||
| graph.setItemState(e.item, 'hover', true); | graph.setItemState(e.item, 'hover', true); | ||||
| if (e.target.get('name') === 'anchor-point') { | |||||
| dropAnchorIdx = e.target.get('anchorPointIdx'); | |||||
| graph.setItemState(e.item, 'drop', true); | |||||
| } else { | |||||
| graph.setItemState(e.item, 'drop', false); | |||||
| } | |||||
| }); | }); | ||||
| graph.on('node:drag', (e) => { | |||||
| graph.setItemState(e.item, 'hover', true); | |||||
| graph.on('node:dragleave', (e) => { | |||||
| if (e.item?.getID() === dragSourceNode?.getID()) return; | |||||
| graph.setItemState(e.item, 'hover', false); | |||||
| graph.setItemState(e.item, 'drop', false); | |||||
| dropAnchorIdx = undefined; | |||||
| }); | |||||
| graph.on('node:drop', (e) => { | |||||
| graph.setItemState(e.item, 'hover', false); | |||||
| graph.setItemState(e.item, 'drop', false); | |||||
| dropAnchorIdx = undefined; | |||||
| }); | }); | ||||
| window.onresize = () => { | window.onresize = () => { | ||||
| if (!graph || graph.get('destroyed')) return; | if (!graph || graph.get('destroyed')) return; | ||||
| @@ -43,32 +43,30 @@ const Pipeline = () => { | |||||
| }; | }; | ||||
| const routeToEdit = (e, record) => { | const routeToEdit = (e, record) => { | ||||
| e.stopPropagation(); | e.stopPropagation(); | ||||
| navgite({ pathname: `/pipeline/template/${record.id}/${record.name}` }); | |||||
| navgite({ pathname: `/pipeline/template/${record.id}` }); | |||||
| }; | }; | ||||
| const showModal = () => { | const showModal = () => { | ||||
| form.resetFields(); | form.resetFields(); | ||||
| setFormId(null); | |||||
| setDialogTitle('新建流水线'); | setDialogTitle('新建流水线'); | ||||
| setIsModalOpen(true); | setIsModalOpen(true); | ||||
| }; | }; | ||||
| const handleOk = () => { | |||||
| console.log(1111); | |||||
| setIsModalOpen(false); | |||||
| }; | |||||
| const handleCancel = () => { | const handleCancel = () => { | ||||
| setIsModalOpen(false); | setIsModalOpen(false); | ||||
| }; | }; | ||||
| const onFinish = (values) => { | const onFinish = (values) => { | ||||
| if (formId) { | if (formId) { | ||||
| editWorkflow({ ...values, id: formId }).then((ret) => { | editWorkflow({ ...values, id: formId }).then((ret) => { | ||||
| setIsModalOpen(false); | |||||
| message.success('编辑成功'); | message.success('编辑成功'); | ||||
| getList(); | getList(); | ||||
| setIsModalOpen(false); | |||||
| }); | }); | ||||
| } else { | } else { | ||||
| addWorkflow(values).then((ret) => { | addWorkflow(values).then((ret) => { | ||||
| console.log(ret); | |||||
| setIsModalOpen(false); | |||||
| message.success('新建成功'); | |||||
| if (ret.code === 200) { | if (ret.code === 200) { | ||||
| navgite({ pathname: `/pipeline/template/${ret.data.id}/${ret.data.name}` }); | |||||
| navgite({ pathname: `/pipeline/template/${ret.data.id}` }); | |||||
| } | } | ||||
| }); | }); | ||||
| } | } | ||||
| @@ -344,7 +344,7 @@ const Login: React.FC = () => { | |||||
| }} | }} | ||||
| placeholder={intl.formatMessage({ | placeholder={intl.formatMessage({ | ||||
| id: 'pages.login.password.placeholder', | id: 'pages.login.password.placeholder', | ||||
| defaultMessage: '密码: admin123', | |||||
| defaultMessage: '请输入密码', | |||||
| })} | })} | ||||
| rules={[ | rules={[ | ||||
| { | { | ||||
| @@ -374,7 +374,7 @@ const Login: React.FC = () => { | |||||
| required: true, | required: true, | ||||
| message: ( | message: ( | ||||
| <FormattedMessage | <FormattedMessage | ||||
| id="pages.searchTable.updateForm.ruleName.nameRules" | |||||
| id="pages.login.captcha.placeholder" | |||||
| defaultMessage="请输入验证啊" | defaultMessage="请输入验证啊" | ||||
| /> | /> | ||||
| ), | ), | ||||
| @@ -9,12 +9,19 @@ import { clearSessionToken, getAccessToken } from './access'; | |||||
| import { setRemoteMenu } from './services/session'; | import { setRemoteMenu } from './services/session'; | ||||
| import { gotoLoginPage } from './utils/ui'; | import { gotoLoginPage } from './utils/ui'; | ||||
| // [antd: Notification] You are calling notice in render which will break in React 18 concurrent mode. Please trigger in effect instead. | |||||
| const popupError = (error: string) => { | |||||
| // 直接调用 message.error 有时候不弹出来 | |||||
| setTimeout(() => { | |||||
| message.error(error); | |||||
| }, 100); | |||||
| }; | |||||
| /** | /** | ||||
| * Umi Max 网络请求配置 | * Umi Max 网络请求配置 | ||||
| * @doc https://umijs.org/docs/max/request#配置 | * @doc https://umijs.org/docs/max/request#配置 | ||||
| */ | */ | ||||
| export const requestConfig: RequestConfig = { | export const requestConfig: RequestConfig = { | ||||
| errorConfig: {}, | |||||
| requestInterceptors: [ | requestInterceptors: [ | ||||
| (url: string, options: AxiosRequestConfig) => { | (url: string, options: AxiosRequestConfig) => { | ||||
| const headers = options.headers ?? {}; | const headers = options.headers ?? {}; | ||||
| @@ -30,26 +37,32 @@ export const requestConfig: RequestConfig = { | |||||
| }, | }, | ||||
| ], | ], | ||||
| responseInterceptors: [ | responseInterceptors: [ | ||||
| (response: AxiosResponse) => { | |||||
| const { status, data } = response || {}; | |||||
| if (status >= 200 && status < 300) { | |||||
| if (data && (data instanceof Blob || data.code === 200)) { | |||||
| return response; | |||||
| } else if (data && data.code === 401) { | |||||
| clearSessionToken(); | |||||
| setRemoteMenu(null); | |||||
| gotoLoginPage(false); | |||||
| message.error('请重新登录'); | |||||
| return Promise.reject(response); | |||||
| [ | |||||
| (response: AxiosResponse) => { | |||||
| const { status, data } = response || {}; | |||||
| console.log(message, data); | |||||
| if (status >= 200 && status < 300) { | |||||
| if (data && (data instanceof Blob || data.code === 200)) { | |||||
| return response; | |||||
| } else if (data && data.code === 401) { | |||||
| clearSessionToken(); | |||||
| setRemoteMenu(null); | |||||
| gotoLoginPage(false); | |||||
| popupError('请重新登录'); | |||||
| return Promise.reject(response); | |||||
| } else { | |||||
| popupError(data?.msg ?? '请求失败'); | |||||
| return Promise.reject(response); | |||||
| } | |||||
| } else { | } else { | ||||
| console.log(message, data); | |||||
| message.error(data?.msg ?? '请求失败'); | |||||
| popupError('请求失败'); | |||||
| return Promise.reject(response); | return Promise.reject(response); | ||||
| } | } | ||||
| } else { | |||||
| message.error('请求失败'); | |||||
| return Promise.reject(response); | |||||
| } | |||||
| }, | |||||
| }, | |||||
| (error: Error) => { | |||||
| popupError(error.message ?? '请求失败'); | |||||
| return Promise.reject(error); | |||||
| }, | |||||
| ], | |||||
| ], | ], | ||||
| }; | }; | ||||
| @@ -34,7 +34,7 @@ public class ExperimentInstanceStatusTask { | |||||
| private ModelDependencyDao modelDependencyDao; | private ModelDependencyDao modelDependencyDao; | ||||
| private List<Integer> experimentIds = new ArrayList<>(); | private List<Integer> experimentIds = new ArrayList<>(); | ||||
| @Scheduled(cron = "0/30 * * * * ?") // 每30S执行一次 | |||||
| @Scheduled(cron = "0/14 * * * * ?") // 每30S执行一次 | |||||
| public void executeExperimentInsStatus() throws IOException { | public void executeExperimentInsStatus() throws IOException { | ||||
| // 首先查到所有非终止态的实验实例 | // 首先查到所有非终止态的实验实例 | ||||
| List<ExperimentIns> experimentInsList = experimentInsService.queryByExperimentIsNotTerminated(); | List<ExperimentIns> experimentInsList = experimentInsService.queryByExperimentIsNotTerminated(); | ||||
| @@ -49,7 +49,7 @@ public class ExperimentInstanceStatusTask { | |||||
| }catch (Exception e){ | }catch (Exception e){ | ||||
| experimentIns.setStatus("Failed"); | experimentIns.setStatus("Failed"); | ||||
| } | } | ||||
| if (!StringUtils.equals(oldStatus,experimentIns.getStatus())){ | |||||
| // if (!StringUtils.equals(oldStatus,experimentIns.getStatus())){ | |||||
| experimentIns.setUpdateTime(new Date()); | experimentIns.setUpdateTime(new Date()); | ||||
| // 线程安全的添加操作 | // 线程安全的添加操作 | ||||
| synchronized (experimentIds) { | synchronized (experimentIds) { | ||||
| @@ -57,7 +57,7 @@ public class ExperimentInstanceStatusTask { | |||||
| } | } | ||||
| updateList.add(experimentIns); | updateList.add(experimentIns); | ||||
| } | |||||
| // } | |||||
| // experimentInsDao.update(experimentIns); | // experimentInsDao.update(experimentIns); | ||||
| } | } | ||||
| @@ -105,7 +105,7 @@ public class ExperimentInstanceStatusTask { | |||||
| } | } | ||||
| } | } | ||||
| @Scheduled(cron = "0/30 * * * * ?") // / 每30S执行一次 | |||||
| @Scheduled(cron = "0/17 * * * * ?") // / 每30S执行一次 | |||||
| public void executeExperimentStatus() throws IOException { | public void executeExperimentStatus() throws IOException { | ||||
| if (experimentIds.size()==0){ | if (experimentIds.size()==0){ | ||||
| return; | return; | ||||