Files
OCR/frontend/src/hooks/useTaskValidation.ts
egg efa7e4175c feat: optimize task file generation and add visualization download
Backend changes:
- Disable PP-Structure debug file generation by default
- Separate raw_ocr_regions.json generation from debug flag (critical file)
- Add visualization folder download endpoint as ZIP
- Add has_visualization field to TaskDetailResponse
- Stop generating Markdown files
- Save translated PDFs to task folder with caching

Frontend changes:
- Replace JSON/MD download buttons with PDF buttons in TaskHistoryPage
- Add visualization download button in TaskDetailPage
- Fix Processing page task switching issue (reset isNotFound)

Archives two OpenSpec proposals:
- optimize-task-files-and-visualization
- simplify-frontend-add-billing

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-12 19:11:50 +08:00

91 lines
2.9 KiB
TypeScript

import { useEffect, useState } from 'react'
import { useQuery } from '@tanstack/react-query'
import { AxiosError } from 'axios'
import { useUploadStore } from '@/store/uploadStore'
import { useTaskStore } from '@/store/taskStore'
import { apiClientV2 } from '@/services/apiV2'
import type { TaskDetail } from '@/types/apiV2'
interface UseTaskValidationResult {
taskId: string | null
taskDetail: TaskDetail | undefined
isLoading: boolean
isNotFound: boolean
clearAndReset: () => void
}
/**
* Hook for validating task existence and handling deleted tasks gracefully.
* Shows loading state first, then either returns task data or marks as not found.
*
* This hook integrates with both uploadStore (legacy) and taskStore (new).
* The taskId is sourced from uploadStore.batchId for backward compatibility,
* while task metadata is synced to taskStore for caching and state management.
*/
export function useTaskValidation(options?: {
refetchInterval?: number | false | ((query: any) => number | false)
}): UseTaskValidationResult {
// Legacy: Get taskId from uploadStore
const { batchId, clearUpload } = useUploadStore()
const taskId = batchId ? String(batchId) : null
// New: Use taskStore for caching and state management
const { updateTaskCache, removeFromCache, clearCurrentTask } = useTaskStore()
const [isNotFound, setIsNotFound] = useState(false)
// Reset isNotFound when taskId changes (new upload)
useEffect(() => {
setIsNotFound(false)
}, [taskId])
const { data: taskDetail, isLoading, error, isFetching } = useQuery({
queryKey: ['taskDetail', taskId],
queryFn: () => apiClientV2.getTask(taskId!),
enabled: !!taskId && !isNotFound,
retry: (failureCount, error: any) => {
// Don't retry on 404
if (error?.response?.status === 404) {
return false
}
return failureCount < 2
},
refetchInterval: options?.refetchInterval ?? false,
// Disable stale time to ensure we check fresh data
staleTime: 0,
})
// Sync task details to taskStore cache when data changes
useEffect(() => {
if (taskDetail) {
updateTaskCache(taskDetail)
}
}, [taskDetail, updateTaskCache])
// Handle 404 error - mark as not found and clean up cache
useEffect(() => {
if (error && error instanceof AxiosError && error.response?.status === 404) {
setIsNotFound(true)
if (taskId) {
removeFromCache(taskId)
}
}
}, [error, taskId, removeFromCache])
// Clear state and store
const clearAndReset = () => {
clearUpload() // Legacy store
clearCurrentTask() // New store
setIsNotFound(false)
}
return {
taskId,
taskDetail,
// Show loading if we have a taskId and are still fetching (but not if already marked as not found)
isLoading: !!taskId && !isNotFound && (isLoading || isFetching) && !taskDetail,
isNotFound,
clearAndReset,
}
}