import { root } from '@repo/core' import { type ListTemplateGenerationsInput, type TemplateGeneration, TemplateGenerationController } from '@repo/sdk' import { useCallback, useEffect, useRef, useState } from 'react' import { type ApiError } from '@/lib/types' import { handleError } from './use-error' const pageSize = 12 // 公共工具函数 const getController = () => root.get(TemplateGenerationController) const filterValidItems = (items: unknown[]): TemplateGeneration[] => (items || []).filter((item: unknown): item is TemplateGeneration => { return Boolean( item && typeof item === 'object' && item !== null && 'id' in item && (item as Record).id, ) }) const calculateHasMore = (items: unknown[], limit: number): boolean => Array.isArray(items) && items.length === limit export const useTemplateGenerations = () => { const [loading, setLoading] = useState(true) const [loadingMore, setLoadingMore] = useState(false) const [error, setError] = useState(null) const [data, setData] = useState([]) const [hasMore, setHasMore] = useState(true) const currentPageRef = useRef(1) const abortControllerRef = useRef(null) const load = useCallback(async (params?: ListTemplateGenerationsInput) => { // 取消之前的请求 if (abortControllerRef.current) { abortControllerRef.current.abort() } abortControllerRef.current = new AbortController() setLoading(true) setError(null) currentPageRef.current = 1 const limit = params?.limit || pageSize const { data: responseData, error } = await handleError(async () => getController().list({ page: 1, limit, ...params, }), ) // 如果请求被中止,直接返回 if (abortControllerRef.current?.signal.aborted) { return } if (error) { setError(error) setLoading(false) return { data: undefined, error } } const items = responseData?.data || [] const filterData = filterValidItems(items) const hasMoreResult = calculateHasMore(items, limit) setData(filterData) setHasMore(hasMoreResult) setLoading(false) abortControllerRef.current = null return { data: filterData, error: null } }, []) const loadMore = useCallback( async (params?: Omit) => { // 防止竞态条件和无效请求 if (loading || loadingMore || !hasMore) return setLoadingMore(true) const nextPage = currentPageRef.current + 1 const limit = params?.limit || pageSize const { data: responseData, error } = await handleError(async () => getController().list({ page: nextPage, limit, ...params, }), ) if (error) { setLoadingMore(false) setError(error) return { data: undefined, error } } const newItems = responseData?.data || [] const filterData = filterValidItems(newItems) const hasMoreResult = calculateHasMore(newItems, limit) currentPageRef.current = nextPage setData((prev) => [...prev, ...filterData]) setHasMore(hasMoreResult) setLoadingMore(false) return { data: filterData, error: null } }, [loading, loadingMore, hasMore], ) const refetch = useCallback( (params?: ListTemplateGenerationsInput) => { setHasMore(true) return load(params) }, [load], ) useEffect(() => { load() // 清理函数:组件卸载时取消未完成的请求 return () => { if (abortControllerRef.current) { abortControllerRef.current.abort() } } // eslint-disable-next-line react-hooks/exhaustive-deps }, []) // 只在组件挂载时执行一次初始加载 return { data, loading, loadingMore, error, load, refetch, loadMore, hasMore, } }