update: fix-02

This commit is contained in:
2026-03-13 09:57:04 +08:00
parent 7cd2a18364
commit e0a40ceff0
10 changed files with 843 additions and 133 deletions

View File

@@ -1,5 +1,6 @@
from uuid import UUID
import asyncio
from sqlalchemy import delete, select
from fastapi import APIRouter, Depends, UploadFile, File, HTTPException
from fastapi.responses import FileResponse
@@ -10,7 +11,13 @@ from app.core.database import get_db
from app.models.evidence_image import EvidenceImage, SourceApp, PageType, OcrStatus
from app.repositories.image_repo import ImageRepository
from app.repositories.case_repo import CaseRepository
from app.schemas.image import ImageOut, ImageDetailOut, OcrFieldCorrection, CaseOcrStartIn
from app.schemas.image import (
ImageOut,
ImageDetailOut,
OcrFieldCorrection,
CaseOcrStartIn,
CaseImagesDeleteIn,
)
from app.utils.hash import sha256_file
from app.utils.file_storage import save_upload
@@ -172,6 +179,12 @@ async def start_case_ocr(
await db.commit()
else:
images = await repo.list_for_ocr(case_id, include_done=include_done)
# Mark queued images as processing immediately, including when OCR is
# triggered from workspace page, so UI can show progress right away.
for img in images:
img.ocr_status = OcrStatus.processing
await db.flush()
await db.commit()
from app.workers.ocr_tasks import process_images_ocr_batch_async
@@ -190,3 +203,70 @@ async def start_case_ocr(
"totalCandidates": len(images),
"message": f"已提交 {submitted} 张截图的 OCR 任务",
}
@router.delete("/cases/{case_id}/images")
async def delete_case_images(
case_id: UUID,
payload: CaseImagesDeleteIn,
db: AsyncSession = Depends(get_db),
):
case_repo = CaseRepository(db)
case = await case_repo.get(case_id)
if not case:
raise HTTPException(404, "案件不存在")
if not payload.image_ids:
return {"caseId": str(case_id), "deleted": 0, "message": "未选择需要删除的截图"}
repo = ImageRepository(db)
images = await repo.list_by_ids_in_case(case_id, payload.image_ids)
if not images:
return {"caseId": str(case_id), "deleted": 0, "message": "未找到可删除的截图"}
from app.models.ocr_block import OcrBlock
from app.models.transaction import TransactionRecord
from app.models.assessment import FraudAssessment
deleted = 0
try:
for image in images:
# remove related OCR blocks and extracted transactions first
# assessments reference transaction_records.transaction_id, so they
# must be deleted before deleting transaction records.
await db.execute(
delete(FraudAssessment).where(
FraudAssessment.transaction_id.in_(
select(TransactionRecord.id).where(
TransactionRecord.evidence_image_id == image.id
)
)
)
)
await db.execute(delete(OcrBlock).where(OcrBlock.image_id == image.id))
await db.execute(delete(TransactionRecord).where(TransactionRecord.evidence_image_id == image.id))
await repo.delete(image)
deleted += 1
# best-effort remove local files
for rel in [image.file_path, image.thumb_path]:
if rel:
try:
p = settings.upload_path / rel
if p.exists():
p.unlink()
except Exception:
pass
case.image_count = await repo.count_by_case(case_id)
await db.flush()
await db.commit()
except Exception as e:
await db.rollback()
raise
return {
"caseId": str(case_id),
"deleted": deleted,
"message": f"已删除 {deleted} 张截图",
}

View File

@@ -38,3 +38,7 @@ class OcrFieldCorrection(CamelModel):
class CaseOcrStartIn(CamelModel):
include_done: bool = False
image_ids: list[UUID] = []
class CaseImagesDeleteIn(CamelModel):
image_ids: list[UUID] = []