# Python → Java 报告解析迁移计划 ## 背景 菌群报告和 DAN 测评报告的 Python 解析脚本(`docs/参考资料/`)是离线数据预处理工具。Java 运行时(`cfc-backend/`)已有部分实现但覆盖不全。 ## 现状 | 解析器 | Java 现状 | Python 覆盖 | 差距 | |--------|----------|------------|------| | 菌群报告 `PdfParseService` | ✅ 868行,PDFBox,完整 | `extract_full_report_v5.py` 1393行 | 持平,Java 已可用于生产 | | DAN A2 (mind) | ✅ 已完成 | `extract_a2_data()` | 持平 | | DAN B4 (wisdom) | ✅ 已完成 | `extract_b4_data()` | 持平 | | DAN A1 儿童认知 | ❌ 未实现 | `extract_a1_data()` | **需移植** | | DAN B2 儿童行为 | ❌ 未实现 | `extract_b2_data()` | **需移植** | | DAN B3 学习能力 | ❌ 未实现 | `extract_b3_data()` | **需移植** | | DAN B5 青春期 | ❌ 未实现 | `extract_b5_data()`(含仪表盘图片分析) | **需移植** | | DAN B6 职业发展 | ❌ 未实现 | `extract_b6_data()` | **需移植** | | DAN C1 校园版 | ❌ 未实现 | `extract_c1_data()` | **需移植** | ## 总体策略 **菌群报告**:Java 已满足生产需求,不做变动。Python 脚本保留为离线参考。 **DAN 报告**:分3波迁移。每波包含:解析逻辑 → 新增 Controller 端点 → 测试验证。 --- ## Wave 1 — 基础类型(A1 + B3) **目标**:纯文本正则提取,无图片分析,约 140 行 Python → Java ### A1 儿童核心认知发展 Python: `extract_a1_data()` ~43 行 - 6 个认知维度:感知觉、注意力、记忆力、推理能力、空间能力、加工速度 - 提取逻辑:正则匹配 3 种 PDF 格式(summary 页百分位、detail 页得分+百分位、fallback) - 输出格式:`{维度名_pct, 维度名_score}` **Java 实现方案**: - 在 `DanReportParseService` 中新增 `parseA1Report(List lines, String fullText)` 方法 - 复用现有的 `DataItem` 和 `DanParsedReport` 结构 - 维度映射到 `dan_assessment_results` 表的 `attention_score`, `memory_score`, `perception_score`, `spatial_score`, `processing_speed_score`, `logic_score` 字段 - 新增 `dimension="cognition"` 路由分支(`parseText()` 中) ### B3 核心学习能力 Python: `extract_b3_data()` ~74 行 - 3 大模块:执行功能(认知灵活性/抑制控制/元认知)、学习动机(内在/外在)、学习策略(深层/表面) - 提取逻辑:章节分割 + 正则匹配分数 **Java 实现方案**: - 新增 `parseB3Report()` 方法 - 复用 `findSectionStart()` + `parseScorePairs()` 模式 - 新增 `dimension="learning"` 路由分支 ### Wave 1 改动范围 ``` DanReportParseService.java ├── parseText(): 新增 "cognition" / "learning" 路由 ├── parseA1Report() ← 新增,~60 行 ├── parseB3Report() ← 新增,~80 行 ├── parseScorePairs() ← 新增辅助方法,复用正则 └── DataItem / DanParsedReport 结构不变 DanAssessmentController.java ├── parsePreview(): 放开 dimension 校验(当前只允许 mind/wisdom) └── dimension 映射表: cognition→A1, learning→B3 schema.sql / DatabaseInitializer └── 无需新增表(dan_assessment_results 已有 JSON 字段 structured_analysis) ``` --- ## Wave 2 — 中等复杂度(B2 + B6 + C1) ### B2 儿童自我与家庭教养 Python: `extract_b2_data()` ~74 行 - 自我概念 6 维 + 儿童行为 8 维 + 家庭环境 10 维 - 提取逻辑:章节定位 + 正则匹配 **Java 实现方案**: - 新增 `parseB2Report()` 方法 - 复用 `parseSelfConcept()`(已存在于 B4 解析中) - 新增行为、家庭环境的提取方法 - 新增 `dimension="behavior"` 路由 ### B6 职业发展 Python: `extract_b6_data()` ~77 行 - Holland 兴趣 6 型(RIASEC)+ 多元智能 8 维 + 职业价值观 - 提取逻辑:表格文本正则匹配 **Java 实现方案**: - 新增 `parseB6Report()` 方法 - 新增 `dimension="career"` 路由 ### C1 校园版 Python: `extract_c1_data()` ~91 行 - 认知 6 维(同 A1)+ 大五人格 5 维(同 A2)+ 自驱力 3 维 + 自我概念 6 维 - 提取逻辑:复用 A1 和 A2 的维度提取 **Java 实现方案**: - 新增 `parseC1Report()` 方法 - 复用 `parseA1Report()` 的认知维度提取 + A2 的大五人格提取 - 新增 `dimension="campus"` 路由 ### Wave 2 改动范围 ``` DanReportParseService.java ├── parseText(): 新增 "behavior"/"career"/"campus" 路由 ├── parseB2Report() ← 新增,~80 行 ├── parseB6Report() ← 新增,~80 行 ├── parseC1Report() ← 新增,~60 行(复用现有方法) ├── parseFamilyEnvironment() ← 新增辅助方法 ├── parseHollandInterest() ← 新增辅助方法 └── parseMultipleIntelligence() ← 新增辅助方法 DanAssessmentController.java └── 路由映射扩展 schema.sql / DatabaseInitializer └── 无需新增表 ``` --- ## Wave 3 — 高复杂度(B5 青春期 + B4 增强) ### B5 青春期挑战 Python: `extract_b5_data()` + 罗盘仪表盘图片分析 ~150 行 - 情绪调节 2 维 + 学业压力 5 维 + 人际关系 4 维 + 社交 5 维 + 睡眠/运动/网络 - 特殊:B5 报告含 **指南针仪表盘图像**,Python 用 PyMuPDF 提取 PNG + 像素分析 **Java 实现方案**: - **文本部分**:新增 `parseB5Report()`,正则提取各维度分数,这覆盖 80% 的数据 - **图像部分**(指南针仪表盘): 1. 用 PDFBox 提取页面图像 `PDImageXObject` 2. 用 Java `BufferedImage` 做像素颜色分析(替代 Python 的 PIL 角度测量) 3. 或:降级方案——跳过图像分析,仅从文本提取可读分数(文本已包含主要维度的数字评分) - 新增 `dimension="adolescent"` 路由 **谨慎意见**:B5 指南针仪表盘是 PNG 嵌入图像,PDFBox 可以提取,但像素级别的指针角度分析在 Java 中更啰嗦(需用 `BufferedImage.getRGB()` 手动实现)。可以考虑: - 方案 A:纯 Java 实现完整图像分析(2-3 天工作量) - 方案 B:跳过图像分析,从文本提取所有维度分数(文本里已有 80% 的数据),1 天内完成 - 建议:**先做方案 B**,文本提取覆盖核心数据,图像部分延后 ### Wave 3 改动范围 ``` DanReportParseService.java ├── parseText(): 新增 "adolescent" 路由 ├── parseB5Report() ← 新增,~120 行(文本部分) ├── parseB5CompassImage() ← 可选,降级优先 └── extractImageFromPDF() ← 新增辅助(PDFBox→BufferedImage) DanAssessmentController.java └── 路由映射扩展 + 处理 B5 图片分析结果 schema.sql / DatabaseInitializer └── 无需新增表 ``` --- ## 测试策略 每波完成后验证: ``` cfc-backend/src/test/java/.../DanReportParseServiceTest.java ├── testParseA1Report() — 用真实 A1 PDF 测试 6 维度提取 ├── testParseB3Report() — 用真实 B3 PDF 测试 ├── testParseA2Report() — 已有,确认回归 ├── testParseB4Report() — 已有,确认回归 ├── testParseB2Report() — Wave 2 ├── testParseB6Report() — Wave 2 ├── testParseC1Report() — Wave 2 └── testParseB5Report() — Wave 3 HealthReportControllerTest.java └── testUploadGutFloraReport() — 回归确认菌群报告不受影响 ``` **测试用 PDF**:`docs/参考资料/dan_reports/` 下已有各类型真实 PDF 样本。 **验证命令**: ```bash cd cfc-backend && mvn clean compile test -Dtest=DanReportParseServiceTest ``` --- ## 不会改动的内容 - 菌群报告的 Python `extract_full_report_v5.py`:保留为离线参考 - DAN Python 脚本集合 `dan_reports/`:完整保留,不删除 - `PdfParseService.java`:不做任何改动 - `HealthReportController.java`:不做任何改动 - DB schema:**不需要新增表**,`dan_assessment_results.structured_analysis`(JSON 字段)已支持所有 DAN 报告类型的结构化数据存储 ## 总工作量估算 | Wave | 新增 Java 行数 | 类型数 | 复杂度 | 估计工时 | |------|---------------|--------|--------|---------| | Wave 1 (A1+B3) | ~140 | 2 | 低 | 1-2 天 | | Wave 2 (B2+B6+C1) | ~220 | 3 | 中 | 2-3 天 | | Wave 3 (B5) | ~150 | 1 | 高 | 1-2 天(文本)/ +2天(图像) | | **合计** | **~510** | **6** | — | **4-7 天** | --- ## 变更风险矩阵 | Risk | 影响 | 缓解措施 | |------|------|---------| | Python 正则与 PDF 实际格式强耦合,不同 PDF 版本格式不同 | 提取失败/漏数据 | 测试覆盖多种 PDF 样本;Java 中用多模式回退(Python 已有多模式模式,直接移植) | | PDFBox 文本提取顺序和 PyMuPDF 不同 | 正则不匹配 | `parseText()` 中增加行合并预处理;对比 5+ 份 PDF 输出 | | B5 图片分析在 PDFBox 中比 PyMuPDF 更复杂 | 开发成本翻倍 | Wave 3 先做文本部分,图片分析延后独立 | | `DanAssessmentController` 现有接口调用方依赖 `mind`/`wisdom` | 前端不兼容 | 向后兼容:老 dimension 值保持可用,新值只影响解析路径 |