81 lines
2.6 KiB
TypeScript
81 lines
2.6 KiB
TypeScript
import { useCallback, useEffect, useLayoutEffect, useReducer, useRef } from 'react'
|
|
import {
|
|
intelligentEvalReadAdapter,
|
|
intelligentEvalReadReducer,
|
|
initialIntelligentEvalReadState,
|
|
type IntelligentEvalReadAdapter,
|
|
type IntelligentEvalReadState,
|
|
} from './intelligentEval'
|
|
import { usePolling } from '../hooks/usePolling'
|
|
|
|
const ACTIVE_STATUSES = new Set(['planning', 'pending_approval', 'executing'])
|
|
|
|
function errorMessage(error: unknown): string {
|
|
return error instanceof Error ? error.message : '读取智能评估失败'
|
|
}
|
|
|
|
function isActive(status: string | undefined): boolean {
|
|
return status != null && ACTIVE_STATUSES.has(status)
|
|
}
|
|
|
|
export function useIntelligentEvalRead(
|
|
selectedId: string | null,
|
|
adapter: IntelligentEvalReadAdapter = intelligentEvalReadAdapter,
|
|
): IntelligentEvalReadState & { reloadList: () => Promise<void>; reloadDetail: () => Promise<void> } {
|
|
const [state, dispatch] = useReducer(intelligentEvalReadReducer, initialIntelligentEvalReadState)
|
|
const detailRequestId = useRef(0)
|
|
|
|
const loadList = useCallback(async (silent = false) => {
|
|
dispatch({ type: 'list_requested', silent })
|
|
try {
|
|
const value = await adapter.list()
|
|
dispatch({ type: 'list_succeeded', value })
|
|
} catch (error) {
|
|
dispatch({ type: 'list_failed', error: errorMessage(error) })
|
|
}
|
|
}, [adapter])
|
|
|
|
const loadDetail = useCallback(async (id: string, silent = false) => {
|
|
const requestId = ++detailRequestId.current
|
|
dispatch({ type: 'detail_requested', id, requestId, silent })
|
|
try {
|
|
const value = await adapter.get(id)
|
|
dispatch({ type: 'detail_succeeded', id, requestId, value })
|
|
} catch (error) {
|
|
dispatch({ type: 'detail_failed', id, requestId, error: errorMessage(error) })
|
|
}
|
|
}, [adapter])
|
|
|
|
useEffect(() => {
|
|
void loadList()
|
|
}, [loadList])
|
|
|
|
useLayoutEffect(() => {
|
|
if (selectedId == null) {
|
|
dispatch({ type: 'detail_cleared', requestId: ++detailRequestId.current })
|
|
return
|
|
}
|
|
void loadDetail(selectedId)
|
|
}, [loadDetail, selectedId])
|
|
|
|
const listActive = state.list.value.some((item) => isActive(item.status))
|
|
const detailActive = isActive(state.detail.value?.status)
|
|
|
|
usePolling(() => { void loadList(true) }, 5000, listActive)
|
|
usePolling(
|
|
() => {
|
|
if (selectedId != null) void loadDetail(selectedId, true)
|
|
},
|
|
5000,
|
|
selectedId != null && detailActive,
|
|
)
|
|
|
|
const reloadList = useCallback(() => loadList(true), [loadList])
|
|
const reloadDetail = useCallback(
|
|
() => (selectedId == null ? Promise.resolve() : loadDetail(selectedId, true)),
|
|
[loadDetail, selectedId],
|
|
)
|
|
|
|
return { ...state, reloadList, reloadDetail }
|
|
}
|