feat: implement hybrid image extraction and memory management

Backend:
- Add hybrid image extraction for Direct track (inline image blocks)
- Add render_inline_image_regions() fallback when OCR doesn't find images
- Add check_document_for_missing_images() for detecting missing images
- Add memory management system (MemoryGuard, ModelManager, ServicePool)
- Update pdf_generator_service to handle HYBRID processing track
- Add ElementType.LOGO for logo extraction

Frontend:
- Fix PDF viewer re-rendering issues with memoization
- Add TaskNotFound component and useTaskValidation hook
- Disable StrictMode due to react-pdf incompatibility
- Fix task detail and results page loading states

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
egg
2025-11-26 10:56:22 +08:00
parent ba8ddf2b68
commit 1afdb822c3
26 changed files with 8273 additions and 366 deletions

View File

@@ -1,3 +1,4 @@
import { useMemo } from 'react'
import { useParams, useNavigate } from 'react-router-dom'
import { useTranslation } from 'react-i18next'
import { useQuery } from '@tanstack/react-query'
@@ -65,6 +66,19 @@ export default function TaskDetailPage() {
retry: false,
})
// Construct PDF URL for preview - memoize to prevent unnecessary reloads
// Must be called unconditionally before any early returns (React hooks rule)
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || 'http://localhost:8000'
const pdfUrl = useMemo(() => {
return taskId ? `${API_BASE_URL}/api/v2/tasks/${taskId}/download/pdf` : ''
}, [taskId, API_BASE_URL])
// Get auth token for PDF preview - memoize to prevent new object reference each render
const pdfHttpHeaders = useMemo(() => {
const authToken = localStorage.getItem('auth_token_v2')
return authToken ? { Authorization: `Bearer ${authToken}` } : undefined
}, [])
const getTrackBadge = (track?: ProcessingTrack) => {
if (!track) return null
switch (track) {
@@ -218,14 +232,6 @@ export default function TaskDetailPage() {
const isProcessing = taskDetail.status === 'processing'
const isFailed = taskDetail.status === 'failed'
// Construct PDF URL for preview
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || 'http://localhost:8000'
const pdfUrl = taskId ? `${API_BASE_URL}/api/v2/tasks/${taskId}/download/pdf` : ''
// Get auth token for PDF preview
const authToken = localStorage.getItem('auth_token_v2')
const pdfHttpHeaders = authToken ? { Authorization: `Bearer ${authToken}` } : undefined
return (
<div className="space-y-6">
{/* Page Header */}