feat: progress log

This commit is contained in:
ningyv
2025-02-12 18:20:35 +08:00
parent ec951dd87f
commit 444a48c8f2
3 changed files with 59 additions and 65 deletions
@@ -5,19 +5,14 @@ import WithPermission from '@common/components/aoplatform/WithPermission'
import { BasicResponse, RESPONSE_TIPS, STATUS_CODE } from '@common/const/const'
import { useFetch } from '@common/hooks/http'
import { $t } from '@common/locales/index.ts'
import { App, Button, Typography } from 'antd'
import { App, Button, Typography } from 'antd'
import { useEffect, useRef, useState } from 'react'
import { useSearchParams } from 'react-router-dom'
import { LoadBalancingHandle, LoadBalancingItems } from './type'
import TableBtnWithPermission from '@common/components/aoplatform/TableBtnWithPermission'
import AddLoadBalancingModel from './AddModel'
const LoadBalancingPage = () => {
const pageListRef = useRef<ActionType>(null)
const [searchParams] = useSearchParams()
const serviceId = searchParams.get('serviceId')
const [searchWord, setSearchWord] = useState<string>('')
const [columns, setColumns] = useState<PageProColumns<LoadBalancingItems>[]>([])
const { modal, message } = App.useApp()
@@ -40,9 +35,9 @@ const LoadBalancingPage = () => {
closable: true,
onOk: () => {
return addModelRef.current?.save().then((res) => {
if (res === true) {
pageListRef.current?.reload()
}
if (res === true) {
pageListRef.current?.reload()
}
})
},
wrapClassName: 'ant-modal-without-footer',
@@ -58,16 +53,13 @@ const LoadBalancingPage = () => {
* @returns
*/
const requestApis = () => {
return fetchData<BasicResponse<{ list: LoadBalancingItems[]; total: number }>>(
`ai/balances`,
{
method: 'GET',
eoParams: {
keyword: searchWord
},
eoTransformKeys: ['api_count', 'key_count']
}
)
return fetchData<BasicResponse<{ list: LoadBalancingItems[]; total: number }>>(`ai/balances`, {
method: 'GET',
eoParams: {
keyword: searchWord
},
eoTransformKeys: ['api_count', 'key_count']
})
.then((response) => {
const { code, data, msg } = response
if (code === STATUS_CODE.SUCCESS) {
@@ -203,7 +195,9 @@ const LoadBalancingPage = () => {
width: 120,
ellipsis: true,
key: 'state',
render: (dom: React.ReactNode, record: LoadBalancingItems) => <span>{statusEnum[record.state]?.text || '-'}</span>
render: (dom: React.ReactNode, record: LoadBalancingItems) => (
<span>{statusEnum[record.state]?.text || '-'}</span>
)
},
{
title: $t('Apis'),
@@ -31,7 +31,13 @@ const SystemList: FC = () => {
const [open, setOpen] = useState(false)
const drawerFormRef = useRef<SystemConfigHandle>(null)
const { checkPermission, accessInit, getGlobalAccessData, state } = useGlobalContext()
const [stateColumnMap] = useState<{ [k: string]: { text: string } }>({
normal: { text: $t('正常') },
deploying: { text: $t('部署中') },
error: { text: $t('异常') },
public: { text: $t('公共服务') },
private: { text: $t('私有服务') }
})
const getSystemList = () => {
if (!accessInit) {
getGlobalAccessData()?.then?.(() => {
@@ -131,9 +137,13 @@ const SystemList: FC = () => {
setOpen(false)
}
const openLogsModal = (record: any) => {
const closeModal = () => {
modalInstance.destroy()
manualReloadTable()
}
const modalInstance = modal.confirm({
title: $t('部署过程'),
content: <ServiceDeployment record={record} />,
content: <ServiceDeployment record={record} closeModal={closeModal} />,
footer: () => {
return <LogsFooter record={record} modalInstance={modalInstance} />
},
@@ -163,7 +173,7 @@ const SystemList: FC = () => {
if ((x.dataIndex as string) === 'state') {
x.render = (text: any, record: any) => (
<span
className={`text-[13px] ${record.state === 'deploying' ? '[&>.ant-typography]:text-[#2196f3]' : record.state === 'error' ? '[&>.ant-typography]:text-[#ff4d4f]' : ''}`}
className={`text-[13px] ${record.state === 'deploying' ? 'text-[#2196f3]' : record.state === 'error' ? 'text-[#ff4d4f]' : ''}`}
onClick={(e) => {
if (['deploying', 'error'].includes(record.state)) {
e?.stopPropagation()
@@ -171,7 +181,7 @@ const SystemList: FC = () => {
}
}}
>
{text}
{stateColumnMap[record.state]?.text || '-'}
</span>
)
}
@@ -3,7 +3,8 @@ import { Steps } from 'antd'
import { CheckCircleOutlined, LoadingOutlined, ClockCircleOutlined, CloseCircleOutlined } from '@ant-design/icons'
import { Codebox } from '@common/components/postcat/api/Codebox'
import { Collapse } from 'antd'
import { useEffect, useState } from 'react'
import { useEffect, useRef, useState } from 'react'
import { $t } from '@common/locales/index.ts'
import { useFetch } from '@common/hooks/http'
const getIcon = (status: string) => {
@@ -21,43 +22,49 @@ const getIcon = (status: string) => {
}
}
export const ServiceDeployment = (props: { record: SystemTableListItem }) => {
const { record } = props
export const ServiceDeployment = (props: { record: SystemTableListItem, closeModal?: () => void }) => {
const { record, closeModal } = props
const [stepItem, setStepItem] = useState<
{
id: string
title: string
description?: string
status?: string
}[]
>([
{
title: 'Download',
id: 'download',
title: $t('下载'),
status: 'pending'
},
{
title: 'Deploy',
id: 'deploy',
title: $t('部署'),
status: 'pending'
},
{
title: 'Initializing',
id: 'initializing',
title: $t('初始化'),
status: 'pending'
}
])
const [scriptStr, setScriptStr] = useState('')
const [step, setStep] = useState(0)
const step = useRef(0)
const [collapseText] = useState('Progress log')
const { fetchData } = useFetch()
useEffect(() => {
const updateStepItems = (targetStep: number, description = '') => {
setStepItem((prevItems) =>
prevItems.map((item, index) => {
return { ...item, status: index < step ? 'completed' : item.status }
})
)
}, [step])
prevItems.map((item, index) => ({
...item,
description: item.id === 'download' ? description : item.description,
status: index < targetStep ? 'completed' : index === targetStep ? 'inProgress' : 'pending',
}))
);
step.current = targetStep;
};
useEffect(() => {
fetchData(
'model/local/deploy',
@@ -72,42 +79,25 @@ export const ServiceDeployment = (props: { record: SystemTableListItem }) => {
const parsedChunk = JSON.parse(chunk)
// 下载中
if (parsedChunk?.data?.state.includes('download')) {
setStepItem((prevItems) =>
prevItems.map((item) => {
return item.title === 'Download'
? {
...item,
description: `${parsedChunk?.data?.info?.current} / ${parsedChunk?.data?.info?.total}`,
status: 'inProgress'
}
: item
})
)
setStep(0)
updateStepItems(0, `${parsedChunk?.data?.info?.current} / ${parsedChunk?.data?.info?.total}`);
// 部署中
} else if (parsedChunk?.data?.state.includes('deploy')) {
setStepItem((prevItems) =>
prevItems.map((item) => {
return { ...item, status: item.title === 'Deploy' ? 'inProgress' : item.status }
})
)
setStep(1)
updateStepItems(1);
// 初始化中
} else if (parsedChunk?.data?.state.includes('initializing')) {
setStepItem((prevItems) =>
prevItems.map((item) => {
return { ...item, status: item.title === 'Initializing' ? 'inProgress' : item.status }
})
)
setStep(2)
updateStepItems(2);
// 完成
} else if (parsedChunk?.data?.state.includes('finish')) {
updateStepItems(4);
setTimeout(() => {
closeModal?.()
}, 200)
} else if (parsedChunk?.data?.state.includes('error')) {
setStepItem((prevItems) =>
prevItems.map((item) => {
return { ...item, status: item.title === 'Initializing' ? 'completed' : item.status }
prevItems.map((item, index) => {
return { ...item, status: index === step.current ? 'error' : item.status }
})
)
setStep(4)
}
setScriptStr(parsedChunk?.data?.message || '')
}