diff --git a/react-ui/src/assets/img/create-experiment.png b/react-ui/src/assets/img/create-experiment.png new file mode 100644 index 00000000..b086fefa Binary files /dev/null and b/react-ui/src/assets/img/create-experiment.png differ diff --git a/react-ui/src/assets/img/edit-experiment.png b/react-ui/src/assets/img/edit-experiment.png new file mode 100644 index 00000000..d41a8dbf Binary files /dev/null and b/react-ui/src/assets/img/edit-experiment.png differ diff --git a/react-ui/src/assets/img/modal-parameter.png b/react-ui/src/assets/img/modal-parameter.png new file mode 100644 index 00000000..d717b59a Binary files /dev/null and b/react-ui/src/assets/img/modal-parameter.png differ diff --git a/react-ui/src/assets/svg/modal-close.svg b/react-ui/src/assets/svg/modal-close.svg new file mode 100644 index 00000000..1345011e --- /dev/null +++ b/react-ui/src/assets/svg/modal-close.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/react-ui/src/assets/svg/parameter.svg b/react-ui/src/assets/svg/parameter.svg new file mode 100644 index 00000000..58803521 --- /dev/null +++ b/react-ui/src/assets/svg/parameter.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/react-ui/src/assets/svg/view-param.svg b/react-ui/src/assets/svg/view-param.svg new file mode 100644 index 00000000..3eb2efce --- /dev/null +++ b/react-ui/src/assets/svg/view-param.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/react-ui/src/components/KFModal/index.less b/react-ui/src/components/KFModal/index.less new file mode 100644 index 00000000..192ec678 --- /dev/null +++ b/react-ui/src/components/KFModal/index.less @@ -0,0 +1,37 @@ +.kf-modal { + .ant-modal-content { + padding: 20px 67px; + background: linear-gradient(180deg, #cfdfff 0%, #d4e2ff 9.77%, #ffffff 40%, #ffffff 100%); + border-radius: 21px; + } + .ant-modal-header { + margin: 20px 0; + background-color: transparent; + } + .ant-modal-footer { + display: flex; + justify-content: center; + margin: 40px 0 20px 0; + + .ant-btn { + height: 40px; + padding: 0 30px; + font-size: 16px; + border-radius: 10px; + } + .ant-btn-default { + color: #1d1d20; + background: rgba(22, 100, 255, 0.06); + border-color: transparent; + } + .ant-btn + .ant-btn { + margin-left: 20px; + } + } + .ant-modal-close { + top: 27px; + right: 27px; + width: 26px; + height: 26px; + } +} diff --git a/react-ui/src/components/KFModal/index.tsx b/react-ui/src/components/KFModal/index.tsx new file mode 100644 index 00000000..2ce5907b --- /dev/null +++ b/react-ui/src/components/KFModal/index.tsx @@ -0,0 +1,25 @@ +// 自定义 Modal + +import { ReactComponent as CloseIcon } from '@/assets/svg/modal-close.svg'; +import ModalTitle from '@/components/ModalTitle'; +import { Modal, type ModalProps } from 'antd'; +import classNames from 'classnames'; +import './index.less'; + +type KFModalProps = ModalProps & { + image: string; +}; +function KFModal({ title, image, children, className, ...rest }: KFModalProps) { + return ( + } + closeIcon={} + > + {children} + + ); +} + +export default KFModal; diff --git a/react-ui/src/components/ModalTitle/index.less b/react-ui/src/components/ModalTitle/index.less new file mode 100644 index 00000000..b56ecc7d --- /dev/null +++ b/react-ui/src/components/ModalTitle/index.less @@ -0,0 +1,12 @@ +@import '@/styles/theme.less'; +.modal_title { + display: flex; + align-items: center; + color: @kf-primary-color; + font-size: 20px; + + &_image { + width: 22px; + margin-right: 10px; + } +} diff --git a/react-ui/src/components/ModalTitle/index.tsx b/react-ui/src/components/ModalTitle/index.tsx new file mode 100644 index 00000000..34bdda74 --- /dev/null +++ b/react-ui/src/components/ModalTitle/index.tsx @@ -0,0 +1,18 @@ +import React from 'react'; +import styles from './index.less'; + +type ModalTitleProps = { + title: React.ReactNode; + image?: string; +}; + +function ModalTitle({ title, image }: ModalTitleProps) { + return ( +
+ + {title} +
+ ); +} + +export default ModalTitle; diff --git a/react-ui/src/hooks/index.ts b/react-ui/src/hooks/index.ts index 7c5cae63..d60bc345 100644 --- a/react-ui/src/hooks/index.ts +++ b/react-ui/src/hooks/index.ts @@ -24,7 +24,7 @@ export function useStateRef(initialValue: T) { * @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) { +export function useAntdModal(initialValue: boolean) { const [visible, setVisible] = useState(initialValue); const open = useCallback(() => { diff --git a/react-ui/src/overrides.less b/react-ui/src/overrides.less new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/react-ui/src/overrides.less @@ -0,0 +1 @@ + diff --git a/react-ui/src/pages/DatasetPreparation/DatasetAnnotation/index.tsx b/react-ui/src/pages/DatasetPreparation/DatasetAnnotation/index.tsx index e5c03dbc..a1f017e6 100644 --- a/react-ui/src/pages/DatasetPreparation/DatasetAnnotation/index.tsx +++ b/react-ui/src/pages/DatasetPreparation/DatasetAnnotation/index.tsx @@ -1,9 +1,22 @@ +import { getLabelStudioUrl } from '@/services/developmentEnvironment'; +import { to } from '@/utils/promise'; +import { useEffect, useState } from 'react'; import styles from './index.less'; function DatasetAnnotation() { + const [iframeUrl, setIframeUrl] = useState(''); + useEffect(() => { + requestIframeUrl(); + }, []); + const requestIframeUrl = async () => { + const [res] = await to(getLabelStudioUrl()); + if (res && res.data) { + setIframeUrl(res.data); + } + }; return (
- + {iframeUrl && }
); } diff --git a/react-ui/src/pages/Experiment/experimentText/addExperimentModal.less b/react-ui/src/pages/Experiment/experimentText/addExperimentModal.less index a92ff9de..e46ef89f 100644 --- a/react-ui/src/pages/Experiment/experimentText/addExperimentModal.less +++ b/react-ui/src/pages/Experiment/experimentText/addExperimentModal.less @@ -1,17 +1,7 @@ .modal { :global { - .ant-modal-content { - width: 825px; - padding: 20px 67px; - background: linear-gradient(180deg, #cfdfff 0%, #d4e2ff 9.77%, #ffffff 40%, #ffffff 100%); - border-radius: 21px; - } - .ant-modal-header { - margin: 20px 0; - background-color: transparent; - } .ant-input { - height: 40px; + height: 30px; border-color: #e6e6e6; } .ant-select-single { @@ -20,38 +10,11 @@ .ant-form-item .ant-form-item-label > label { color: rgba(29, 29, 32, 0.8); } - .ant-modal-footer { - display: flex; - justify-content: center; - margin: 40px 0 30px 0; - } - .ant-btn { - width: 110px; - height: 40px; - font-size: 18px; - background: rgba(22, 100, 255, 0.06); - border-color: transparent; - border-radius: 10px; - } - .ant-btn-primary { - background: #1664ff; - } - } - - .title { - display: flex; - align-items: center; - font-weight: 500; - - .image { - width: 20px; - margin-right: 10px; - } } .global_param_item { max-height: 230px; - padding: 20px 12px; + padding: 24px 12px 0; overflow-y: auto; border: 1px solid #e6e6e6; border-radius: 6px; diff --git a/react-ui/src/pages/Experiment/experimentText/addExperimentModal.tsx b/react-ui/src/pages/Experiment/experimentText/addExperimentModal.tsx index b236566c..53ebc7ca 100644 --- a/react-ui/src/pages/Experiment/experimentText/addExperimentModal.tsx +++ b/react-ui/src/pages/Experiment/experimentText/addExperimentModal.tsx @@ -1,5 +1,8 @@ +import createExperimentIcon from '@/assets/img/create-experiment.png'; +import editExperimentIcon from '@/assets/img/edit-experiment.png'; +import KFModal from '@/components/KFModal'; import { type PipelineGlobalParam } from '@/types'; -import { Form, Input, Modal, Radio, Select, type FormRule } from 'antd'; +import { Form, Input, Radio, Select, type FormRule } from 'antd'; import { useState } from 'react'; import styles from './addExperimentModal.less'; @@ -76,21 +79,22 @@ function AddExperimentModal({ workflowList = [], initialValues = {}, }: AddExperimentModalProps) { - const dialogTitle = isAdd ? '新建实验' : '编辑实验'; + const modalTitle = isAdd ? '新建实验' : '配置实验'; + const modalIcon = isAdd ? createExperimentIcon : editExperimentIcon; const workflowDisabled = isAdd ? false : true; const [globalParam, setGlobalParam] = useState( initialValues.global_param || [], ); const [form] = Form.useForm(); - const layout = { + const tailLayout = { labelCol: { span: 24 }, wrapperCol: { span: 24 }, }; - const tailLayout = { - labelCol: { span: 8 }, - wrapperCol: { span: 16 }, + const layout = { + labelCol: { span: 4 }, + wrapperCol: { span: 20 }, }; // 除了流水线选择发生变化 @@ -105,14 +109,10 @@ function AddExperimentModal({ } }; return ( - - - {dialogTitle} - - } + title={modalTitle} + image={modalIcon} open={open} okButtonProps={{ htmlType: 'submit', @@ -120,6 +120,7 @@ function AddExperimentModal({ }} onCancel={onCancel} destroyOnClose={true} + width={825} >
{globalParam.length > 0 && ( - +
{(fields) => fields.map(({ key, name, ...restField }) => ( {getParamComponent( @@ -192,7 +198,7 @@ function AddExperimentModal({ )} - + ); } diff --git a/react-ui/src/pages/Experiment/experimentText/index.jsx b/react-ui/src/pages/Experiment/experimentText/index.jsx index 37dbb4b3..15fd0f51 100644 --- a/react-ui/src/pages/Experiment/experimentText/index.jsx +++ b/react-ui/src/pages/Experiment/experimentText/index.jsx @@ -1,14 +1,18 @@ +import { ReactComponent as ViewParam } from '@/assets/svg/view-param.svg'; +import { useAntdModal } from '@/hooks'; import { getExperimentIns } from '@/services/experiment/index.js'; import { getWorkflowById } from '@/services/pipeline/index.js'; import { elapsedTime } from '@/utils/date'; import { useEmotionCss } from '@ant-design/use-emotion-css'; import G6 from '@antv/g6'; +import { Button } from 'antd'; import momnet from 'moment'; import { useEffect, useRef, useState } from 'react'; import { useNavigate, useParams } from 'react-router-dom'; import { s8 } from '../../../utils'; import { experimentStatusInfo } from '../status'; -import Styles from './editPipeline.less'; +import styles from './index.less'; +import ParamsModal from './paramsModal'; import Props from './props'; function ExperimentText() { @@ -18,6 +22,7 @@ function ExperimentText() { const navgite = useNavigate(); const locationParams = useParams(); //新版本获取路由参数接口 let graph = null; + const [paramsModalOpen, openParamsModal, closeParamsModal] = useAntdModal(false); const timers = (time) => { let timer = new Date(time); @@ -91,53 +96,50 @@ function ExperimentText() { }; const getFirstWorkflow = (val) => { getWorkflowById(val).then((ret) => { - console.log(ret, 'retttttttttt'); - if (ret.code == 200) { - if (graph && ret.data && ret.data.dag) { - console.log(JSON.parse(ret.data.dag)); - getExperimentIns(locationParams.id).then((res) => { - if (res.code == 200) { - console.log(ret.data, 'data'); - setMessage(res.data); - const experimentStatusObjs = JSON.parse(res.data.nodes_status); - const newNodeList = JSON.parse(ret.data.dag).nodes.map((item) => { - console.log(experimentStatusObjs); - return { - ...item, - experimentEndTime: - experimentStatusObjs && - experimentStatusObjs[item.id] && - experimentStatusObjs[item.id].finishedAt, - experimentStartTime: - experimentStatusObjs && - experimentStatusObjs[item.id] && - experimentStatusObjs[item.id].startedAt, - experimentStatus: - experimentStatusObjs && - experimentStatusObjs[item.id] && - experimentStatusObjs[item.id].phase, - component_id: - experimentStatusObjs && - experimentStatusObjs[item.id] && - experimentStatusObjs[item.id].id, - img: - experimentStatusObjs && - experimentStatusObjs[item.id] && - experimentStatusObjs[item.id].phase - ? item.img.slice(0, item.img.length - 4) + - '-' + - experimentStatusObjs[item.id].phase + - '.png' - : item.img, - }; - }); - const newData = { ...JSON.parse(ret.data.dag), nodes: newNodeList }; + if (graph && ret.data && ret.data.dag) { + console.log(JSON.parse(ret.data.dag)); + getExperimentIns(locationParams.id).then((res) => { + if (res.code == 200) { + console.log(ret.data, 'data'); + setMessage(res.data); + const experimentStatusObjs = JSON.parse(res.data.nodes_status); + const newNodeList = JSON.parse(ret.data.dag).nodes.map((item) => { + console.log(experimentStatusObjs); + return { + ...item, + experimentEndTime: + experimentStatusObjs && + experimentStatusObjs[item.id] && + experimentStatusObjs[item.id].finishedAt, + experimentStartTime: + experimentStatusObjs && + experimentStatusObjs[item.id] && + experimentStatusObjs[item.id].startedAt, + experimentStatus: + experimentStatusObjs && + experimentStatusObjs[item.id] && + experimentStatusObjs[item.id].phase, + component_id: + experimentStatusObjs && + experimentStatusObjs[item.id] && + experimentStatusObjs[item.id].id, + img: + experimentStatusObjs && + experimentStatusObjs[item.id] && + experimentStatusObjs[item.id].phase + ? item.img.slice(0, item.img.length - 4) + + '-' + + experimentStatusObjs[item.id].phase + + '.png' + : item.img, + }; + }); + const newData = { ...JSON.parse(ret.data.dag), nodes: newNodeList }; - getGraphData(newData); - // setExperimentStatusObj(JSON.parse(ret.data.nodes_status)) - } - }); - } + getGraphData(newData); + // setExperimentStatusObj(JSON.parse(ret.data.nodes_status)) + } + }); } // graph&&graph.data(JSON.parse(ret.dag)) // graph.render() @@ -369,18 +371,18 @@ function ExperimentText() { }; return (
-
-
-
+
+
+
启动时间:{momnet(message.create_time).format('YYYY-MM-DD HH:mm:ss')}
-
+
执行时长: {message.finish_time ? elapsedTime(new Date(message.create_time), new Date(message.finish_time)) : elapsedTime(new Date(message.create_time), new Date())}
-
+
状态:
+
-
+
+
); } diff --git a/react-ui/src/pages/Experiment/experimentText/editPipeline.less b/react-ui/src/pages/Experiment/experimentText/index.less similarity index 93% rename from react-ui/src/pages/Experiment/experimentText/editPipeline.less rename to react-ui/src/pages/Experiment/experimentText/index.less index f9e0e21b..d426b5b9 100644 --- a/react-ui/src/pages/Experiment/experimentText/editPipeline.less +++ b/react-ui/src/pages/Experiment/experimentText/index.less @@ -24,7 +24,7 @@ display: flex; align-items: center; width: 100%; - height: 45px; + height: 56px; padding: 0 30px; background: #ffffff; box-shadow: 0px 3px 6px rgba(146, 146, 146, 0.09); @@ -43,6 +43,10 @@ color: rgba(29, 29, 32, 0.8); font-size: 15px; } +.param_button { + margin-right: 0; + margin-left: auto; +} .resultTop { display: flex; align-items: center; diff --git a/react-ui/src/pages/Experiment/experimentText/paramsModal.less b/react-ui/src/pages/Experiment/experimentText/paramsModal.less new file mode 100644 index 00000000..e8b1e16e --- /dev/null +++ b/react-ui/src/pages/Experiment/experimentText/paramsModal.less @@ -0,0 +1,30 @@ +.params_container { + max-height: 230px; + padding: 15px; + border: 1px solid #e6e6e6; + border-radius: 8px; + + &_line { + display: flex; + align-items: center; + margin-bottom: 15px; + + &_label { + width: 120px; + color: #1d1d20; + font-size: 15px; + } + &_value { + flex: 1; + width: 100px; + margin-left: 15px; + padding: 10px 20px; + color: #1d1d20; + font-size: 15px; + line-height: 20px; + background: #f6f6f6; + border: 1px solid #e0e0e1; + border-radius: 4px; + } + } +} diff --git a/react-ui/src/pages/Experiment/experimentText/paramsModal.tsx b/react-ui/src/pages/Experiment/experimentText/paramsModal.tsx new file mode 100644 index 00000000..1a1cf41f --- /dev/null +++ b/react-ui/src/pages/Experiment/experimentText/paramsModal.tsx @@ -0,0 +1,34 @@ +import parameterImg from '@/assets/img/modal-parameter.png'; +import KFModal from '@/components/KFModal'; +import { type PipelineGlobalParam } from '@/types'; +import styles from './paramsModal.less'; + +type ParamsModalProps = { + open: boolean; + onCancel: () => void; + globalParam?: PipelineGlobalParam[]; +}; + +function ParamsModal({ open, onCancel, globalParam = [] }: ParamsModalProps) { + return ( + +
+ {globalParam.map((item) => ( +
+ {item.param_name} + {item.param_value} +
+ ))} +
+
+ ); +} + +export default ParamsModal; diff --git a/react-ui/src/pages/Experiment/experimentText/props.jsx b/react-ui/src/pages/Experiment/experimentText/props.jsx index 1a6c738b..a8fc72de 100644 --- a/react-ui/src/pages/Experiment/experimentText/props.jsx +++ b/react-ui/src/pages/Experiment/experimentText/props.jsx @@ -6,7 +6,7 @@ import { Drawer, Form, Input, Tabs, message } from 'antd'; import moment from 'moment'; import { forwardRef, useImperativeHandle, useState } from 'react'; import LogList from './LogList'; -import Styles from './editPipeline.less'; +import Styles from './index.less'; const { TextArea } = Input; const Props = forwardRef(({ onParentChange }, ref) => { const [form] = Form.useForm(); diff --git a/react-ui/src/pages/Pipeline/editPipeline/index.jsx b/react-ui/src/pages/Pipeline/editPipeline/index.jsx index 1fae2fd5..094735cf 100644 --- a/react-ui/src/pages/Pipeline/editPipeline/index.jsx +++ b/react-ui/src/pages/Pipeline/editPipeline/index.jsx @@ -1,4 +1,5 @@ -import { useModal } from '@/hooks'; +import { ReactComponent as ParameterIcon } from '@/assets/svg/parameter.svg'; +import { useAntdModal } from '@/hooks'; import { getWorkflowById, saveWorkflow } from '@/services/pipeline/index.js'; import { to } from '@/utils/promise'; import { SaveOutlined } from '@ant-design/icons'; @@ -7,7 +8,6 @@ import G6 from '@antv/g6'; import { Button, message } from 'antd'; import { useEffect, useRef, useState } from 'react'; import { useNavigate, useParams } from 'react-router-dom'; -import { Icon } from 'umi'; import { s8 } from '../../../utils'; import Styles from './editPipeline.less'; import GlobalParamsDrawer from './globalParamsDrawer'; @@ -60,7 +60,7 @@ const EditPipeline = () => { }); const graphRef = useRef(); const paramsDrawerRef = useRef(); - const [paramsDrawerVisible, openParamsDrawer, closeParamsDrawer] = useModal(false); + const [paramsDrawerOpen, openParamsDrawer, closeParamsDrawer] = useAntdModal(false); const [globalParam, setGlobalParam] = useState([]); const onDragEnd = (val) => { @@ -704,7 +704,7 @@ const EditPipeline = () => {