| @@ -18,7 +18,7 @@ import themes from '@/styles/theme.less'; | |||
| import { elapsedTime, formatDate } from '@/utils/date'; | |||
| import { to } from '@/utils/promise'; | |||
| import { modalConfirm } from '@/utils/ui'; | |||
| import { App, Button, ConfigProvider, Space, Table } from 'antd'; | |||
| import { App, Button, ConfigProvider, Space, Table, Tooltip } from 'antd'; | |||
| import classNames from 'classnames'; | |||
| import { useEffect, useRef, useState } from 'react'; | |||
| import { useNavigate } from 'react-router-dom'; | |||
| @@ -279,14 +279,14 @@ function Experiment() { | |||
| dataIndex: 'name', | |||
| key: 'name', | |||
| render: (text) => <div>{text}</div>, | |||
| width: '20%', | |||
| width: '16%', | |||
| }, | |||
| { | |||
| title: '关联流水线名称', | |||
| dataIndex: 'workflow_name', | |||
| key: 'workflow_name', | |||
| render: (text, record) => <a onClick={(e) => routeToEdit(e, record)}>{text}</a>, | |||
| width: '20%', | |||
| width: '16%', | |||
| }, | |||
| { | |||
| title: '实验描述', | |||
| @@ -443,13 +443,17 @@ function Experiment() { | |||
| <div style={{ width: '50%' }}> | |||
| {elapsedTime(item.create_time, item.finish_time)} | |||
| </div> | |||
| <div style={{ width: '50%' }}>{formatDate(item.create_time)}</div> | |||
| <div style={{ width: '50%' }} className={Styles.startTime}> | |||
| <Tooltip title={formatDate(item.create_time)}> | |||
| <span>{formatDate(item.create_time)}</span> | |||
| </Tooltip> | |||
| </div> | |||
| </div> | |||
| <div className={Styles.statusBox}> | |||
| <img | |||
| style={{ width: '17px', marginRight: '7px' }} | |||
| src={experimentStatusInfo[item.status]?.icon} | |||
| />{' '} | |||
| /> | |||
| <span | |||
| style={{ color: experimentStatusInfo[item.status]?.color }} | |||
| className={Styles.statusIcon} | |||
| @@ -36,17 +36,21 @@ | |||
| } | |||
| .index { | |||
| width: calc((100% + 32px + 33px) / 5); | |||
| width: calc((100% + 32px + 33px) / 6.25); | |||
| } | |||
| .tensorBoard { | |||
| width: calc((100% + 32px + 33px) / 5); | |||
| width: calc((100% + 32px + 33px) / 6.25); | |||
| } | |||
| .description { | |||
| display: flex; | |||
| flex: 1; | |||
| align-items: center; | |||
| .startTime { | |||
| .singleLine(); | |||
| } | |||
| } | |||
| .status { | |||
| @@ -80,6 +84,7 @@ | |||
| .statusBox:hover .statusIcon { | |||
| visibility: visible; | |||
| } | |||
| .experimentBox { | |||
| height: calc(100% - 20px); | |||
| .experimentTable { | |||
| @@ -0,0 +1,90 @@ | |||
| import { getComponentAll } from '@/services/pipeline/index.js'; | |||
| import { PipelineNodeModel } from '@/types'; | |||
| import { to } from '@/utils/promise'; | |||
| import { Collapse, type CollapseProps } from 'antd'; | |||
| import { useEffect, useState } from 'react'; | |||
| import Styles from './index.less'; | |||
| type ModelMenuData = { | |||
| key: string; | |||
| name: string; | |||
| value: PipelineNodeModel[]; | |||
| }; | |||
| type ModelMenuProps = { | |||
| onComponentDragEnd: ( | |||
| data: PipelineNodeModel & { x: number; y: number; label: string; img: string }, | |||
| ) => void; | |||
| }; | |||
| const ModelMenu = ({ onComponentDragEnd }: ModelMenuProps) => { | |||
| const [modelMenusList, setModelMenusList] = useState<ModelMenuData[]>([]); | |||
| const [collapseItems, setCollapseItems] = useState<CollapseProps['items']>([]); | |||
| useEffect(() => { | |||
| getAllComponents(); | |||
| }, []); | |||
| // 获取所有组件 | |||
| const getAllComponents = async () => { | |||
| const [res] = await to(getComponentAll()); | |||
| if (res && res.data) { | |||
| const menus = res.data as ModelMenuData[]; | |||
| setModelMenusList(menus); | |||
| const items = menus.map((item) => { | |||
| return { | |||
| key: item.key, | |||
| label: item.name, | |||
| children: item.value.map((ele) => { | |||
| return ( | |||
| <div | |||
| key={ele.id} | |||
| draggable="true" | |||
| onDragEnd={(e) => { | |||
| dragEnd(e, ele); | |||
| }} | |||
| className={Styles.collapseItem} | |||
| > | |||
| {ele.icon_path && ( | |||
| <img | |||
| style={{ height: '16px', marginRight: '15px' }} | |||
| src={`/assets/images/${ele.icon_path}.png`} | |||
| alt="" | |||
| /> | |||
| )} | |||
| {ele.component_label} | |||
| </div> | |||
| ); | |||
| }), | |||
| }; | |||
| }); | |||
| setCollapseItems(items); | |||
| } | |||
| }; | |||
| const dragEnd = (e: React.DragEvent<HTMLDivElement>, data: PipelineNodeModel) => { | |||
| onComponentDragEnd({ | |||
| ...data, | |||
| x: e.clientX, | |||
| y: e.clientY, | |||
| label: data.component_label, | |||
| img: `/assets/images/${data.icon_path}.png`, | |||
| }); | |||
| }; | |||
| const defaultActiveKey = modelMenusList.map((item) => item.key + ''); | |||
| return ( | |||
| <div className={Styles.collapse}> | |||
| <div className={Styles.modelMenusTitle}>组件库</div> | |||
| {modelMenusList.length > 0 ? ( | |||
| <Collapse | |||
| collapsible="header" | |||
| expandIconPosition="end" | |||
| defaultActiveKey={defaultActiveKey} | |||
| items={collapseItems} | |||
| ></Collapse> | |||
| ) : null} | |||
| </div> | |||
| ); | |||
| }; | |||
| export default ModelMenu; | |||
| @@ -8,8 +8,8 @@ import { useEffect, useRef } from 'react'; | |||
| import { useNavigate, useParams } from 'react-router-dom'; | |||
| import { s8 } from '../../../utils'; | |||
| import GlobalParamsDrawer from '../components/GlobalParamsDrawer'; | |||
| import ModelMenu from '../components/ModelMenu'; | |||
| import styles from './index.less'; | |||
| import ModelMenus from './modelMenus'; | |||
| import Props from './props'; | |||
| import { findAllParentNodes, findFirstDuplicate } from './utils'; | |||
| @@ -97,7 +97,7 @@ const EditPipeline = () => { | |||
| closeParamsDrawer(); | |||
| setTimeout(() => { | |||
| if (val) { | |||
| navgite({ pathname: `/pipeline` }); | |||
| navgite({ pathname: `/pipeline/template` }); | |||
| } | |||
| }, 500); | |||
| }); | |||
| @@ -699,7 +699,7 @@ const EditPipeline = () => { | |||
| }; | |||
| return ( | |||
| <div className={styles['pipeline-container']}> | |||
| <ModelMenus onParDragEnd={onDragEnd}></ModelMenus> | |||
| <ModelMenu onComponentDragEnd={onDragEnd}></ModelMenu> | |||
| <div className={styles['pipeline-container__workflow']}> | |||
| <div className={styles['pipeline-container__workflow__top']}> | |||
| <Button | |||
| @@ -1,67 +0,0 @@ | |||
| import { getComponentAll } from '@/services/pipeline/index.js'; | |||
| import { Collapse } from 'antd'; | |||
| import { useEffect, useState } from 'react'; | |||
| import Styles from './modelMenus.less'; | |||
| const ModelMenus = ({ onParDragEnd }) => { | |||
| const [modelMenusList, setModelMenusList] = useState([]); | |||
| useEffect(() => { | |||
| getComponentAll().then((ret) => { | |||
| console.log(ret); | |||
| if (ret.code === 200) { | |||
| setModelMenusList(ret.data); | |||
| } | |||
| }); | |||
| }, []); | |||
| const dragEnd = (e, data) => { | |||
| console.log(e, data); | |||
| onParDragEnd({ | |||
| ...data, | |||
| x: e.clientX, | |||
| y: e.clientY, | |||
| label: data.component_label, | |||
| img: `/assets/images/${data.icon_path}.png`, | |||
| }); | |||
| }; | |||
| const { Panel } = Collapse; | |||
| return ( | |||
| <div className={Styles.collapse}> | |||
| <div className={Styles.modelMenusTitle}>组件库</div> | |||
| {modelMenusList && modelMenusList.length > 0 ? ( | |||
| <Collapse | |||
| collapsible="header" | |||
| defaultActiveKey={modelMenusList.map((item) => item.key + '')} | |||
| expandIconPosition="end" | |||
| > | |||
| {modelMenusList && modelMenusList.length > 0 | |||
| ? modelMenusList.map((item) => ( | |||
| <Panel header={<div>{item.name}</div>} key={item.key}> | |||
| {item.value && item.value.length > 0 | |||
| ? item.value.map((ele) => ( | |||
| <div | |||
| key={ele.id} | |||
| draggable="true" | |||
| onDragEnd={(e) => { | |||
| dragEnd(e, ele); | |||
| }} | |||
| className={Styles.collapseItem} | |||
| > | |||
| {ele.icon_path && ( | |||
| <img | |||
| style={{ height: '16px', marginRight: '15px' }} | |||
| src={`/assets/images/${ele.icon_path}.png`} | |||
| alt="" | |||
| /> | |||
| )} | |||
| {ele.component_label} | |||
| </div> | |||
| )) | |||
| : ''} | |||
| </Panel> | |||
| )) | |||
| : ''} | |||
| </Collapse> | |||
| ) : null} | |||
| </div> | |||
| ); | |||
| }; | |||
| export default ModelMenus; | |||
| @@ -41,9 +41,11 @@ export type PipelineNodeModel = { | |||
| control_strategy: string; | |||
| in_parameters: string; | |||
| out_parameters: string; | |||
| component_label: string; | |||
| icon_path: string; | |||
| }; | |||
| // 流水线 | |||
| // 流水线节点模型数据 | |||
| export type PipelineNodeModelParameter = { | |||
| label: string; | |||
| value: any; | |||