'use client' import { useState, useCallback, useEffect, useRef } from 'react' import { api } from '@/lib/api' import type { VideoReviewRequest, ReviewTask, TaskStatus, } from '@/types/review' interface UseReviewOptions { pollingInterval?: number onComplete?: (result: ReviewTask) => void onError?: (error: Error) => void } /** * 视频审核 Hook */ export function useReview(options: UseReviewOptions = {}) { const { pollingInterval = 2000, onComplete, onError } = options const [isSubmitting, setIsSubmitting] = useState(false) const [isPolling, setIsPolling] = useState(false) const [task, setTask] = useState(null) const [error, setError] = useState(null) const intervalRef = useRef(null) /** * 提交审核 */ const submitReview = useCallback(async (data: VideoReviewRequest) => { setIsSubmitting(true) setError(null) try { const response = await api.submitVideoReview(data) setTask({ reviewId: response.reviewId, status: response.status, createdAt: new Date().toISOString(), }) return response.reviewId } catch (err) { const error = err instanceof Error ? err : new Error('提交失败') setError(error) onError?.(error) throw error } finally { setIsSubmitting(false) } }, [onError]) /** * 查询进度 */ const fetchProgress = useCallback(async (reviewId: string) => { try { const progress = await api.getReviewProgress(reviewId) setTask((prev) => ({ ...prev, reviewId: progress.reviewId, status: progress.status, progress: progress.progress, currentStep: progress.currentStep, createdAt: prev?.createdAt || new Date().toISOString(), })) return progress } catch (err) { const error = err instanceof Error ? err : new Error('查询失败') setError(error) throw error } }, []) /** * 查询结果 */ const fetchResult = useCallback(async (reviewId: string) => { try { const result = await api.getReviewResult(reviewId) const updatedTask: ReviewTask = { reviewId: result.reviewId, status: result.status, score: result.score, summary: result.summary, violations: result.violations, softWarnings: result.softWarnings, createdAt: task?.createdAt || new Date().toISOString(), completedAt: new Date().toISOString(), } setTask(updatedTask) return updatedTask } catch (err) { const error = err instanceof Error ? err : new Error('查询失败') setError(error) throw error } }, [task?.createdAt]) /** * 清除轮询定时器 */ const clearPollingInterval = useCallback(() => { if (intervalRef.current) { clearInterval(intervalRef.current) intervalRef.current = null } }, []) /** * 开始轮询进度 */ const startPolling = useCallback((reviewId: string) => { // 清除之前的轮询(如果有) clearPollingInterval() setIsPolling(true) const poll = async () => { try { const progress = await fetchProgress(reviewId) if (progress.status === 'completed') { clearPollingInterval() setIsPolling(false) const result = await fetchResult(reviewId) onComplete?.(result) } else if (progress.status === 'failed') { clearPollingInterval() setIsPolling(false) const error = new Error('审核失败') setError(error) onError?.(error) } } catch { // 继续轮询,忽略单次错误 } } intervalRef.current = setInterval(poll, pollingInterval) poll() // 立即执行一次 return () => { clearPollingInterval() setIsPolling(false) } }, [fetchProgress, fetchResult, pollingInterval, onComplete, onError, clearPollingInterval]) /** * 停止轮询 */ const stopPolling = useCallback(() => { clearPollingInterval() setIsPolling(false) }, [clearPollingInterval]) // 组件卸载时清除定时器,防止内存泄漏 useEffect(() => { return () => { clearPollingInterval() } }, [clearPollingInterval]) /** * 重置状态 */ const reset = useCallback(() => { setTask(null) setError(null) setIsSubmitting(false) setIsPolling(false) }, []) return { task, error, isSubmitting, isPolling, submitReview, fetchProgress, fetchResult, startPolling, stopPolling, reset, } } /** * 审核结果 Hook (单次查询) */ export function useReviewResult(reviewId: string | null) { const [task, setTask] = useState(null) const [isLoading, setIsLoading] = useState(false) const [error, setError] = useState(null) useEffect(() => { if (!reviewId) return const fetchResult = async () => { setIsLoading(true) setError(null) try { const result = await api.getReviewResult(reviewId) setTask({ reviewId: result.reviewId, status: result.status, score: result.score, summary: result.summary, violations: result.violations, softWarnings: result.softWarnings, createdAt: new Date().toISOString(), }) } catch (err) { setError(err instanceof Error ? err : new Error('查询失败')) } finally { setIsLoading(false) } } fetchResult() }, [reviewId]) return { task, isLoading, error } }