架构与实现
卓安Claw 案卷文件 V1 补齐 v1.0
日期:2026-11-13
状态:旧文书回填、删除清理、PDF 页级 OCR 已落地;OCR 默认关闭
关联:卓安Claw-数据存储与处理架构-v1.0.md、ADR-004-数据先存后处理.md
0. 一句话
V1 不只是“能上传”:旧文书要能补进原件层,删除要能把版本/FTS/解析产物/无引用原件一起清掉,扫描件要能按页 OCR,而不是把整份 PDF 当一张图。
1. 旧文书回填
触发
POST /api/zhuoan/documents/backfill(仅管理者):
{"case_id": "可选,按案件回填", "limit": 200, "enqueue": true}
案件材料卡片右上角「回填旧文书」:只对当前案件执行,结果弹窗显示成功/跳过数。
逻辑
- 查
document表中没有zhuoan_doc_version的文书(可按案件过滤,单次最多 1000)。 - 解析
file_path:绝对路径 →JIFENG_DATA_DIR相对路径 → 当前工作目录 → 用户目录。 - 文件存在且 ≤1.5GB:流式 SHA-256,写
zhuoan_doc_blob(内容寻址)。 - 建
zhuoan_doc_version:source='backfill',版本号沿用document.version。 - 写事件
backfilled,按需入解析队列。 - 返回
total / backfilled / skipped / errors / items;找不到文件的跳过并给原因。
幂等:已有版本行的文书不再回填;同一 blob 可被多份文书共享。
边界
- 不扫描磁盘找文件,只看
document.file_path;路径失效就跳过。 - 不回填
document缺失但磁盘上存在的散落文件。 - 回填会复制原件到 blob 存储(内容寻址),不移动/删除原文件。
2. 删除清理
触发
- 现有案管删除接口
DELETE /api/casemgr/documents/<id>。 - 删除前调用
purge_document,再删上游document行。
清理范围
zhuoan_doc_fts:按document_id删该文书的全部页索引。zhuoan_doc_version:删该文书的版本映射。- 对每个不再被其他文书引用的 blob:
- 删 FTS(按 blob 兜底)、
zhuoan_doc_artifact、zhuoan_ingest_job、zhuoan_doc_blob。 -legal_hold=1的原件不删,保留 blob 行。 - 删除 blob 磁盘文件(remove_blob=True)。 - 写
purged事件;共享 blob 只解引用,不删文件。
边界
- 不是回收站:删除即清理,没有恢复。
- 没有删除审批/双人复核;正式版应加删除申请与留痕。
- 不清理知识库/任务/预约中对文书的引用;后续需做引用检查。
3. PDF 页级 OCR
开关:ZHUOAN_DOC_OCR=1(默认关闭)。
逻辑
- 先走 pypdf;无文本时用 PyMuPDF 文本层兜底。
- 若开启 OCR:
- 整份无文本:OCR 前 20 页,按
page_texts重建页码。 - 混合 PDF:只挑“文本为空”的页,按页码送common.ocr.ocr_file(page_numbers=...),最多 50 页。 - OCR 结果按页合并,非空页保持原文;引擎标记pypdf+ocr或ocr。 - 图片文件仍走单页 OCR。
- FTS 索引按页写入,引用卡仍能定位页码。
边界
- OCR 依赖 RapidOCR/PyMuPDF;未安装时记录日志并回退到“未提取到文本”,不会伪造内容。
- 超过 50 页的扫描件只 OCR 前 50 页;后续需分批任务。
- OCR 结果没有人工校对标记;正式版应加“机器识别/律师校对”状态。
- 默认关闭,避免演示机 CPU 被大 PDF 拖死;演示需要时再开。
4. 验证
用临时文书 回填测试文书.txt 指向 C:\tmp\zhuoan-backfill-test.txt:
POST /documents/backfill:total=1 / backfilled=1 / skipped=0。- 解析:
ingest_status=ready、page_count=1、SHA-256 写入。 - 检索:
documents/search?q=回填测试唯一词命中第 1 页,snippet 正确。 - 删除
DELETE /api/casemgr/documents/<id>:200;document / version / blob / artifact / FTS计数均为 0;blob 磁盘文件已删除。 - Playwright:管理者可见「回填旧文书」,承办律师不可见;0 console error。
- OCR 关闭路径单测:空页保持原样,不触发 OCR。
5. 未做
- 删除审批/回收站/恢复。
- 跨表引用检查(知识、任务、预约、Agent 引用)。
- 全量 OCR 队列、OCR 进度、人工校对。
- 旧文书路径失效的批量修复/重新挂载。
- 原件去重 GC(目前按引用删除,未做全库 GC 巡检)。
6. 下一步
- 删除审批:申请→复核→软删→保留期→物理清理。
- 回填任务化:大案件后台分批回填,页面看进度与失败清单。
- OCR 任务化:按页入
zhuoan_ingest_job,可暂停/重试/只跑指定页。 - 文档引用检查:删除前提示被哪些知识/任务/预约引用。
- 存储巡检:孤儿 blob、缺失文件、哈希不一致的定期扫描。