diff --git a/react-ui/src/components/RunDuration/index.tsx b/react-ui/src/components/RunDuration/index.tsx new file mode 100644 index 00000000..f430d058 --- /dev/null +++ b/react-ui/src/components/RunDuration/index.tsx @@ -0,0 +1,35 @@ +import { useServerTime } from '@/hooks/useServerTime'; +import { elapsedTime } from '@/utils/date'; +import React, { useEffect, useState } from 'react'; + +type RunDurationProps = { + createTime?: string; + finishTime?: string; + className?: string; + style?: React.CSSProperties; +}; +function RunDuration({ createTime, finishTime, className, style }: RunDurationProps) { + const [now] = useServerTime(); + const [currentTime, setCurrentTime] = useState(now()); + + // 定时刷新耗时 + useEffect(() => { + if (finishTime) { + setCurrentTime(new Date(finishTime)); + } else { + const timer = setInterval(() => { + setCurrentTime(now()); + }, 1000); + return () => { + clearInterval(timer); + }; + } + }, [finishTime, now]); + return ( + + {elapsedTime(createTime, currentTime)} + + ); +} + +export default RunDuration; diff --git a/react-ui/src/pages/ActiveLearn/Instance/index.tsx b/react-ui/src/pages/ActiveLearn/Instance/index.tsx index ba62fae7..d16d5428 100644 --- a/react-ui/src/pages/ActiveLearn/Instance/index.tsx +++ b/react-ui/src/pages/ActiveLearn/Instance/index.tsx @@ -1,6 +1,5 @@ import KFIcon from '@/components/KFIcon'; import { AutoMLTaskType, ExperimentStatus } from '@/enums'; -import { useServerTime } from '@/hooks/useServerTime'; import { getActiveLearnInsReq } from '@/services/activeLearn'; import { NodeStatus } from '@/types'; import { parseJsonText } from '@/utils'; @@ -36,9 +35,6 @@ function ActiveLearnInstance() { const params = useParams(); const instanceId = safeInvoke(Number)(params.id); const evtSourceRef = useRef(null); - const [now] = useServerTime(); - const [currentTime, setCurrentTime] = useState(now()); - const finish_time = workflowStatus?.finishedAt; useEffect(() => { if (instanceId) { @@ -50,20 +46,6 @@ function ActiveLearnInstance() { // eslint-disable-next-line react-hooks/exhaustive-deps }, [instanceId]); - // 定时刷新耗时 - useEffect(() => { - if (finish_time) { - setCurrentTime(new Date(finish_time)); - } else { - const timer = setInterval(() => { - setCurrentTime(now()); - }, 1000); - return () => { - clearInterval(timer); - }; - } - }, [finish_time, now]); - // 获取实验实例详情 const getExperimentInsInfo = async (isStatusDetermined: boolean) => { const [res] = await to(getActiveLearnInsReq(instanceId)); @@ -171,7 +153,6 @@ function ActiveLearnInstance() { className={styles['active-learn-instance__basic']} info={experimentInfo} runStatus={workflowStatus} - finishTime={currentTime} isInstance /> ), diff --git a/react-ui/src/pages/ActiveLearn/components/ActiveLearnBasic/index.tsx b/react-ui/src/pages/ActiveLearn/components/ActiveLearnBasic/index.tsx index e76fe67b..5c0d4e3e 100644 --- a/react-ui/src/pages/ActiveLearn/components/ActiveLearnBasic/index.tsx +++ b/react-ui/src/pages/ActiveLearn/components/ActiveLearnBasic/index.tsx @@ -1,4 +1,5 @@ import ConfigInfo, { type BasicInfoData } from '@/components/ConfigInfo'; +import RunDuration from '@/components/RunDuration'; import { AutoMLTaskType, autoMLTaskTypeOptions } from '@/enums'; import { useComputingResource } from '@/hooks/useComputingResource'; import { @@ -11,7 +12,6 @@ import { import { ActiveLearnData } from '@/pages/ActiveLearn/types'; import { experimentStatusInfo } from '@/pages/Experiment/status'; import { type NodeStatus } from '@/types'; -import { elapsedTime } from '@/utils/date'; import { formatBoolean, formatCodeConfig, @@ -31,10 +31,9 @@ type BasicInfoProps = { className?: string; isInstance?: boolean; runStatus?: NodeStatus; - finishTime?: Date; }; -function BasicInfo({ info, className, runStatus, finishTime, isInstance = false }: BasicInfoProps) { +function BasicInfo({ info, className, runStatus, isInstance = false }: BasicInfoProps) { const getResourceDescription = useComputingResource()[1]; const basicDatas: BasicInfoData[] = useMemo(() => { if (!info) { @@ -215,12 +214,10 @@ function BasicInfo({ info, className, runStatus, finishTime, isInstance = false { label: '启动时间', value: formatDate(info.create_time), - ellipsis: true, }, { label: '执行时长', - value: elapsedTime(info.create_time, finishTime), - ellipsis: true, + value: , }, { label: '状态', @@ -243,10 +240,9 @@ function BasicInfo({ info, className, runStatus, finishTime, isInstance = false ), - ellipsis: true, }, ]; - }, [runStatus, info, finishTime]); + }, [runStatus, info]); return (
diff --git a/react-ui/src/pages/AutoML/Instance/index.tsx b/react-ui/src/pages/AutoML/Instance/index.tsx index 675b02d4..5f1b5e34 100644 --- a/react-ui/src/pages/AutoML/Instance/index.tsx +++ b/react-ui/src/pages/AutoML/Instance/index.tsx @@ -1,6 +1,5 @@ import KFIcon from '@/components/KFIcon'; import { AutoMLTaskType, AutoMLType, ExperimentStatus } from '@/enums'; -import { useServerTime } from '@/hooks/useServerTime'; import { getExperimentInsReq } from '@/services/autoML'; import { NodeStatus } from '@/types'; import { parseJsonText } from '@/utils'; @@ -36,9 +35,6 @@ function AutoMLInstance() { const params = useParams(); const instanceId = safeInvoke(Number)(params.id); const evtSourceRef = useRef(null); - const [now] = useServerTime(); - const [currentTime, setCurrentTime] = useState(now()); - const finish_time = workflowStatus?.finishedAt; useEffect(() => { if (instanceId) { @@ -50,20 +46,6 @@ function AutoMLInstance() { // eslint-disable-next-line react-hooks/exhaustive-deps }, [instanceId]); - // 定时刷新耗时 - useEffect(() => { - if (finish_time) { - setCurrentTime(new Date(finish_time)); - } else { - const timer = setInterval(() => { - setCurrentTime(now()); - }, 1000); - return () => { - clearInterval(timer); - }; - } - }, [finish_time, now]); - // 获取实验实例详情 const getExperimentInsInfo = async (isStatusDetermined: boolean) => { const [res] = await to(getExperimentInsReq(instanceId)); @@ -174,7 +156,6 @@ function AutoMLInstance() { className={styles['auto-ml-instance__basic']} info={autoMLInfo} runStatus={workflowStatus} - finishTime={currentTime} isInstance /> ), diff --git a/react-ui/src/pages/AutoML/components/AutoMLBasic/index.tsx b/react-ui/src/pages/AutoML/components/AutoMLBasic/index.tsx index e31c7ecb..c421c59e 100644 --- a/react-ui/src/pages/AutoML/components/AutoMLBasic/index.tsx +++ b/react-ui/src/pages/AutoML/components/AutoMLBasic/index.tsx @@ -1,4 +1,5 @@ import ConfigInfo, { type BasicInfoData } from '@/components/ConfigInfo'; +import RunDuration from '@/components/RunDuration'; import { AutoMLTaskType, AutoMLType, @@ -10,7 +11,6 @@ import { AutoMLData } from '@/pages/AutoML/types'; import { experimentStatusInfo } from '@/pages/Experiment/status'; import { type NodeStatus } from '@/types'; import { parseJsonText } from '@/utils'; -import { elapsedTime } from '@/utils/date'; import { formatBoolean, formatDataset, formatDate, formatEnum } from '@/utils/format'; import { Flex } from 'antd'; import classNames from 'classnames'; @@ -40,16 +40,9 @@ type AutoMLBasicProps = { className?: string; isInstance?: boolean; runStatus?: NodeStatus; - finishTime?: Date; }; -function AutoMLBasic({ - info, - className, - runStatus, - finishTime, - isInstance = false, -}: AutoMLBasicProps) { +function AutoMLBasic({ info, className, runStatus, isInstance = false }: AutoMLBasicProps) { const getResourceDescription = useComputingResource()[1]; const basicDatas: BasicInfoData[] = useMemo(() => { if (!info) { @@ -303,7 +296,7 @@ function AutoMLBasic({ }, { label: '执行时长', - value: elapsedTime(info.create_time, finishTime), + value: , }, { label: '状态', @@ -328,7 +321,7 @@ function AutoMLBasic({ ), }, ]; - }, [runStatus, info, finishTime]); + }, [runStatus, info]); return (
diff --git a/react-ui/src/pages/AutoML/components/ExperimentInstanceList/instance.tsx b/react-ui/src/pages/AutoML/components/ExperimentInstanceList/instance.tsx index 831879f2..402d27dd 100644 --- a/react-ui/src/pages/AutoML/components/ExperimentInstanceList/instance.tsx +++ b/react-ui/src/pages/AutoML/components/ExperimentInstanceList/instance.tsx @@ -1,11 +1,11 @@ +import RunDuration from '@/components/RunDuration'; import { ExperimentStatus } from '@/enums'; -import { useServerTime } from '@/hooks/useServerTime'; import { useSSE, type MessageHandler } from '@/hooks/useSSE'; import { experimentStatusInfo } from '@/pages/Experiment/status'; import { ExperimentCompleted } from '@/utils/constant'; -import { elapsedTime, formatDate } from '@/utils/date'; +import { formatDate } from '@/utils/date'; import { Typography } from 'antd'; -import React, { useCallback, useEffect, useState } from 'react'; +import React, { useCallback } from 'react'; import styles from './index.less'; type ExperimentInstanceProps = { @@ -25,9 +25,6 @@ function ExperimentInstance({ argo_ins_ns, experimentInsId, }: ExperimentInstanceProps) { - const [now] = useServerTime(); - const [currentTime, setCurrentTime] = useState(now()); - const handleSSEMessage: MessageHandler = useCallback( (experimentInsId: number, status: string, finish_time: string) => { window.postMessage({ @@ -43,23 +40,11 @@ function ExperimentInstance({ ); useSSE(experimentInsId, status, argo_ins_name, argo_ins_ns, handleSSEMessage); - // 定时刷新耗时 - useEffect(() => { - if (finish_time) { - setCurrentTime(new Date(finish_time)); - } else { - const timer = setInterval(() => { - setCurrentTime(now()); - }, 1000); - return () => { - clearInterval(timer); - }; - } - }, [finish_time, now]); - return ( -
{elapsedTime(create_time, currentTime)}
+
+ +
{formatDate(create_time)} diff --git a/react-ui/src/pages/AutoML/components/ExperimentList/index.tsx b/react-ui/src/pages/AutoML/components/ExperimentList/index.tsx index b4eeb199..442f38f5 100644 --- a/react-ui/src/pages/AutoML/components/ExperimentList/index.tsx +++ b/react-ui/src/pages/AutoML/components/ExperimentList/index.tsx @@ -29,7 +29,7 @@ import { } from 'antd'; import { type SearchProps } from 'antd/es/input'; import classNames from 'classnames'; -import { useCallback, useEffect, useState } from 'react'; +import { useCallback, useEffect, useRef, useState } from 'react'; import ExperimentInstanceList from '../ExperimentInstanceList'; import { ExperimentListType, experimentListConfig } from './config'; import styles from './index.less'; @@ -58,6 +58,7 @@ function ExperimentList({ type }: ExperimentListProps) { }, ); const config = experimentListConfig[type]; + const timerRef = useRef | undefined>(); // 获取自主机器学习或超参数自动优化列表 const getAutoMLList = useCallback(async () => { @@ -140,7 +141,13 @@ function ExperimentList({ type }: ExperimentListProps) { : v, ), ); - setTimeout(() => { + + if (timerRef.current) { + clearTimeout(timerRef.current); + timerRef.current = undefined; + } + + timerRef.current = setTimeout(() => { refreshExperimentList(); }, 10000); } @@ -149,6 +156,10 @@ function ExperimentList({ type }: ExperimentListProps) { window.addEventListener('message', handleMessage); return () => { window.removeEventListener('message', handleMessage); + if (timerRef.current) { + clearTimeout(timerRef.current); + timerRef.current = undefined; + } }; }, [refreshExperimentList]); diff --git a/react-ui/src/pages/Experiment/Info/index.jsx b/react-ui/src/pages/Experiment/Info/index.jsx index 39526410..60424e52 100644 --- a/react-ui/src/pages/Experiment/Info/index.jsx +++ b/react-ui/src/pages/Experiment/Info/index.jsx @@ -16,6 +16,7 @@ import ParamsModal from '../components/ViewParamsModal'; import { experimentStatusInfo } from '../status'; import styles from './index.less'; import { useServerTime } from '@/hooks/useServerTime'; +import RunDuration from '@/components/RunDuration'; let graph = null; @@ -28,13 +29,10 @@ function ExperimentText() { const [paramsModalOpen, openParamsModal, closeParamsModal] = useVisible(false); const [propsDrawerOpen, openPropsDrawer, closePropsDrawer, propsDrawerOpenRef] = useVisible(false); - const [now] = useServerTime(); - const [currentTime, setCurrentTime] = useState(now()); const navigate = useNavigate(); const evtSourceRef = useRef(); const width = 110; const height = 36; - const finish_time = experimentIns?.finish_time useEffect(() => { initGraph(); @@ -63,20 +61,6 @@ function ExperimentText() { }; }, []); - // 定时刷新耗时 - useEffect(() => { - if (finish_time) { - setCurrentTime(new Date(finish_time)); - } else { - const timer = setInterval(() => { - setCurrentTime(now()); - }, 1000); - return () => { - clearInterval(timer); - }; - } - }, [finish_time, now]); - // 获取流水线模版 const getWorkflow = async () => { const [res] = await to(getWorkflowById(locationParams.workflowId)); @@ -492,7 +476,7 @@ function ExperimentText() {
执行时长: - {elapsedTime(experimentIns?.create_time, currentTime)} +
状态: diff --git a/react-ui/src/pages/Experiment/components/ExperimentDrawer/index.tsx b/react-ui/src/pages/Experiment/components/ExperimentDrawer/index.tsx index 766b8f9a..11d0ff2e 100644 --- a/react-ui/src/pages/Experiment/components/ExperimentDrawer/index.tsx +++ b/react-ui/src/pages/Experiment/components/ExperimentDrawer/index.tsx @@ -1,11 +1,11 @@ +import RunDuration from '@/components/RunDuration'; import { ExperimentStatus } from '@/enums'; -import { useServerTime } from '@/hooks/useServerTime'; import { experimentStatusInfo } from '@/pages/Experiment/status'; import { PipelineNodeModelSerialize } from '@/types'; -import { elapsedTime, formatDate } from '@/utils/date'; +import { formatDate } from '@/utils/date'; import { CloseOutlined, DatabaseOutlined, ProfileOutlined } from '@ant-design/icons'; import { Drawer, Tabs, Typography } from 'antd'; -import { useEffect, useMemo, useState } from 'react'; +import { useMemo } from 'react'; import ExperimentParameter from '../ExperimentParameter'; import ExperimentResult from '../ExperimentResult'; import LogList from '../LogList'; @@ -42,23 +42,6 @@ const ExperimentDrawer = ({ instanceNodeStartTime, instanceNodeEndTime, }: ExperimentDrawerProps) => { - const [now] = useServerTime(); - const [currentTime, setCurrentTime] = useState(now()); - - // 定时刷新耗时 - useEffect(() => { - if (instanceNodeEndTime) { - setCurrentTime(new Date(instanceNodeEndTime)); - } else { - const timer = setInterval(() => { - setCurrentTime(now()); - }, 1000); - return () => { - clearInterval(timer); - }; - } - }, [instanceNodeEndTime, now]); - // 如果性能有问题,可以进一步拆解 const items = useMemo( () => [ @@ -160,7 +143,7 @@ const ExperimentDrawer = ({
耗时: - {elapsedTime(instanceNodeStartTime, currentTime)} +
(now()); - const handleSSEMessage: MessageHandler = useCallback( (experimentInsId: number, status: string, finish_time: string) => { window.postMessage({ @@ -43,24 +40,12 @@ function ExperimentInstance({ ); useSSE(experimentInsId, status, argo_ins_name, argo_ins_ns, handleSSEMessage); - // 定时刷新耗时 - useEffect(() => { - if (finish_time) { - setCurrentTime(new Date(finish_time)); - } else { - const timer = setInterval(() => { - setCurrentTime(now()); - }, 1000); - return () => { - clearInterval(timer); - }; - } - }, [finish_time, now]); - return (
-
{elapsedTime(create_time, currentTime)}
+
+ +
{formatDate(create_time)} diff --git a/react-ui/src/pages/Experiment/index.jsx b/react-ui/src/pages/Experiment/index.jsx index e424de20..e94c625c 100644 --- a/react-ui/src/pages/Experiment/index.jsx +++ b/react-ui/src/pages/Experiment/index.jsx @@ -21,7 +21,7 @@ import tableCellRender, { TableCellValueType } from '@/utils/table'; import { modalConfirm } from '@/utils/ui'; import { App, Button, ConfigProvider, Dropdown, Input, Space, Table, Tooltip } from 'antd'; import classNames from 'classnames'; -import { useCallback, useEffect, useState } from 'react'; +import { useCallback, useEffect, useRef, useState } from 'react'; import { useNavigate } from 'react-router-dom'; import { ComparisonType } from './Comparison/config'; import AddExperimentModal from './components/AddExperimentModal'; @@ -54,6 +54,7 @@ function Experiment() { }, ); const { message } = App.useApp(); + const timerRef = useRef(); // 获取实验列表 const getExperimentList = useCallback(async () => { @@ -126,7 +127,13 @@ function Experiment() { : v, ), ); - setTimeout(() => { + + if (timerRef.current) { + clearTimeout(timerRef.current); + timerRef.current = undefined; + } + + timerRef.current = setTimeout(() => { refreshExperimentList(); }, 10000); } @@ -135,6 +142,10 @@ function Experiment() { window.addEventListener('message', handleMessage); return () => { window.removeEventListener('message', handleMessage); + if (timerRef.current) { + clearTimeout(timerRef.current); + timerRef.current = undefined; + } }; }, [refreshExperimentList]); diff --git a/react-ui/src/pages/HyperParameter/Instance/index.tsx b/react-ui/src/pages/HyperParameter/Instance/index.tsx index 148a38e7..a0ebae5b 100644 --- a/react-ui/src/pages/HyperParameter/Instance/index.tsx +++ b/react-ui/src/pages/HyperParameter/Instance/index.tsx @@ -1,6 +1,5 @@ import KFIcon from '@/components/KFIcon'; import { ExperimentStatus } from '@/enums'; -import { useServerTime } from '@/hooks/useServerTime'; import { getRayInsReq } from '@/services/hyperParameter'; import { NodeStatus } from '@/types'; import { parseJsonText } from '@/utils'; @@ -36,9 +35,6 @@ function HyperParameterInstance() { const params = useParams(); const instanceId = safeInvoke(Number)(params.id); const evtSourceRef = useRef(null); - const [now] = useServerTime(); - const [currentTime, setCurrentTime] = useState(now()); - const finish_time = workflowStatus?.finishedAt; useEffect(() => { if (instanceId) { @@ -50,20 +46,6 @@ function HyperParameterInstance() { // eslint-disable-next-line react-hooks/exhaustive-deps }, [instanceId]); - // 定时刷新耗时 - useEffect(() => { - if (finish_time) { - setCurrentTime(new Date(finish_time)); - } else { - const timer = setInterval(() => { - setCurrentTime(now()); - }, 1000); - return () => { - clearInterval(timer); - }; - } - }, [finish_time, now]); - // 获取实验实例详情 const getExperimentInsInfo = async (isStatusDetermined: boolean) => { const [res] = await to(getRayInsReq(instanceId)); @@ -71,7 +53,7 @@ function HyperParameterInstance() { const info = res.data as HyperParameterInstanceData; const { param, node_status, argo_ins_name, argo_ins_ns, status, create_time } = info; // 解析配置参数 - const paramJson = parseJsonText(param); + const paramJson = parseJsonText(param).data; if (paramJson) { // 实例详情返回的参数是字符串,需要转换 if (typeof paramJson.parameters === 'string') { @@ -186,7 +168,6 @@ function HyperParameterInstance() { className={styles['hyper-parameter-instance__basic']} info={experimentInfo} runStatus={workflowStatus} - finishTime={currentTime} isInstance /> ), diff --git a/react-ui/src/pages/HyperParameter/components/HyperParameterBasic/index.tsx b/react-ui/src/pages/HyperParameter/components/HyperParameterBasic/index.tsx index e62bc6ff..3e526848 100644 --- a/react-ui/src/pages/HyperParameter/components/HyperParameterBasic/index.tsx +++ b/react-ui/src/pages/HyperParameter/components/HyperParameterBasic/index.tsx @@ -1,4 +1,5 @@ import ConfigInfo, { type BasicInfoData } from '@/components/ConfigInfo'; +import RunDuration from '@/components/RunDuration'; import { hyperParameterOptimizedMode } from '@/enums'; import { useComputingResource } from '@/hooks/useComputingResource'; import { experimentStatusInfo } from '@/pages/Experiment/status'; @@ -8,7 +9,6 @@ import { } from '@/pages/HyperParameter/components/CreateForm/utils'; import { HyperParameterData } from '@/pages/HyperParameter/types'; import { type NodeStatus } from '@/types'; -import { elapsedTime } from '@/utils/date'; import { formatCodeConfig, formatDataset, @@ -33,14 +33,12 @@ type HyperParameterBasicProps = { className?: string; isInstance?: boolean; runStatus?: NodeStatus; - finishTime?: Date; }; function HyperParameterBasic({ info, className, runStatus, - finishTime, isInstance = false, }: HyperParameterBasicProps) { const getResourceDescription = useComputingResource()[1]; @@ -157,7 +155,7 @@ function HyperParameterBasic({ }, { label: '执行时长', - value: elapsedTime(info.create_time, finishTime), + value: , ellipsis: true, }, { @@ -184,7 +182,7 @@ function HyperParameterBasic({ ellipsis: true, }, ]; - }, [runStatus, info, finishTime]); + }, [runStatus, info]); return (