feat: add batch processing for multiple file uploads
- Add BatchState management in taskStore with progress tracking - Implement batch processing service with concurrency control - Direct Track: max 5 parallel tasks - OCR Track: sequential processing (GPU VRAM limit) - Refactor ProcessingPage to support batch mode with BatchProcessingPanel - Update UploadPage to initialize batch state for multi-file uploads - Add i18n translations for batch processing (zh-TW, en-US) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -14,11 +14,30 @@ import PreprocessingSettings from '@/components/PreprocessingSettings'
|
||||
import PreprocessingPreview from '@/components/PreprocessingPreview'
|
||||
import ProcessingTrackSelector from '@/components/ProcessingTrackSelector'
|
||||
import TaskNotFound from '@/components/TaskNotFound'
|
||||
import BatchProcessingPanel from '@/components/BatchProcessingPanel'
|
||||
import { useTaskValidation } from '@/hooks/useTaskValidation'
|
||||
import { useTaskStore, useProcessingState } from '@/store/taskStore'
|
||||
import { useTaskStore, useProcessingState, useIsBatchMode } from '@/store/taskStore'
|
||||
import type { LayoutModel, ProcessingOptions, PreprocessingMode, PreprocessingConfig, ProcessingTrack } from '@/types/apiV2'
|
||||
|
||||
/**
|
||||
* ProcessingPage - Main entry point
|
||||
* Routes to batch or single task processing based on state
|
||||
*/
|
||||
export default function ProcessingPage() {
|
||||
const isBatchMode = useIsBatchMode()
|
||||
|
||||
// Route to appropriate component
|
||||
if (isBatchMode) {
|
||||
return <BatchProcessingPanel />
|
||||
}
|
||||
|
||||
return <SingleTaskProcessing />
|
||||
}
|
||||
|
||||
/**
|
||||
* SingleTaskProcessing - Original single task processing UI
|
||||
*/
|
||||
function SingleTaskProcessing() {
|
||||
const { t } = useTranslation()
|
||||
const navigate = useNavigate()
|
||||
const { toast } = useToast()
|
||||
|
||||
@@ -7,6 +7,7 @@ import { Button } from '@/components/ui/button'
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
|
||||
import { useToast } from '@/components/ui/toast'
|
||||
import { useUploadStore } from '@/store/uploadStore'
|
||||
import { useTaskStore } from '@/store/taskStore'
|
||||
import { apiClientV2 } from '@/services/apiV2'
|
||||
import { FileText, X, Upload, Trash2, CheckCircle2, ArrowRight } from 'lucide-react'
|
||||
|
||||
@@ -16,6 +17,8 @@ export default function UploadPage() {
|
||||
const { toast } = useToast()
|
||||
const [selectedFiles, setSelectedFiles] = useState<File[]>([])
|
||||
const { setBatchId, setUploadProgress } = useUploadStore()
|
||||
const initBatch = useTaskStore((state) => state.initBatch)
|
||||
const setCurrentTask = useTaskStore((state) => state.setCurrentTask)
|
||||
|
||||
const uploadMutation = useMutation({
|
||||
mutationFn: async (files: File[]) => {
|
||||
@@ -33,9 +36,22 @@ export default function UploadPage() {
|
||||
if (tasks.length > 0) {
|
||||
setBatchId(tasks[0].task_id as unknown as number)
|
||||
}
|
||||
|
||||
// Initialize batch state with all uploaded tasks
|
||||
if (tasks.length > 1) {
|
||||
// Multiple files: use batch mode
|
||||
initBatch(tasks.map(t => ({
|
||||
taskId: t.task_id,
|
||||
filename: t.filename,
|
||||
})))
|
||||
} else if (tasks.length === 1) {
|
||||
// Single file: use single task mode
|
||||
setCurrentTask(tasks[0].task_id, tasks[0].filename)
|
||||
}
|
||||
|
||||
toast({
|
||||
title: t('upload.uploadSuccess'),
|
||||
description: `成功上傳 ${tasks.length} 個檔案`,
|
||||
description: t('upload.filesUploaded', { count: tasks.length }),
|
||||
variant: 'success',
|
||||
})
|
||||
navigate('/processing')
|
||||
|
||||
Reference in New Issue
Block a user