diff --git a/react-ui/src/app.tsx b/react-ui/src/app.tsx index ac8b8652..686c495d 100644 --- a/react-ui/src/app.tsx +++ b/react-ui/src/app.tsx @@ -11,6 +11,7 @@ import { getAccessToken } from './access'; import ErrorBoundary from './components/ErrorBoundary'; import './dayjsConfig'; import { removeAllPageCacheState } from './hooks/useCacheState'; +import { globalGetSeverTime } from './hooks/useServerTime'; import { getRemoteMenu, getRoutersInfo, @@ -29,6 +30,7 @@ export { requestConfig as request } from './requestConfig'; export async function getInitialState(): Promise { const fetchUserInfo = async () => { try { + globalGetSeverTime(); const response = await getUserInfo(); return { ...response.user, diff --git a/react-ui/src/components/CodeConfigItem/index.tsx b/react-ui/src/components/CodeConfigItem/index.tsx index ff48368c..942fa203 100644 --- a/react-ui/src/components/CodeConfigItem/index.tsx +++ b/react-ui/src/components/CodeConfigItem/index.tsx @@ -1,4 +1,3 @@ -import { AvailableRange } from '@/enums'; import { type CodeConfigData } from '@/pages/CodeConfig/List'; import { Flex, Typography } from 'antd'; import classNames from 'classnames'; @@ -24,12 +23,12 @@ function CodeConfigItem({ item, onClick }: CodeConfigItemProps) {
- {item.code_repo_vis === AvailableRange.Public ? '公开' : '私有'} + {item.is_public ? '公开' : '私有'}
(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/enums/index.ts b/react-ui/src/enums/index.ts index b043a2d3..a9dd4a0f 100644 --- a/react-ui/src/enums/index.ts +++ b/react-ui/src/enums/index.ts @@ -39,9 +39,9 @@ export enum TensorBoardStatus { // 镜像版本状态 export enum MirrorVersionStatus { - Available = 'available', // 可用 - Building = 'building', // 构建中 - Failed = 'failed', // 构建中 + Available = 'Available', // 可用 + Building = 'Building', // 构建中 + Failed = 'Failed', // 失败 } // 服务运行状态 diff --git a/react-ui/src/hooks/useSSE.ts b/react-ui/src/hooks/useSSE.ts index 5e278675..4ed9d7f2 100644 --- a/react-ui/src/hooks/useSSE.ts +++ b/react-ui/src/hooks/useSSE.ts @@ -1,11 +1,13 @@ import { parseJsonText } from '@/utils'; -import { useCallback, useRef } from 'react'; +import { useEffect } from 'react'; +import { ExperimentStatus } from '@/enums'; +import { NodeStatus } from '@/types'; -export const useSSE = (onMessage: (data: any) => void) => { - const evtSourceRef = useRef(null); - - const setupSSE = useCallback( - (name: string, namespace: string) => { +export type MessageHandler = (experimentInsId: number, status: string, finishedAt: string, nodes: Record) => void +export const useSSE = (experimentInsId: number, status: ExperimentStatus, name: string, namespace: string, onMessage: MessageHandler) => { + const isRunning = status === ExperimentStatus.Pending || status === ExperimentStatus.Running + useEffect(() => { + if (isRunning) { const { origin } = location; const params = encodeURIComponent(`metadata.namespace=${namespace},metadata.name=${name}`); const evtSource = new EventSource( @@ -18,11 +20,10 @@ export const useSSE = (onMessage: (data: any) => void) => { return; } const dataJson = parseJsonText(data); - if (dataJson) { - const nodes = dataJson?.result?.object?.status?.nodes; - if (nodes) { - onMessage(nodes); - } + const statusData = dataJson?.result?.object?.status; + if (statusData) { + const { finishedAt, phase, nodes } = statusData; + onMessage(experimentInsId, phase, finishedAt, nodes); } }; @@ -30,17 +31,10 @@ export const useSSE = (onMessage: (data: any) => void) => { console.error('SSE error: ', error); }; - evtSourceRef.current = evtSource; - }, - [onMessage], - ); - - const closeSSE = useCallback(() => { - if (evtSourceRef.current) { - evtSourceRef.current.close(); - evtSourceRef.current = null; + return () => { + evtSource.close(); + } } - }, []); - - return [setupSSE, closeSSE]; + + }, [experimentInsId, isRunning, name, namespace, onMessage]); }; diff --git a/react-ui/src/hooks/useServerTime.ts b/react-ui/src/hooks/useServerTime.ts new file mode 100644 index 00000000..a5c6f229 --- /dev/null +++ b/react-ui/src/hooks/useServerTime.ts @@ -0,0 +1,53 @@ +/* + * @Author: 赵伟 + * @Date: 2024-10-10 08:51:41 + * @Description: 服务器时间 hook + */ + +import { getSeverTimeReq } from '@/services/experiment'; +import { to } from '@/utils/promise'; +import { useCallback, useEffect, useState } from 'react'; + +let globalTimeOffset: number | undefined = undefined; + +export const globalGetSeverTime = async () => { + const requestStartTime = Date.now(); + const [res] = await to(getSeverTimeReq()); + const requestEndTime = Date.now(); + const requestDuration = (requestEndTime - requestStartTime) / 2; + if (res && res.data) { + const serverDate = new Date(res.data); + const timeOffset = serverDate.getTime() + requestDuration - requestEndTime; + globalTimeOffset = timeOffset; + return timeOffset; + } +}; + +export const now = () => { + return new Date(Date.now() + (globalTimeOffset ?? 0)); +}; + +/** 获取服务器时间 */ +export function useServerTime() { + const [timeOffset, setTimeOffset] = useState(globalTimeOffset ?? 0); + + useEffect(() => { + const getSeverTime = async () => { + const [res] = await to(globalGetSeverTime()); + if (res) { + setTimeOffset(res); + } + }; + + // 获取服务器时间,防止第一次加载时,请求失败 + if (!globalTimeOffset) { + getSeverTime(); + } + }, []); + + const now = useCallback(() => { + return new Date(Date.now() + timeOffset); + }, [timeOffset]); + + return [now] as const; +} diff --git a/react-ui/src/iconfont/iconfont-menu.js b/react-ui/src/iconfont/iconfont-menu.js index 2b0bcaa9..f527568a 100644 --- a/react-ui/src/iconfont/iconfont-menu.js +++ b/react-ui/src/iconfont/iconfont-menu.js @@ -1 +1 @@ -window._iconfont_svg_string_4511326='',(t=>{var a=(l=(l=document.getElementsByTagName("script"))[l.length-1]).getAttribute("data-injectcss"),l=l.getAttribute("data-disable-injectsvg");if(!l){var i,h,o,c,e,m=function(a,l){l.parentNode.insertBefore(a,l)};if(a&&!t.__iconfont__svg__cssinject__){t.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(a){console&&console.log(a)}}i=function(){var a,l=document.createElement("div");l.innerHTML=t._iconfont_svg_string_4511326,(l=l.getElementsByTagName("svg")[0])&&(l.setAttribute("aria-hidden","true"),l.style.position="absolute",l.style.width=0,l.style.height=0,l.style.overflow="hidden",l=l,(a=document.body).firstChild?m(l,a.firstChild):a.appendChild(l))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(i,0):(h=function(){document.removeEventListener("DOMContentLoaded",h,!1),i()},document.addEventListener("DOMContentLoaded",h,!1)):document.attachEvent&&(o=i,c=t.document,e=!1,n(),c.onreadystatechange=function(){"complete"==c.readyState&&(c.onreadystatechange=null,p())})}function p(){e||(e=!0,o())}function n(){try{c.documentElement.doScroll("left")}catch(a){return void setTimeout(n,50)}p()}})(window); \ No newline at end of file +window._iconfont_svg_string_4511326='',(t=>{var a=(l=(l=document.getElementsByTagName("script"))[l.length-1]).getAttribute("data-injectcss"),l=l.getAttribute("data-disable-injectsvg");if(!l){var i,h,o,c,e,m=function(a,l){l.parentNode.insertBefore(a,l)};if(a&&!t.__iconfont__svg__cssinject__){t.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(a){console&&console.log(a)}}i=function(){var a,l=document.createElement("div");l.innerHTML=t._iconfont_svg_string_4511326,(l=l.getElementsByTagName("svg")[0])&&(l.setAttribute("aria-hidden","true"),l.style.position="absolute",l.style.width=0,l.style.height=0,l.style.overflow="hidden",l=l,(a=document.body).firstChild?m(l,a.firstChild):a.appendChild(l))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(i,0):(h=function(){document.removeEventListener("DOMContentLoaded",h,!1),i()},document.addEventListener("DOMContentLoaded",h,!1)):document.attachEvent&&(o=i,c=t.document,e=!1,n(),c.onreadystatechange=function(){"complete"==c.readyState&&(c.onreadystatechange=null,p())})}function p(){e||(e=!0,o())}function n(){try{c.documentElement.doScroll("left")}catch(a){return void setTimeout(n,50)}p()}})(window); \ No newline at end of file diff --git a/react-ui/src/iconfont/iconfont-menu.json b/react-ui/src/iconfont/iconfont-menu.json index 15215226..cb25a583 100644 --- a/react-ui/src/iconfont/iconfont-menu.json +++ b/react-ui/src/iconfont/iconfont-menu.json @@ -1,10 +1,24 @@ { "id": "4511326", - "name": "智能材料科研平台-导航", + "name": "复杂智能软件-导航", "font_family": "iconfont", "css_prefix_text": "icon-", "description": "", "glyphs": [ + { + "icon_id": "42495274", + "name": "知识图谱-active", + "font_class": "zhishitupu-icon-active", + "unicode": "e63e", + "unicode_decimal": 58942 + }, + { + "icon_id": "42495275", + "name": "知识图谱", + "font_class": "zhishitupu-icon", + "unicode": "e63f", + "unicode_decimal": 58943 + }, { "icon_id": "41643218", "name": "模型开发", diff --git a/react-ui/src/iconfont/iconfont.js b/react-ui/src/iconfont/iconfont.js index 75c1b755..38c8ec18 100644 --- a/react-ui/src/iconfont/iconfont.js +++ b/react-ui/src/iconfont/iconfont.js @@ -1 +1 @@ -window._iconfont_svg_string_4511447='',(t=>{var a=(h=(h=document.getElementsByTagName("script"))[h.length-1]).getAttribute("data-injectcss"),h=h.getAttribute("data-disable-injectsvg");if(!h){var l,z,v,i,o,m=function(a,h){h.parentNode.insertBefore(a,h)};if(a&&!t.__iconfont__svg__cssinject__){t.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(a){console&&console.log(a)}}l=function(){var a,h=document.createElement("div");h.innerHTML=t._iconfont_svg_string_4511447,(h=h.getElementsByTagName("svg")[0])&&(h.setAttribute("aria-hidden","true"),h.style.position="absolute",h.style.width=0,h.style.height=0,h.style.overflow="hidden",h=h,(a=document.body).firstChild?m(h,a.firstChild):a.appendChild(h))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(l,0):(z=function(){document.removeEventListener("DOMContentLoaded",z,!1),l()},document.addEventListener("DOMContentLoaded",z,!1)):document.attachEvent&&(v=l,i=t.document,o=!1,d(),i.onreadystatechange=function(){"complete"==i.readyState&&(i.onreadystatechange=null,p())})}function p(){o||(o=!0,v())}function d(){try{i.documentElement.doScroll("left")}catch(a){return void setTimeout(d,50)}p()}})(window); \ No newline at end of file +window._iconfont_svg_string_4511447='',(t=>{var a=(h=(h=document.getElementsByTagName("script"))[h.length-1]).getAttribute("data-injectcss"),h=h.getAttribute("data-disable-injectsvg");if(!h){var l,v,z,i,o,p=function(a,h){h.parentNode.insertBefore(a,h)};if(a&&!t.__iconfont__svg__cssinject__){t.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(a){console&&console.log(a)}}l=function(){var a,h=document.createElement("div");h.innerHTML=t._iconfont_svg_string_4511447,(h=h.getElementsByTagName("svg")[0])&&(h.setAttribute("aria-hidden","true"),h.style.position="absolute",h.style.width=0,h.style.height=0,h.style.overflow="hidden",h=h,(a=document.body).firstChild?p(h,a.firstChild):a.appendChild(h))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(l,0):(v=function(){document.removeEventListener("DOMContentLoaded",v,!1),l()},document.addEventListener("DOMContentLoaded",v,!1)):document.attachEvent&&(z=l,i=t.document,o=!1,d(),i.onreadystatechange=function(){"complete"==i.readyState&&(i.onreadystatechange=null,m())})}function m(){o||(o=!0,z())}function d(){try{i.documentElement.doScroll("left")}catch(a){return void setTimeout(d,50)}m()}})(window); \ No newline at end of file diff --git a/react-ui/src/pages/ActiveLearn/Instance/index.tsx b/react-ui/src/pages/ActiveLearn/Instance/index.tsx index 680f935c..5655e60d 100644 --- a/react-ui/src/pages/ActiveLearn/Instance/index.tsx +++ b/react-ui/src/pages/ActiveLearn/Instance/index.tsx @@ -106,13 +106,13 @@ function ActiveLearnInstance() { if (dataJson) { const nodes = dataJson?.result?.object?.status?.nodes; if (nodes) { + // 节点 + setNodes(nodes); + const workflowStatus = Object.values(nodes).find((node: any) => node.displayName.startsWith(NodePrefix), ) as NodeStatus; - // 节点 - setNodes(nodes); - // 设置工作流状态 if (workflowStatus) { setWorkflowStatus(workflowStatus); @@ -153,6 +153,7 @@ function ActiveLearnInstance() { className={styles['active-learn-instance__basic']} info={experimentInfo} runStatus={workflowStatus} + instanceStatus={instanceInfo?.status} isInstance /> ), diff --git a/react-ui/src/pages/ActiveLearn/components/ActiveLearnBasic/index.tsx b/react-ui/src/pages/ActiveLearn/components/ActiveLearnBasic/index.tsx index 892e6725..79ab1698 100644 --- a/react-ui/src/pages/ActiveLearn/components/ActiveLearnBasic/index.tsx +++ b/react-ui/src/pages/ActiveLearn/components/ActiveLearnBasic/index.tsx @@ -1,5 +1,5 @@ import ConfigInfo, { type BasicInfoData } from '@/components/ConfigInfo'; -import { AutoMLTaskType, autoMLTaskTypeOptions } from '@/enums'; +import { AutoMLTaskType, autoMLTaskTypeOptions, ExperimentStatus } from '@/enums'; import { useComputingResource } from '@/hooks/useComputingResource'; import { classifierAlgorithms, @@ -9,9 +9,8 @@ import { regressorAlgorithms, } from '@/pages/ActiveLearn/components/CreateForm/utils'; import { ActiveLearnData } from '@/pages/ActiveLearn/types'; -import { experimentStatusInfo } from '@/pages/Experiment/status'; +import ExperimentRunBasic from '@/pages/AutoML/components/ExperimentRunBasic'; import { type NodeStatus } from '@/types'; -import { elapsedTime } from '@/utils/date'; import { formatBoolean, formatCodeConfig, @@ -21,7 +20,6 @@ import { formatMirror, formatModel, } from '@/utils/format'; -import { Flex } from 'antd'; import classNames from 'classnames'; import { useMemo } from 'react'; import styles from './index.less'; @@ -31,9 +29,16 @@ type BasicInfoProps = { className?: string; isInstance?: boolean; runStatus?: NodeStatus; + instanceStatus?: ExperimentStatus; }; -function BasicInfo({ info, className, runStatus, isInstance = false }: BasicInfoProps) { +function BasicInfo({ + info, + className, + runStatus, + instanceStatus, + isInstance = false, +}: BasicInfoProps) { const getResourceDescription = useComputingResource()[1]; const basicDatas: BasicInfoData[] = useMemo(() => { if (!info) { @@ -149,7 +154,7 @@ function BasicInfo({ info, className, runStatus, isInstance = false }: BasicInfo value: info.dataset_py, }, { - label: '数据集类名', + label: '数据集处理类名', value: info.dataset_class_name, }, { @@ -205,56 +210,13 @@ function BasicInfo({ info, className, runStatus, isInstance = false }: BasicInfo ]; }, [info, getResourceDescription]); - const instanceDatas = useMemo(() => { - if (!info || !runStatus) { - return []; - } - - return [ - { - label: '启动时间', - value: formatDate(info.create_time), - ellipsis: true, - }, - { - label: '执行时长', - value: elapsedTime(info.create_time, runStatus.finishedAt), - ellipsis: true, - }, - { - label: '状态', - value: ( - - -
- {experimentStatusInfo[runStatus?.phase]?.label} -
-
- ), - ellipsis: true, - }, - ]; - }, [runStatus, info]); - return (
{isInstance && runStatus && ( - )} {!isInstance && ( diff --git a/react-ui/src/pages/ActiveLearn/components/CreateForm/ExecuteConfig.tsx b/react-ui/src/pages/ActiveLearn/components/CreateForm/ExecuteConfig.tsx index addb402c..c510dc3b 100644 --- a/react-ui/src/pages/ActiveLearn/components/CreateForm/ExecuteConfig.tsx +++ b/react-ui/src/pages/ActiveLearn/components/CreateForm/ExecuteConfig.tsx @@ -101,16 +101,16 @@ function ExecuteConfig() { - + diff --git a/react-ui/src/pages/AutoML/Instance/index.tsx b/react-ui/src/pages/AutoML/Instance/index.tsx index 44489ea7..e0fb5e4d 100644 --- a/react-ui/src/pages/AutoML/Instance/index.tsx +++ b/react-ui/src/pages/AutoML/Instance/index.tsx @@ -110,13 +110,13 @@ function AutoMLInstance() { if (dataJson) { const nodes = dataJson?.result?.object?.status?.nodes; if (nodes) { + // 节点 + setNodes(nodes); + const workflowStatus = Object.values(nodes).find((node: any) => node.displayName.startsWith(NodePrefix), ) as NodeStatus; - // 节点 - setNodes(nodes); - if (workflowStatus) { setWorkflowStatus(workflowStatus); @@ -156,6 +156,7 @@ function AutoMLInstance() { className={styles['auto-ml-instance__basic']} info={autoMLInfo} runStatus={workflowStatus} + instanceStatus={instanceInfo?.status} isInstance /> ), diff --git a/react-ui/src/pages/AutoML/components/AutoMLBasic/index.tsx b/react-ui/src/pages/AutoML/components/AutoMLBasic/index.tsx index 98a1f4ba..08c95ed9 100644 --- a/react-ui/src/pages/AutoML/components/AutoMLBasic/index.tsx +++ b/react-ui/src/pages/AutoML/components/AutoMLBasic/index.tsx @@ -2,19 +2,18 @@ import ConfigInfo, { type BasicInfoData } from '@/components/ConfigInfo'; import { AutoMLTaskType, AutoMLType, + ExperimentStatus, autoMLEnsembleClassOptions, autoMLTaskTypeOptions, } from '@/enums'; import { useComputingResource } from '@/hooks/useComputingResource'; 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'; import { useMemo } from 'react'; +import ExperimentRunBasic from '../ExperimentRunBasic'; import styles from './index.less'; // 格式化优化方向 @@ -40,9 +39,16 @@ type AutoMLBasicProps = { className?: string; isInstance?: boolean; runStatus?: NodeStatus; + instanceStatus?: ExperimentStatus; }; -function AutoMLBasic({ info, className, runStatus, isInstance = false }: AutoMLBasicProps) { +function AutoMLBasic({ + info, + className, + runStatus, + instanceStatus, + isInstance = false, +}: AutoMLBasicProps) { const getResourceDescription = useComputingResource()[1]; const basicDatas: BasicInfoData[] = useMemo(() => { if (!info) { @@ -284,53 +290,13 @@ function AutoMLBasic({ info, className, runStatus, isInstance = false }: AutoMLB ]; }, [info]); - const instanceDatas = useMemo(() => { - if (!info || !runStatus) { - return []; - } - - return [ - { - label: '启动时间', - value: formatDate(info.create_time), - }, - { - label: '执行时长', - value: elapsedTime(info.create_time, runStatus.finishedAt), - }, - { - label: '状态', - value: ( - - -
- {experimentStatusInfo[runStatus?.phase]?.label} -
-
- ), - }, - ]; - }, [runStatus, info]); - return (
{isInstance && runStatus && ( - )} {!isInstance && ( diff --git a/react-ui/src/pages/AutoML/components/ExperimentInstance/index.less b/react-ui/src/pages/AutoML/components/ExperimentInstanceList/index.less similarity index 77% rename from react-ui/src/pages/AutoML/components/ExperimentInstance/index.less rename to react-ui/src/pages/AutoML/components/ExperimentInstanceList/index.less index 833ced06..94258c7f 100644 --- a/react-ui/src/pages/AutoML/components/ExperimentInstance/index.less +++ b/react-ui/src/pages/AutoML/components/ExperimentInstanceList/index.less @@ -1,3 +1,5 @@ +@cellWidth: calc(100% + 32px + 33px - 48px - 200px - 344px); + .tableExpandBox { display: flex; align-items: center; @@ -11,22 +13,22 @@ } .check { - width: calc((100% + 32px + 33px) / 5 / 2); + width: calc(@cellWidth * 3 / 20); // 15% } .index { - width: calc((100% + 32px + 33px) / 5 / 2); + width: calc(@cellWidth * 3 / 20); // 15% } .description { display: flex; - flex: 1; align-items: center; + width: calc(@cellWidth / 2); // 50% } .startTime { .singleLine(); - width: 200px; + width: calc(@cellWidth / 5); // 20% } .status { diff --git a/react-ui/src/pages/AutoML/components/ExperimentInstance/index.tsx b/react-ui/src/pages/AutoML/components/ExperimentInstanceList/index.tsx similarity index 83% rename from react-ui/src/pages/AutoML/components/ExperimentInstance/index.tsx rename to react-ui/src/pages/AutoML/components/ExperimentInstanceList/index.tsx index 74cf1115..05d6d786 100644 --- a/react-ui/src/pages/AutoML/components/ExperimentInstance/index.tsx +++ b/react-ui/src/pages/AutoML/components/ExperimentInstanceList/index.tsx @@ -1,20 +1,19 @@ import KFIcon from '@/components/KFIcon'; import { ExperimentStatus } from '@/enums'; import { useCheck } from '@/hooks/useCheck'; -import { experimentStatusInfo } from '@/pages/Experiment/status'; import themes from '@/styles/theme.less'; import { type ExperimentInstance } from '@/types'; -import { elapsedTime, formatDate } from '@/utils/date'; import { to } from '@/utils/promise'; import { modalConfirm } from '@/utils/ui'; import { DoubleRightOutlined } from '@ant-design/icons'; -import { App, Button, Checkbox, ConfigProvider, Typography } from 'antd'; +import { App, Button, Checkbox, ConfigProvider } from 'antd'; import classNames from 'classnames'; import { useEffect, useMemo } from 'react'; import { ExperimentListType, experimentListConfig } from '../ExperimentList/config'; import styles from './index.less'; +import ExperimentInstanceComponent from './instance'; -type ExperimentInstanceProps = { +type ExperimentInstanceListProps = { type: ExperimentListType; experimentInsList?: ExperimentInstance[]; experimentInsTotal: number; @@ -24,7 +23,7 @@ type ExperimentInstanceProps = { onLoadMore?: () => void; }; -function ExperimentInstanceComponent({ +function ExperimentInstanceList({ type, experimentInsList, experimentInsTotal, @@ -32,7 +31,7 @@ function ExperimentInstanceComponent({ onRemove, onTerminate, onLoadMore, -}: ExperimentInstanceProps) { +}: ExperimentInstanceListProps) { const { message } = App.useApp(); const allIntanceIds = useMemo(() => { return experimentInsList?.map((item) => item.id) || []; @@ -171,28 +170,14 @@ function ExperimentInstanceComponent({ > {index + 1} -
- {elapsedTime(item.create_time, item.finish_time)} -
-
- - {formatDate(item.create_time)} - -
-
- - - {experimentStatusInfo[item.status as ExperimentStatus]?.label} - -
+
)} +
+ + {info.praises_count} +
版本号: @@ -262,12 +291,17 @@ const ResourceInfo = ({ resourceType }: ResourceInfoProps) => { - )} - {record.status === DevEditorStatus.Running ? ( + {record.status !== DevEditorStatus.Running ? (
执行时长: - {elapsedTime(experimentIns?.create_time, experimentIns?.finish_time)} +
状态: diff --git a/react-ui/src/pages/Experiment/components/ExperimentDrawer/index.tsx b/react-ui/src/pages/Experiment/components/ExperimentDrawer/index.tsx index bcb3af1e..11d0ff2e 100644 --- a/react-ui/src/pages/Experiment/components/ExperimentDrawer/index.tsx +++ b/react-ui/src/pages/Experiment/components/ExperimentDrawer/index.tsx @@ -1,10 +1,11 @@ +import RunDuration from '@/components/RunDuration'; import { ExperimentStatus } from '@/enums'; 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'; @@ -41,22 +42,6 @@ const ExperimentDrawer = ({ instanceNodeStartTime, instanceNodeEndTime, }: ExperimentDrawerProps) => { - const [currentDate, setCurrentDate] = useState( - instanceNodeEndTime ? new Date(instanceNodeEndTime) : new Date(), - ); - - // 定时刷新耗时 - useEffect(() => { - if (!instanceNodeEndTime) { - const timer = setInterval(() => { - setCurrentDate(new Date()); - }, 1000); - return () => { - clearInterval(timer); - }; - } - }, [instanceNodeEndTime]); - // 如果性能有问题,可以进一步拆解 const items = useMemo( () => [ @@ -158,7 +143,7 @@ const ExperimentDrawer = ({
耗时: - {elapsedTime(instanceNodeStartTime, currentDate)} +
void; @@ -29,7 +28,7 @@ type ExperimentInstanceProps = { onLoadMore?: () => void; }; -function ExperimentInstanceComponent({ +function ExperimentInstanceList({ experimentInsList, experimentInsTotal, onClickInstance, @@ -37,7 +36,7 @@ function ExperimentInstanceComponent({ onRemove, onTerminate, onLoadMore, -}: ExperimentInstanceProps) { +}: ExperimentInstanceListProps) { const { message } = App.useApp(); const allIntanceIds = useMemo(() => { return experimentInsList?.map((item) => item.id) || []; @@ -185,28 +184,16 @@ function ExperimentInstanceComponent({ '--' )} -
-
{elapsedTime(item.create_time, item.finish_time)}
-
- - {formatDate(item.create_time)} - -
-
-
- - - {experimentStatusInfo[item.status as ExperimentStatus]?.label} - -
+ + +