| @@ -154,4 +154,5 @@ export default defineConfig({ | |||||
| strategy: 'normal', | strategy: 'normal', | ||||
| }, | }, | ||||
| requestRecord: {}, | requestRecord: {}, | ||||
| icons: {}, | |||||
| }); | }); | ||||
| @@ -1,4 +1,11 @@ | |||||
| import { useEffect, useRef, useState } from 'react'; | |||||
| import { useCallback, useEffect, useRef, useState } from 'react'; | |||||
| /** | |||||
| * Generates a state reference with the initial value. | |||||
| * | |||||
| * @param initialValue - The initial value for the state | |||||
| * @return An array containing the state value, state setter function, and a mutable reference object | |||||
| */ | |||||
| export function useStateRef<T>(initialValue: T) { | export function useStateRef<T>(initialValue: T) { | ||||
| const [value, setValue] = useState(initialValue); | const [value, setValue] = useState(initialValue); | ||||
| @@ -10,3 +17,23 @@ export function useStateRef<T>(initialValue: T) { | |||||
| return [value, setValue, ref] as const; | return [value, setValue, ref] as const; | ||||
| } | } | ||||
| /** | |||||
| * Generates a custom hook for managing the visibility state of a modal. | |||||
| * | |||||
| * @param initialValue - The initial visibility state of the modal. | |||||
| * @return An array containing the visibility state and functions to open and close the modal. | |||||
| */ | |||||
| export function useModal(initialValue: boolean) { | |||||
| const [visible, setVisible] = useState(initialValue); | |||||
| const open = useCallback(() => { | |||||
| setVisible(true); | |||||
| }, []); | |||||
| const close = useCallback(() => { | |||||
| setVisible(false); | |||||
| }, []); | |||||
| return [visible, open, close]; | |||||
| } | |||||
| @@ -54,7 +54,7 @@ const Dataset = () => { | |||||
| const [dialogTitle, setDialogTitle] = useState('新建版本'); | const [dialogTitle, setDialogTitle] = useState('新建版本'); | ||||
| const [isModalOpen, setIsModalOpen] = useState(false); | const [isModalOpen, setIsModalOpen] = useState(false); | ||||
| const [datasetDetailObj, setDatasetDetailObj] = useState({}); | const [datasetDetailObj, setDatasetDetailObj] = useState({}); | ||||
| const [version, setVersion] = useState(''); | |||||
| const [version, setVersion] = useState(null); | |||||
| const [versionList, setVersionList] = useState([]); | const [versionList, setVersionList] = useState([]); | ||||
| const locationParams = useParams(); //新版本获取路由参数接口 | const locationParams = useParams(); //新版本获取路由参数接口 | ||||
| const [wordList, setWordList] = useState([]); | const [wordList, setWordList] = useState([]); | ||||
| @@ -109,27 +109,24 @@ const Dataset = () => { | |||||
| onOk: () => { | onOk: () => { | ||||
| deleteDatasetVersion({ dataset_id: locationParams.id, version }).then((ret) => { | deleteDatasetVersion({ dataset_id: locationParams.id, version }).then((ret) => { | ||||
| message.success('删除成功'); | |||||
| setVersion(null); | |||||
| getDatasetVersionList(); | |||||
| getDatasetVersions({ version, dataset_id: locationParams.id }); | getDatasetVersions({ version, dataset_id: locationParams.id }); | ||||
| message.success('删除成功'); | |||||
| }); | }); | ||||
| }, | }, | ||||
| }); | }); | ||||
| }; | }; | ||||
| const onFinish = (values) => { | const onFinish = (values) => { | ||||
| addDatasetVersionDetail(formList).then((ret) => { | addDatasetVersionDetail(formList).then((ret) => { | ||||
| console.log(ret); | |||||
| getDatasetVersionList(); | getDatasetVersionList(); | ||||
| setIsModalOpen(false); | setIsModalOpen(false); | ||||
| message.success('创建成功'); | |||||
| }); | }); | ||||
| }; | }; | ||||
| const getDatasetVersions = (params) => { | const getDatasetVersions = (params) => { | ||||
| getDatasetVersionIdList(params).then((res) => { | getDatasetVersionIdList(params).then((res) => { | ||||
| setWordList( | |||||
| res.data.map((v) => ({ | |||||
| ...v, | |||||
| key: v.id, | |||||
| })), | |||||
| ); | |||||
| setWordList(res.data); | |||||
| }); | }); | ||||
| }; | }; | ||||
| const handleChange = (value) => { | const handleChange = (value) => { | ||||
| @@ -242,6 +239,7 @@ const Dataset = () => { | |||||
| width: 160, | width: 160, | ||||
| }} | }} | ||||
| allowClear | allowClear | ||||
| value={version} | |||||
| onChange={handleChange} | onChange={handleChange} | ||||
| options={versionList} | options={versionList} | ||||
| /> | /> | ||||
| @@ -281,7 +279,7 @@ const Dataset = () => { | |||||
| <div style={{ marginBottom: '10px', fontSize: '14px' }}> | <div style={{ marginBottom: '10px', fontSize: '14px' }}> | ||||
| {wordList.length > 0 ? wordList[0].description : null} | {wordList.length > 0 ? wordList[0].description : null} | ||||
| </div> | </div> | ||||
| <Table columns={columns} dataSource={wordList} pagination={false} /> | |||||
| <Table columns={columns} dataSource={wordList} pagination={false} rowKey="id" /> | |||||
| </div> | </div> | ||||
| </TabPane> | </TabPane> | ||||
| </Tabs> | </Tabs> | ||||
| @@ -1,4 +1,4 @@ | |||||
| import { ExperimentStatus } from '../types'; | |||||
| import { ExperimentStatus } from '../status'; | |||||
| import LogGroup, { type LogGroupProps } from './logGroup'; | import LogGroup, { type LogGroupProps } from './logGroup'; | ||||
| type LogListProps = { | type LogListProps = { | ||||
| @@ -3,7 +3,7 @@ import { getExperimentPodsLog } from '@/services/experiment/index.js'; | |||||
| import { DoubleRightOutlined, DownOutlined, UpOutlined } from '@ant-design/icons'; | import { DoubleRightOutlined, DownOutlined, UpOutlined } from '@ant-design/icons'; | ||||
| import { Button } from 'antd'; | import { Button } from 'antd'; | ||||
| import { useEffect, useState } from 'react'; | import { useEffect, useState } from 'react'; | ||||
| import { ExperimentStatus } from '../types'; | |||||
| import { ExperimentStatus } from '../status'; | |||||
| import styles from './logGroup.less'; | import styles from './logGroup.less'; | ||||
| export type LogGroupProps = { | export type LogGroupProps = { | ||||
| @@ -4,6 +4,17 @@ export interface StatusInfo { | |||||
| icon: string; | icon: string; | ||||
| } | } | ||||
| export enum ExperimentStatus { | |||||
| Running = 'Running', | |||||
| Succeeded = 'Succeeded', | |||||
| Pending = 'Pending', | |||||
| Failed = 'Failed', | |||||
| Error = 'Error', | |||||
| Terminated = 'Terminated', | |||||
| Skipped = 'Skipped', | |||||
| Omitted = 'Omitted', | |||||
| } | |||||
| export const experimentStatusInfo: Record<string, StatusInfo | undefined> = { | export const experimentStatusInfo: Record<string, StatusInfo | undefined> = { | ||||
| Running: { | Running: { | ||||
| label: '运行中', | label: '运行中', | ||||
| @@ -1,10 +0,0 @@ | |||||
| export enum ExperimentStatus { | |||||
| Running = 'Running', | |||||
| Succeeded = 'Succeeded', | |||||
| Pending = 'Pending', | |||||
| Failed = 'Failed', | |||||
| Error = 'Error', | |||||
| Terminated = 'Terminated', | |||||
| Skipped = 'Skipped', | |||||
| Omitted = 'Omitted', | |||||
| } | |||||
| @@ -54,7 +54,7 @@ const Dataset = () => { | |||||
| const [dialogTitle, setDialogTitle] = useState('新建版本'); | const [dialogTitle, setDialogTitle] = useState('新建版本'); | ||||
| const [isModalOpen, setIsModalOpen] = useState(false); | const [isModalOpen, setIsModalOpen] = useState(false); | ||||
| const [datasetDetailObj, setDatasetDetailObj] = useState({}); | const [datasetDetailObj, setDatasetDetailObj] = useState({}); | ||||
| const [version, setVersion] = useState(''); | |||||
| const [version, setVersion] = useState(null); | |||||
| const [versionList, setVersionList] = useState([]); | const [versionList, setVersionList] = useState([]); | ||||
| const locationParams = useParams(); //新版本获取路由参数接口 | const locationParams = useParams(); //新版本获取路由参数接口 | ||||
| console.log(locationParams); | console.log(locationParams); | ||||
| @@ -104,17 +104,19 @@ const Dataset = () => { | |||||
| onOk: () => { | onOk: () => { | ||||
| deleteModelVersion({ models_id: locationParams.id, version }).then((ret) => { | deleteModelVersion({ models_id: locationParams.id, version }).then((ret) => { | ||||
| message.success('删除成功'); | |||||
| setVersion(null); | |||||
| getModelVersionsList(); | |||||
| getModelVersions({ version, models_id: locationParams.id }); | getModelVersions({ version, models_id: locationParams.id }); | ||||
| message.success('删除成功'); | |||||
| }); | }); | ||||
| }, | }, | ||||
| }); | }); | ||||
| }; | }; | ||||
| const onFinish = () => { | const onFinish = () => { | ||||
| addModelsVersionDetail(formList).then((ret) => { | addModelsVersionDetail(formList).then((ret) => { | ||||
| console.log(ret); | |||||
| getModelVersionsList(); | getModelVersionsList(); | ||||
| setIsModalOpen(false); | setIsModalOpen(false); | ||||
| message.success('创建成功'); | |||||
| }); | }); | ||||
| }; | }; | ||||
| const getModelVersions = (params) => { | const getModelVersions = (params) => { | ||||
| @@ -140,7 +142,7 @@ const Dataset = () => { | |||||
| getModelVersions({ version: value, models_id: locationParams.id }); | getModelVersions({ version: value, models_id: locationParams.id }); | ||||
| setVersion(value); | setVersion(value); | ||||
| } else { | } else { | ||||
| setVersion(null); | |||||
| setVersion(''); | |||||
| } | } | ||||
| }; | }; | ||||
| const onFinishFailed = (errorInfo) => { | const onFinishFailed = (errorInfo) => { | ||||
| @@ -237,6 +239,7 @@ const Dataset = () => { | |||||
| style={{ | style={{ | ||||
| width: 160, | width: 160, | ||||
| }} | }} | ||||
| value={version} | |||||
| allowClear | allowClear | ||||
| onChange={handleChange} | onChange={handleChange} | ||||
| options={versionList} | options={versionList} | ||||
| @@ -277,7 +280,7 @@ const Dataset = () => { | |||||
| <div style={{ marginBottom: '10px', fontSize: '14px' }}> | <div style={{ marginBottom: '10px', fontSize: '14px' }}> | ||||
| {wordList.length > 0 ? wordList[0].description : null} | {wordList.length > 0 ? wordList[0].description : null} | ||||
| </div> | </div> | ||||
| <Table columns={columns} dataSource={wordList} pagination={false} /> | |||||
| <Table columns={columns} dataSource={wordList} pagination={false} rowKey="id" /> | |||||
| </div> | </div> | ||||
| </TabPane> | </TabPane> | ||||
| </Tabs> | </Tabs> | ||||
| @@ -0,0 +1,14 @@ | |||||
| .form_item_block { | |||||
| position: relative; | |||||
| padding-top: 40px; | |||||
| border-bottom: 1px dashed rgba(20, 49, 179, 0.12); | |||||
| } | |||||
| .delete_button { | |||||
| position: absolute; | |||||
| top: 5px; | |||||
| right: 0; | |||||
| } | |||||
| .add_button { | |||||
| margin-top: 15px; | |||||
| padding: 0; | |||||
| } | |||||
| @@ -0,0 +1,133 @@ | |||||
| import { type PipelineGlobalParam } from '@/types'; | |||||
| import { to } from '@/utils/promise'; | |||||
| import { DeleteOutlined, PlusOutlined } from '@ant-design/icons'; | |||||
| import { Button, Drawer, Form, Input, Radio } from 'antd'; | |||||
| import { forwardRef, useImperativeHandle } from 'react'; | |||||
| import styles from './globalParamsDrawer.less'; | |||||
| type GlobalParamsDrawerProps = { | |||||
| open: boolean; | |||||
| onClose: () => void; | |||||
| globalParam: PipelineGlobalParam[]; | |||||
| }; | |||||
| const GlobalParamsDrawer = forwardRef( | |||||
| ({ open = false, onClose, globalParam = [] }: GlobalParamsDrawerProps, ref) => { | |||||
| const [form] = Form.useForm(); | |||||
| useImperativeHandle(ref, () => ({ | |||||
| getFieldsValue: async () => { | |||||
| const [res, error] = await to(form.validateFields()); | |||||
| if (res && !error) { | |||||
| const values = form.getFieldsValue(); | |||||
| return values; | |||||
| } else { | |||||
| return Promise.reject(error); | |||||
| } | |||||
| }, | |||||
| })); | |||||
| return ( | |||||
| <Drawer | |||||
| rootStyle={{ marginTop: '45px' }} | |||||
| title="全局参数" | |||||
| placement="right" | |||||
| closeIcon={false} | |||||
| getContainer={false} | |||||
| onClose={onClose} | |||||
| open={open} | |||||
| width={420} | |||||
| > | |||||
| <Form | |||||
| name="global_params_form" | |||||
| autoComplete="off" | |||||
| form={form} | |||||
| labelCol={{ span: 7 }} | |||||
| wrapperCol={{ span: 17 }} | |||||
| initialValues={{ global_param: globalParam }} | |||||
| labelAlign="left" | |||||
| > | |||||
| <Form.List name="global_param"> | |||||
| {(fields, { add, remove }) => ( | |||||
| <> | |||||
| {fields.map(({ key, name, ...restField }) => ( | |||||
| <div key={key} className={styles.form_item_block}> | |||||
| <Form.Item | |||||
| {...restField} | |||||
| name={[name, 'param_name']} | |||||
| label="参数名称" | |||||
| rules={[{ required: true, message: '请输入参数名称' }]} | |||||
| > | |||||
| <Input placeholder="请输入参数名称" allowClear /> | |||||
| </Form.Item> | |||||
| <Form.Item | |||||
| {...restField} | |||||
| name={[name, 'description']} | |||||
| label="参数描述" | |||||
| rules={[{ required: true, message: '请输入参数描述' }]} | |||||
| > | |||||
| <Input.TextArea | |||||
| placeholder="请输入参数描述" | |||||
| autoSize={{ minRows: 2, maxRows: 4 }} | |||||
| allowClear | |||||
| /> | |||||
| </Form.Item> | |||||
| <Form.Item | |||||
| {...restField} | |||||
| name={[name, 'param_type']} | |||||
| label="类 型" | |||||
| rules={[{ required: true, message: '请选择类型' }]} | |||||
| > | |||||
| <Radio.Group> | |||||
| <Radio value={1}>字符串</Radio> | |||||
| <Radio value={2}>整型</Radio> | |||||
| <Radio value={3}>布尔类型</Radio> | |||||
| </Radio.Group> | |||||
| </Form.Item> | |||||
| <Form.Item | |||||
| {...restField} | |||||
| name={[name, 'param_value']} | |||||
| label="值" | |||||
| rules={[{ required: true, message: '请输入值' }]} | |||||
| > | |||||
| <Input placeholder="请输入值" allowClear /> | |||||
| </Form.Item> | |||||
| <Form.Item | |||||
| {...restField} | |||||
| name={[name, 'is_sensitive']} | |||||
| label="脱敏显示" | |||||
| rules={[{ required: true, message: '请选择' }]} | |||||
| tooltip="脱敏后的参数以*****显示" | |||||
| > | |||||
| <Radio.Group> | |||||
| <Radio value={1}>是</Radio> | |||||
| <Radio value={0}>否</Radio> | |||||
| </Radio.Group> | |||||
| </Form.Item> | |||||
| <Button | |||||
| className={styles.delete_button} | |||||
| type="link" | |||||
| onClick={() => remove(name)} | |||||
| icon={<DeleteOutlined />} | |||||
| ></Button> | |||||
| </div> | |||||
| ))} | |||||
| <Form.Item> | |||||
| <Button | |||||
| className={styles.add_button} | |||||
| type="link" | |||||
| onClick={add} | |||||
| icon={<PlusOutlined />} | |||||
| > | |||||
| 流水线参数 | |||||
| </Button> | |||||
| </Form.Item> | |||||
| </> | |||||
| )} | |||||
| </Form.List> | |||||
| </Form> | |||||
| </Drawer> | |||||
| ); | |||||
| }, | |||||
| ); | |||||
| export default GlobalParamsDrawer; | |||||
| @@ -1,21 +1,27 @@ | |||||
| import { useModal } from '@/hooks'; | |||||
| import { getWorkflowById, saveWorkflow } from '@/services/pipeline/index.js'; | import { getWorkflowById, saveWorkflow } from '@/services/pipeline/index.js'; | ||||
| import { to } from '@/utils/promise'; | |||||
| import { SaveOutlined } from '@ant-design/icons'; | import { SaveOutlined } from '@ant-design/icons'; | ||||
| import { useEmotionCss } from '@ant-design/use-emotion-css'; | import { useEmotionCss } from '@ant-design/use-emotion-css'; | ||||
| import G6 from '@antv/g6'; | import G6 from '@antv/g6'; | ||||
| import { Button, message } from 'antd'; | import { Button, message } from 'antd'; | ||||
| import React, { useEffect, useRef } from 'react'; | |||||
| import { useEffect, useRef, useState } from 'react'; | |||||
| import { useNavigate, useParams } from 'react-router-dom'; | import { useNavigate, useParams } from 'react-router-dom'; | ||||
| import { Icon } from 'umi'; | |||||
| import { s8 } from '../../../utils'; | import { s8 } from '../../../utils'; | ||||
| import Styles from './editPipeline.less'; | import Styles from './editPipeline.less'; | ||||
| import GlobalParamsDrawer from './globalParamsDrawer'; | |||||
| import ModelMenus from './modelMenus'; | import ModelMenus from './modelMenus'; | ||||
| import Props from './props'; | import Props from './props'; | ||||
| const editPipeline = (React.FC = () => { | |||||
| let graph = null; | |||||
| const EditPipeline = () => { | |||||
| const propsRef = useRef(); | const propsRef = useRef(); | ||||
| const navgite = useNavigate(); | const navgite = useNavigate(); | ||||
| // const [contextMenu,setContextMenu]=useState({}) | // const [contextMenu,setContextMenu]=useState({}) | ||||
| let contextMenu = {}; | let contextMenu = {}; | ||||
| const locationParams = useParams(); //新版本获取路由参数接口 | const locationParams = useParams(); //新版本获取路由参数接口 | ||||
| let graph = null; | |||||
| let sourceAnchorIdx, targetAnchorIdx; | let sourceAnchorIdx, targetAnchorIdx; | ||||
| const pipelineContainer = useEmotionCss(() => { | const pipelineContainer = useEmotionCss(() => { | ||||
| return { | return { | ||||
| @@ -53,6 +59,9 @@ const editPipeline = (React.FC = () => { | |||||
| }; | }; | ||||
| }); | }); | ||||
| const graphRef = useRef(); | const graphRef = useRef(); | ||||
| const paramsDrawerRef = useRef(); | |||||
| const [paramsDrawerVisible, openParamsDrawer, closeParamsDrawer] = useModal(false); | |||||
| const [globalParam, setGlobalParam] = useState([]); | |||||
| const onDragEnd = (val) => { | const onDragEnd = (val) => { | ||||
| console.log(val, 'eee'); | console.log(val, 'eee'); | ||||
| @@ -74,35 +83,37 @@ const editPipeline = (React.FC = () => { | |||||
| console.log(graph); | console.log(graph); | ||||
| }; | }; | ||||
| const formChange = (val) => { | const formChange = (val) => { | ||||
| const data = graph.save(); | |||||
| const index = data.nodes.findIndex((item) => { | |||||
| return item.id === val.id; | |||||
| }); | |||||
| data.nodes[index] = val; | |||||
| graph.changeData(data); | |||||
| graph.render(); | |||||
| if (graph) { | |||||
| const data = graph.save(); | |||||
| const index = data.nodes.findIndex((item) => { | |||||
| return item.id === val.id; | |||||
| }); | |||||
| data.nodes[index] = val; | |||||
| graph.changeData(data); | |||||
| graph.render(); | |||||
| } | |||||
| }; | }; | ||||
| const savePipeline = (val) => { | |||||
| const savePipeline = async (val) => { | |||||
| const [res, error] = await to(paramsDrawerRef.current.getFieldsValue()); | |||||
| if (error) { | |||||
| message.error('全局参数配置有误'); | |||||
| return; | |||||
| } | |||||
| const data = graph.save(); | const data = graph.save(); | ||||
| console.log(data); | console.log(data); | ||||
| let params = { | let params = { | ||||
| ...locationParams, | ...locationParams, | ||||
| dag: JSON.stringify(data), | dag: JSON.stringify(data), | ||||
| global_param: JSON.stringify(res.global_param), | |||||
| }; | }; | ||||
| saveWorkflow(params).then((ret) => { | saveWorkflow(params).then((ret) => { | ||||
| console.log(ret); | |||||
| if (ret.code == 200) { | |||||
| message.success('保存成功'); | |||||
| setTimeout(() => { | |||||
| if (val) { | |||||
| navgite({ pathname: `/pipeline` }); | |||||
| } | |||||
| }, 500); | |||||
| } else { | |||||
| message.error('保存失败'); | |||||
| } | |||||
| message.success('保存成功'); | |||||
| setTimeout(() => { | |||||
| if (val) { | |||||
| navgite({ pathname: `/pipeline` }); | |||||
| } | |||||
| }, 500); | |||||
| }); | }); | ||||
| console.log(params); | |||||
| }; | }; | ||||
| const handlerClick = (e) => { | const handlerClick = (e) => { | ||||
| e.stopPropagation(); | e.stopPropagation(); | ||||
| @@ -258,13 +269,12 @@ const editPipeline = (React.FC = () => { | |||||
| }; | }; | ||||
| const getFirstWorkflow = (val) => { | const getFirstWorkflow = (val) => { | ||||
| getWorkflowById(val).then((ret) => { | getWorkflowById(val).then((ret) => { | ||||
| console.log(ret); | |||||
| if (ret.code == 200) { | |||||
| if (graph && ret.data && ret.data.dag) { | |||||
| getGraphData(JSON.parse(ret.data.dag)); | |||||
| } | |||||
| if (ret && ret.data) { | |||||
| setGlobalParam(ret.data.global_param); | |||||
| } | |||||
| if (graph && ret.data && ret.data.dag) { | |||||
| getGraphData(JSON.parse(ret.data.dag)); | |||||
| } | } | ||||
| // graph&&graph.data(JSON.parse(ret.dag)) | // graph&&graph.data(JSON.parse(ret.dag)) | ||||
| // graph.render() | // graph.render() | ||||
| }); | }); | ||||
| @@ -334,7 +344,6 @@ const editPipeline = (React.FC = () => { | |||||
| }); | }); | ||||
| graph.off('dblclick', handlerClick); | graph.off('dblclick', handlerClick); | ||||
| }; | }; | ||||
| console.log(contextMenu); | |||||
| }, []); | }, []); | ||||
| const initGraph = () => { | const initGraph = () => { | ||||
| const fittingString = (str, maxWidth, fontSize) => { | const fittingString = (str, maxWidth, fontSize) => { | ||||
| @@ -601,8 +610,10 @@ const editPipeline = (React.FC = () => { | |||||
| }); | }); | ||||
| graph.on('dblclick', (e) => { | graph.on('dblclick', (e) => { | ||||
| console.log(e.item); | console.log(e.item); | ||||
| graph.setItemState(e.item, 'nodeClicked', true); | |||||
| handlerClick(e); | |||||
| if (e.item) { | |||||
| graph.setItemState(e.item, 'nodeClicked', true); | |||||
| handlerClick(e); | |||||
| } | |||||
| }); | }); | ||||
| graph.on('click', (e) => { | graph.on('click', (e) => { | ||||
| console.log(e.item); | console.log(e.item); | ||||
| @@ -690,11 +701,18 @@ const editPipeline = (React.FC = () => { | |||||
| <ModelMenus onParDragEnd={onDragEnd}></ModelMenus> | <ModelMenus onParDragEnd={onDragEnd}></ModelMenus> | ||||
| <div className={Styles.centerContainer}> | <div className={Styles.centerContainer}> | ||||
| <div className={Styles.buttonList}> | <div className={Styles.buttonList}> | ||||
| <Button | |||||
| type="default" | |||||
| icon={<Icon icon="local:parameter" style={{ verticalAlign: '-2px' }} />} | |||||
| style={{ marginRight: '20px' }} | |||||
| onClick={openParamsDrawer} | |||||
| > | |||||
| 全局参数 | |||||
| </Button> | |||||
| <Button | <Button | ||||
| type="primary" | type="primary" | ||||
| shape="round" | |||||
| icon={<SaveOutlined />} | icon={<SaveOutlined />} | ||||
| style={{ marginRight: '20px', background: '#1664ff' }} | |||||
| style={{ marginRight: '20px' }} | |||||
| onClick={() => { | onClick={() => { | ||||
| savePipeline(false); | savePipeline(false); | ||||
| }} | }} | ||||
| @@ -703,9 +721,7 @@ const editPipeline = (React.FC = () => { | |||||
| </Button> | </Button> | ||||
| <Button | <Button | ||||
| type="primary" | type="primary" | ||||
| shape="round" | |||||
| icon={<SaveOutlined />} | icon={<SaveOutlined />} | ||||
| style={{ background: '#1664ff' }} | |||||
| onClick={() => { | onClick={() => { | ||||
| savePipeline(true); | savePipeline(true); | ||||
| }} | }} | ||||
| @@ -716,7 +732,13 @@ const editPipeline = (React.FC = () => { | |||||
| <div className={graphStyle} ref={graphRef} id={Styles.graphStyle}></div> | <div className={graphStyle} ref={graphRef} id={Styles.graphStyle}></div> | ||||
| </div> | </div> | ||||
| <Props ref={propsRef} onParentChange={formChange}></Props> | <Props ref={propsRef} onParentChange={formChange}></Props> | ||||
| <GlobalParamsDrawer | |||||
| ref={paramsDrawerRef} | |||||
| open={paramsDrawerVisible} | |||||
| globalParam={globalParam} | |||||
| onClose={closeParamsDrawer} | |||||
| ></GlobalParamsDrawer> | |||||
| </div> | </div> | ||||
| ); | ); | ||||
| }); | |||||
| export default editPipeline; | |||||
| }; | |||||
| export default EditPipeline; | |||||
| @@ -94,7 +94,7 @@ export function deleteModelVersion(params) { | |||||
| } | } | ||||
| // 新增数据集版本 | // 新增数据集版本 | ||||
| export function addDatasetVersionDetail(data) { | export function addDatasetVersionDetail(data) { | ||||
| return request(`/api/mmp//datasetVersion/addDatasetVersions`, { | |||||
| return request(`/api/mmp/datasetVersion/addDatasetVersions`, { | |||||
| method: 'POST', | method: 'POST', | ||||
| headers: { | headers: { | ||||
| 'Content-Type': 'application/json;charset=UTF-8', | 'Content-Type': 'application/json;charset=UTF-8', | ||||
| @@ -53,10 +53,10 @@ export function getQueryByExperimentLog(data) { | |||||
| }); | }); | ||||
| } | } | ||||
| // 查询实例节点结果 | // 查询实例节点结果 | ||||
| export function getNodeResult(params) { | |||||
| export function getNodeResult(data) { | |||||
| return request(`/api/mmp/experimentIns/nodeResult/`, { | return request(`/api/mmp/experimentIns/nodeResult/`, { | ||||
| method: 'GET', | |||||
| params, | |||||
| method: 'POST', | |||||
| data, | |||||
| }); | }); | ||||
| } | } | ||||
| @@ -0,0 +1,9 @@ | |||||
| // 流水线全局参数 | |||||
| export type PipelineGlobalParam = { | |||||
| workflow_id: number; | |||||
| param_name: string; | |||||
| description: string; | |||||
| param_type: number; | |||||
| param_value: number | string | boolean; | |||||
| is_sensitive: number; | |||||
| }; | |||||
| @@ -8,5 +8,5 @@ import java.lang.annotation.Target; | |||||
| @Retention(RetentionPolicy.RUNTIME) | @Retention(RetentionPolicy.RUNTIME) | ||||
| public @interface CheckDuplicate { | public @interface CheckDuplicate { | ||||
| String value() default ""; | String value() default ""; | ||||
| String message() default "不能重复"; | |||||
| String message() default "不能重复!"; | |||||
| } | } | ||||
| @@ -1,15 +1,15 @@ | |||||
| package com.ruoyi.platform.domain; | package com.ruoyi.platform.domain; | ||||
| public enum TensorBoardStatus { | |||||
| Pending("Pending",1), Running("Running",2),Terminated("未运行",3); | |||||
| public enum PodStatus { | |||||
| Pending("Pending",1), Running("Running",2),Terminated("Terminated",3), Failed("Failed",4), Unknown("Unknown",5); | |||||
| private String name; | private String name; | ||||
| private int index; | private int index; | ||||
| private TensorBoardStatus(String name, int index) { | |||||
| private PodStatus(String name, int index) { | |||||
| this.name = name; | this.name = name; | ||||
| this.index = index; | this.index = index; | ||||
| } | } | ||||
| public static String getName(int index) { | public static String getName(int index) { | ||||
| for (TensorBoardStatus c : TensorBoardStatus.values()) { | |||||
| for (PodStatus c : PodStatus.values()) { | |||||
| if (c.getIndex() == index) { | if (c.getIndex() == index) { | ||||
| return c.name; | return c.name; | ||||
| } | } | ||||
| @@ -59,11 +59,9 @@ public class DatasetServiceImpl implements DatasetService { | |||||
| // 固定存储桶名 | // 固定存储桶名 | ||||
| private final String bucketName = "platform-data"; | private final String bucketName = "platform-data"; | ||||
| private final MinioUtil minioUtil; | |||||
| @Resource | |||||
| private MinioUtil minioUtil; | |||||
| public DatasetServiceImpl(MinioUtil minioUtil) { | |||||
| this.minioUtil = minioUtil; | |||||
| } | |||||
| /** | /** | ||||
| @@ -306,6 +304,8 @@ public class DatasetServiceImpl implements DatasetService { | |||||
| .filter(version -> version != null && !version.isEmpty()) //忽略null或空字符串的version | .filter(version -> version != null && !version.isEmpty()) //忽略null或空字符串的version | ||||
| .distinct() // 去重 | .distinct() // 去重 | ||||
| .collect(Collectors.toList()); // 收集到List中 | .collect(Collectors.toList()); // 收集到List中 | ||||
| } | } | ||||
| @@ -58,12 +58,9 @@ public class ModelsServiceImpl implements ModelsService { | |||||
| // 固定存储桶名 | // 固定存储桶名 | ||||
| private final String bucketName = "platform-data"; | private final String bucketName = "platform-data"; | ||||
| @Resource | |||||
| private MinioUtil minioUtil; | |||||
| private final MinioUtil minioUtil; | |||||
| public ModelsServiceImpl(MinioUtil minioUtil) { | |||||
| this.minioUtil = minioUtil; | |||||
| } | |||||
| /** | /** | ||||
| * 通过ID查询单条数据 | * 通过ID查询单条数据 | ||||
| @@ -2,19 +2,15 @@ package com.ruoyi.platform.service.impl; | |||||
| import com.ruoyi.common.core.utils.StringUtils; | import com.ruoyi.common.core.utils.StringUtils; | ||||
| import com.ruoyi.common.security.utils.SecurityUtils; | import com.ruoyi.common.security.utils.SecurityUtils; | ||||
| import com.ruoyi.platform.domain.TensorBoardStatus; | |||||
| import com.ruoyi.platform.domain.PodStatus; | |||||
| import com.ruoyi.platform.service.TensorBoardService; | import com.ruoyi.platform.service.TensorBoardService; | ||||
| import com.ruoyi.platform.utils.K8sClientUtil; | import com.ruoyi.platform.utils.K8sClientUtil; | ||||
| import com.ruoyi.platform.vo.FrameLogPathVo; | import com.ruoyi.platform.vo.FrameLogPathVo; | ||||
| import com.ruoyi.system.api.model.LoginUser; | import com.ruoyi.system.api.model.LoginUser; | ||||
| import io.kubernetes.client.openapi.models.V1Pod; | |||||
| import net.sf.jsqlparser.schema.Database; | |||||
| import org.springframework.beans.factory.annotation.Value; | import org.springframework.beans.factory.annotation.Value; | ||||
| import org.springframework.stereotype.Service; | import org.springframework.stereotype.Service; | ||||
| import javax.annotation.Resource; | import javax.annotation.Resource; | ||||
| import java.text.SimpleDateFormat; | |||||
| import java.util.Date; | |||||
| @Service | @Service | ||||
| public class TensorBoardServiceImpl implements TensorBoardService { | public class TensorBoardServiceImpl implements TensorBoardService { | ||||
| @@ -30,8 +26,8 @@ public class TensorBoardServiceImpl implements TensorBoardService { | |||||
| private K8sClientUtil k8sClientUtil; | private K8sClientUtil k8sClientUtil; | ||||
| @Override | @Override | ||||
| public String getTensorBoardStatus(FrameLogPathVo frameLogPathVo){ | public String getTensorBoardStatus(FrameLogPathVo frameLogPathVo){ | ||||
| String status = TensorBoardStatus.Terminated.getName(); | |||||
| if (StringUtils.isEmpty(frameLogPathVo.getPath())||StringUtils.isEmpty(frameLogPathVo.getPvcName())){ | |||||
| String status = PodStatus.Terminated.getName(); | |||||
| if (StringUtils.isEmpty(frameLogPathVo.getPath())){ | |||||
| return status; | return status; | ||||
| } | } | ||||
| LoginUser loginUser = SecurityUtils.getLoginUser(); | LoginUser loginUser = SecurityUtils.getLoginUser(); | ||||
| @@ -39,9 +35,14 @@ public class TensorBoardServiceImpl implements TensorBoardService { | |||||
| try { | try { | ||||
| String podStatus = k8sClientUtil.getPodStatus(podName, StringUtils.isEmpty(frameLogPathVo.getNamespace()) ? "default" : frameLogPathVo.getNamespace()); | String podStatus = k8sClientUtil.getPodStatus(podName, StringUtils.isEmpty(frameLogPathVo.getNamespace()) ? "default" : frameLogPathVo.getNamespace()); | ||||
| System.out.println(podStatus); | |||||
| for (PodStatus s : PodStatus.values()) { | |||||
| if (s.getName().equals(podStatus)) { | |||||
| status = s.getName(); | |||||
| break; | |||||
| } | |||||
| } | |||||
| } catch (Exception e) { | } catch (Exception e) { | ||||
| return TensorBoardStatus.Terminated.getName(); | |||||
| return PodStatus.Terminated.getName(); | |||||
| } | } | ||||
| return status; | return status; | ||||
| } | } | ||||
| @@ -50,7 +50,7 @@ public class K8sClientUtil { | |||||
| * 3. service-account namespace | * 3. service-account namespace | ||||
| * 4. master endpoints(ip, port) from pre-set environment variables | * 4. master endpoints(ip, port) from pre-set environment variables | ||||
| */ | */ | ||||
| @Autowired | |||||
| // @Autowired | |||||
| public K8sClientUtil(@Value("${k8s.http}") String http, @Value("${k8s.token}") String token) { | public K8sClientUtil(@Value("${k8s.http}") String http, @Value("${k8s.token}") String token) { | ||||
| this.http = http; | this.http = http; | ||||
| this.token = token; | this.token = token; | ||||
| @@ -91,7 +91,7 @@ public class K8sClientUtil { | |||||
| // try { | // try { | ||||
| // this.apiClient = new ClientBuilder(). | // this.apiClient = new ClientBuilder(). | ||||
| // setBasePath("https://172.20.32.181:6443").setVerifyingSsl(false). | // setBasePath("https://172.20.32.181:6443").setVerifyingSsl(false). | ||||
| // setAuthentication(new AccessTokenAuthentication("eyJhbGciOiJSUzI1NiIsImtpZCI6IjRWcFBPWl9YSFFxQ2tVanRuNHdRT1dnUlJNTnB2bG5TQlVSRjNKdExWNDQifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJkZWZhdWx0LXRva2VuLXNteGxuIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImRlZmF1bHQiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiIyZWY1ZjdkMC0zMTdkLTQxN2UtOWY4Ni1mYjA1OTFhYWVhZDQiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZS1zeXN0ZW06ZGVmYXVsdCJ9.GMpReYK7YJ0nNy-F6VrUJQzjWQiSauAOeq0-DT8ik2Lx8f2eznYEm_3cHX4kIn_nYgfxo857urcHt4Ft6IgVtWzxLzVTCQVaNP_H2J8bnJn8W2tUKXzF_3d_GwO75H7kN8P3aoShULrOLpiIf3o3Az28_gwHkwCnd42npcKrCXfAKj8A2U7-KUFQXXA-etrWSw81C5t8ziL-2xaiDgwD3ewH-TNYsOpyWjGopNTxJn1F7GyJ7xDlmMJOaZhSnOrDggB7lqDEsE68YmZtqB7lcSaZHnKzvNhEdbKri4R7_urpjttz_k6qcfIi-l6GwPtJLatsPDg3OL3FFnzjvArJ-A")).build(); | |||||
| // setAuthentication(new AccessTokenAuthentication("eyJhbGciOiJSUzI1NiIsImtpZCI6IjRWcFBPWl9YSFFxQ2tVanRuNHdRT1dnUlJNTnB2bG5TQlVSRjNKdExWNDQifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImFkbWluLXNlcnZpY2UtYWNjb3VudC10b2tlbi14ZDk5eiIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJhZG1pbi1zZXJ2aWNlLWFjY291bnQiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiJmMGEzNmYyMS01MjQyLTQ4MTAtYWVmZS0xOTEwOTZlZjc5YmUiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6ZGVmYXVsdDphZG1pbi1zZXJ2aWNlLWFjY291bnQifQ.fo-Wf0-5-IRC5fhRh65yfqCJqKfE9MrNFIXL2fd1CqVAHD7JBpWO2IsFiSmz9Bm7VfLmFAp2NB7DjW4ZLjC7ODiGhpSseBP8x4ceFuHL6pRGUsEBvHQBBBuQcGhNOcsxIDHnDqUdUzoLprj223lMZNTQowITuqYFU4GVbethyEuS6G5Wh9KHI3KYHFtG4_AeWBgI5Ppz8pDrhHzSFWTFbzxQ3RPGEwF0V-9wEtdrSYnfETi3rdRWif9W4a0RW8HwD9Gf7UCYcyFOs7e5_3-IvmctS85g87PYIfHXMhu_kOw-_Il4bkwPEK5uiBFDw0M1-s9YP-F9r5sXXvOJlsAr1g")).build(); | |||||
| // } catch (Exception e) { | // } catch (Exception e) { | ||||
| // log.error("构建K8s-Client异常", e); | // log.error("构建K8s-Client异常", e); | ||||
| // throw new RuntimeException("构建K8s-Client异常"); | // throw new RuntimeException("构建K8s-Client异常"); | ||||
| @@ -31,6 +31,7 @@ public class MinioUtil { | |||||
| @Value("${minio.secretKey}") | @Value("${minio.secretKey}") | ||||
| private String minioSecretKey; | private String minioSecretKey; | ||||
| private MinioClient minioClient; | private MinioClient minioClient; | ||||
| @PostConstruct | @PostConstruct | ||||
| public void init() { | public void init() { | ||||
| this.minioClient = MinioClient.builder() | this.minioClient = MinioClient.builder() | ||||
| @@ -39,10 +39,10 @@ | |||||
| from models_version | from models_version | ||||
| <where> | <where> | ||||
| state = 1 | state = 1 | ||||
| <if test="modelsId != null"> | |||||
| <if test="modelsVersion.modelsId != null"> | |||||
| and models_id = #{modelsVersion.modelsId} | and models_id = #{modelsVersion.modelsId} | ||||
| </if> | </if> | ||||
| <if test="version != null and version != ''"> | |||||
| <if test="modelsVersion.version != null and modelsVersion.version != ''"> | |||||
| and version = #{modelsVersion.version} | and version = #{modelsVersion.version} | ||||
| </if> | </if> | ||||
| </where> | </where> | ||||