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>
This commit is contained in:
egg
2025-12-12 19:11:50 +08:00
parent 65abd51d60
commit efa7e4175c
14 changed files with 534 additions and 97 deletions

View File

@@ -1510,14 +1510,25 @@ class OCRService:
'height': ocr_height
}]
# Generate PP-StructureV3 debug outputs if enabled
# Always save raw_ocr_regions.json (required for PDF generation and translation)
if output_dir:
try:
import json
ocr_json_path = output_dir / f"{image_path.stem}_raw_ocr_regions.json"
with open(ocr_json_path, 'w', encoding='utf-8') as f:
json.dump(text_regions, f, ensure_ascii=False, indent=2)
logger.info(f"Saved raw OCR regions to {ocr_json_path}")
except Exception as ocr_save_error:
logger.warning(f"Failed to save raw OCR regions: {ocr_save_error}")
# Generate PP-StructureV3 debug outputs if enabled (debug files only)
if settings.pp_structure_debug_enabled and output_dir:
try:
from app.services.pp_structure_debug import PPStructureDebug
debug_service = PPStructureDebug(output_dir)
# Save raw results as JSON
debug_service.save_raw_results(
# Save PP-Structure raw results and summary (debug only)
debug_service.save_debug_results(
pp_structure_results={
'elements': layout_data.get('elements', []),
'total_elements': layout_data.get('total_elements', 0),
@@ -2536,7 +2547,7 @@ class OCRService:
source_file_path: Optional[Path] = None
) -> Tuple[Optional[Path], Optional[Path], Optional[Path]]:
"""
Save OCR results to JSON, Markdown, and layout-preserving PDF files
Save OCR results to JSON and layout-preserving PDF files
Args:
result: OCR result (UnifiedDocument or dictionary)
@@ -2546,9 +2557,11 @@ class OCRService:
Returns:
Tuple of (json_path, markdown_path, pdf_path)
Note: markdown_path is always None (Markdown generation removed)
"""
try:
output_dir.mkdir(parents=True, exist_ok=True)
markdown_path = None # Markdown generation removed
# Use UnifiedDocumentExporter for standardized export
if isinstance(result, UnifiedDocument) and UnifiedDocumentExporter is not None:
@@ -2560,31 +2573,16 @@ class OCRService:
include_metadata=True,
include_statistics=True
)
markdown_path = output_dir / f"{file_id}_output.md"
UnifiedDocumentExporter.export_to_markdown(
result,
markdown_path,
include_metadata_header=False # Keep output clean
)
markdown_content = result.extract_all_text()
else:
# Legacy path for dict results
result_dict = result if isinstance(result, dict) else result.to_dict()
markdown_content = result.get('markdown_content', '') if isinstance(result, dict) else ''
# Save JSON
json_path = output_dir / f"{file_id}_result.json"
with open(json_path, 'w', encoding='utf-8') as f:
json.dump(result_dict, f, ensure_ascii=False, indent=2)
# Save Markdown
markdown_path = output_dir / f"{file_id}_output.md"
with open(markdown_path, 'w', encoding='utf-8') as f:
f.write(markdown_content)
logger.info(f"Results saved: {json_path.name}, {markdown_path.name}")
logger.info(f"Results saved: {json_path.name}")
# Generate layout-preserving PDF
pdf_path = None