StepPageSplit now: - Auto-calls POST /page-split on step entry - Shows oriented image + detection result - If double page: creates sub-sessions named "Title — S. 1/2" - If single page: green badge "keine Trennung noetig" - Manual "Weiter" button (no auto-advance) Also: - StepOrientation wrapper simplified (no page-split in orientation) - StepUpload passes name back via onUploaded(sid, name) - page.tsx: after page-split "Weiter" switches to first sub-session - useKombiPipeline exposes setSessionName Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
185 lines
5.8 KiB
TypeScript
185 lines
5.8 KiB
TypeScript
'use client'
|
|
|
|
import { Suspense } from 'react'
|
|
import { PagePurpose } from '@/components/common/PagePurpose'
|
|
import { BoxSessionTabs } from '@/components/ocr-pipeline/BoxSessionTabs'
|
|
import { KombiStepper } from '@/components/ocr-kombi/KombiStepper'
|
|
import { SessionList } from '@/components/ocr-kombi/SessionList'
|
|
import { SessionHeader } from '@/components/ocr-kombi/SessionHeader'
|
|
import { StepUpload } from '@/components/ocr-kombi/StepUpload'
|
|
import { StepOrientation } from '@/components/ocr-kombi/StepOrientation'
|
|
import { StepPageSplit } from '@/components/ocr-kombi/StepPageSplit'
|
|
import { StepDeskew } from '@/components/ocr-kombi/StepDeskew'
|
|
import { StepDewarp } from '@/components/ocr-kombi/StepDewarp'
|
|
import { StepContentCrop } from '@/components/ocr-kombi/StepContentCrop'
|
|
import { StepOcr } from '@/components/ocr-kombi/StepOcr'
|
|
import { StepStructure } from '@/components/ocr-kombi/StepStructure'
|
|
import { StepGridBuild } from '@/components/ocr-kombi/StepGridBuild'
|
|
import { StepGridReview } from '@/components/ocr-kombi/StepGridReview'
|
|
import { StepGroundTruth } from '@/components/ocr-kombi/StepGroundTruth'
|
|
import { useKombiPipeline } from './useKombiPipeline'
|
|
|
|
function OcrKombiContent() {
|
|
const {
|
|
currentStep,
|
|
sessionId,
|
|
sessionName,
|
|
loadingSessions,
|
|
activeCategory,
|
|
isGroundTruth,
|
|
subSessions,
|
|
parentSessionId,
|
|
steps,
|
|
gridSaveRef,
|
|
groupedSessions,
|
|
loadSessions,
|
|
openSession,
|
|
handleStepClick,
|
|
handleNext,
|
|
handleNewSession,
|
|
deleteSession,
|
|
renameSession,
|
|
updateCategory,
|
|
handleSessionChange,
|
|
setSessionId,
|
|
setSessionName,
|
|
setSubSessions,
|
|
setParentSessionId,
|
|
setIsGroundTruth,
|
|
} = useKombiPipeline()
|
|
|
|
const renderStep = () => {
|
|
switch (currentStep) {
|
|
case 0:
|
|
return (
|
|
<StepUpload
|
|
sessionId={sessionId}
|
|
onUploaded={(sid, name) => {
|
|
setSessionId(sid)
|
|
setSessionName(name)
|
|
loadSessions()
|
|
}}
|
|
onNext={handleNext}
|
|
/>
|
|
)
|
|
case 1:
|
|
return (
|
|
<StepOrientation
|
|
sessionId={sessionId}
|
|
onNext={() => handleNext()}
|
|
onSessionList={() => { loadSessions(); handleNewSession() }}
|
|
/>
|
|
)
|
|
case 2:
|
|
return (
|
|
<StepPageSplit
|
|
sessionId={sessionId}
|
|
sessionName={sessionName}
|
|
onNext={() => {
|
|
// If sub-sessions were created, switch to the first one
|
|
if (subSessions.length > 0) {
|
|
setSessionId(subSessions[0].id)
|
|
setSessionName(subSessions[0].name)
|
|
}
|
|
handleNext()
|
|
}}
|
|
onSubSessionsCreated={(subs) => {
|
|
setSubSessions(subs)
|
|
if (sessionId) setParentSessionId(sessionId)
|
|
loadSessions()
|
|
}}
|
|
/>
|
|
)
|
|
case 3:
|
|
return <StepDeskew sessionId={sessionId} onNext={handleNext} />
|
|
case 4:
|
|
return <StepDewarp sessionId={sessionId} onNext={handleNext} />
|
|
case 5:
|
|
return <StepContentCrop sessionId={sessionId} onNext={handleNext} />
|
|
case 6:
|
|
return <StepOcr sessionId={sessionId} onNext={handleNext} />
|
|
case 7:
|
|
return <StepStructure sessionId={sessionId} onNext={handleNext} />
|
|
case 8:
|
|
return <StepGridBuild sessionId={sessionId} onNext={handleNext} />
|
|
case 9:
|
|
return <StepGridReview sessionId={sessionId} onNext={handleNext} saveRef={gridSaveRef} />
|
|
case 10:
|
|
return (
|
|
<StepGroundTruth
|
|
sessionId={sessionId}
|
|
isGroundTruth={isGroundTruth}
|
|
onMarked={() => setIsGroundTruth(true)}
|
|
gridSaveRef={gridSaveRef}
|
|
/>
|
|
)
|
|
default:
|
|
return null
|
|
}
|
|
}
|
|
|
|
return (
|
|
<div className="space-y-6">
|
|
<PagePurpose
|
|
title="OCR Kombi Pipeline"
|
|
purpose="Modulare 11-Schritt-Pipeline: Upload, Vorverarbeitung, Dual-Engine-OCR (PP-OCRv5 + Tesseract), Strukturerkennung, Grid-Aufbau und Review. Multi-Page-Dokument-Unterstuetzung."
|
|
audience={['Entwickler']}
|
|
architecture={{
|
|
services: ['klausur-service (FastAPI)', 'OpenCV', 'Tesseract', 'PaddleOCR'],
|
|
databases: ['PostgreSQL Sessions'],
|
|
}}
|
|
relatedPages={[
|
|
{ name: 'OCR Overlay (Legacy)', href: '/ai/ocr-overlay', description: 'Alter 3-Modi-Monolith' },
|
|
{ name: 'OCR Regression', href: '/ai/ocr-regression', description: 'Regressionstests' },
|
|
]}
|
|
defaultCollapsed
|
|
/>
|
|
|
|
<SessionList
|
|
items={groupedSessions()}
|
|
loading={loadingSessions}
|
|
activeSessionId={sessionId}
|
|
onOpenSession={(sid) => openSession(sid)}
|
|
onNewSession={handleNewSession}
|
|
onDeleteSession={deleteSession}
|
|
onRenameSession={renameSession}
|
|
onUpdateCategory={updateCategory}
|
|
/>
|
|
|
|
{sessionId && sessionName && (
|
|
<SessionHeader
|
|
sessionName={sessionName}
|
|
activeCategory={activeCategory}
|
|
isGroundTruth={isGroundTruth}
|
|
onUpdateCategory={(cat) => updateCategory(sessionId, cat)}
|
|
/>
|
|
)}
|
|
|
|
<KombiStepper
|
|
steps={steps}
|
|
currentStep={currentStep}
|
|
onStepClick={handleStepClick}
|
|
/>
|
|
|
|
{subSessions.length > 0 && parentSessionId && sessionId && (
|
|
<BoxSessionTabs
|
|
parentSessionId={parentSessionId}
|
|
subSessions={subSessions}
|
|
activeSessionId={sessionId}
|
|
onSessionChange={handleSessionChange}
|
|
/>
|
|
)}
|
|
|
|
<div className="min-h-[400px]">{renderStep()}</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default function OcrKombiPage() {
|
|
return (
|
|
<Suspense fallback={<div className="p-4 text-sm text-gray-400">Lade...</div>}>
|
|
<OcrKombiContent />
|
|
</Suspense>
|
|
)
|
|
}
|