|
|
@@ -0,0 +1,226 @@
|
|
|
+# 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<String> 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 值保持可用,新值只影响解析路径 |
|