Files
AIclinicalresearch/docs/03-业务模块/RVW-稿件审查系统/06-开发记录/务实版.md
HaHafeng f9ed0c2528 feat(rvw): Complete V2.0 Week 3 - Statistical validation extension and UX improvements
Week 3 Development Summary:

- Implement negative sign normalization (6 Unicode variants)

- Enhance T-test validation with smart sample size extraction

- Enhance SE triangle and CI-P consistency validation with subrow support

- Add precise sub-cell highlighting for P-values in multi-line cells

- Add frontend issue type Chinese translations (6 new types)

- Add file format tips for PDF/DOC uploads

Technical improvements:

- Add _clean_statistical_text() in extractor.py

- Add _safe_float() wrapper in validator.py

- Add ForensicsReport.tsx component

- Update ISSUE_TYPE_LABELS translations

Documentation:

- Add 2026-02-18 development record

- Update RVW module status (v5.1)

- Update system status (v5.2)

Status: Week 3 complete, ready for Week 4 testing
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-18 18:26:16 +08:00

149 lines
6.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# **RVW V2.0 表格提取疑难杂症专项解决方案 (v1.1 务实版)**
**问题焦点:** Word 表格“隐性多行”(单元格内多段落)导致的提取与验证错位 **核心策略:** **提取层保持原貌,验证层“懒分裂” (Lazy Split)** **技术栈:** Python (python-docx, pandas)
## **1\. 核心判断:技术选型定调**
| 维度 | 方案 A: 视觉模型 (VLM) | 方案 B: 结构重组 (预分裂) | 方案 C: 懒分裂 (推荐) |
| :---- | :---- | :---- | :---- |
| **原理** | 用 GPT-4V 截图识别 | 提取时把 Table 拆成 N 倍行 | **提取保持 \\n验证时 split** |
| **准确性** | 低 (幻觉/小数点风险) | 中 (容易破坏合并单元格结构) | **高 (数据无损,逻辑灵活)** |
| **复杂度** | 高 (GPU/Prompt) | 高 (重构 DataFrame 结构) | **低 (仅在 Validator 中处理)** |
| **前端适配** | 难 (无法定位) | 难 (需定制虚拟行渲染) | **易 (原生 HTML \<br\>)** |
**最终决策:**
1. **坚决不用视觉模型**:数值准确性是底线。
2. **放弃“预分裂”**不在提取阶段破坏表格的物理结构Row/Span避免引入元数据丢失风险。
3. **采用“懒分裂”**:在验证逻辑中,针对特定单元格内容进行 split('\\n'),实现细粒度验证。
## **2\. 提取层规范 (Extractor Layer)**
**目标**:忠实还原 Word 文档的物理结构,不自作聪明地拆行。
### **2.1 Python 实现逻辑**
在 DocxTableExtractor 中,对于单元格内的多段落,直接使用换行符 \\n 连接。
def extract\_cell\_text(cell):
"""
提取单元格文本,保留段落结构
"""
\# 过滤掉完全空白的段落,保留有内容的段落
paragraphs \= \[p.text.strip() for p in cell.paragraphs if p.text.strip()\]
return "\\n".join(paragraphs)
**输出数据结构示例 (JSON)**
{
"row\_index": 3,
"cells": \[
{ "text": "并发症\\n颅内出血\\n牙龈出血" }, // Col 0
{ "text": "277 (14.65)\\n85 (4.49)\\n94 (4.97)" }, // Col 1
{ "text": "χ²=5.687\\nχ²=0.003\\nχ²=13.745" }, // Col 3 (统计值)
{ "text": "0.017\\n0.01\\n\<0.001" } // Col 4 (P值)
\]
}
## **3\. 验证层规范 (Validator Layer)**
**核心逻辑:** 验证器在读取数据时,动态检测是否存在多行内容。如果存在,则在内存中“临时分裂”并逐一验证。
### **3.1 懒分裂验证算法 (Lazy Verification Logic)**
def verify\_row\_statistics(row\_data, col\_map):
"""
验证单行数据的统计逻辑(支持隐性多行)
"""
issues \= \[\]
\# 1\. 获取目标单元格的原始文本
\# 假设我们要验证 Col 1 (Group A) vs Col 2 (Group B) \-\> P Value
cell\_a\_text \= row\_data\[col\_map\['group\_a'\]\]
cell\_b\_text \= row\_data\[col\_map\['group\_b'\]\]
cell\_p\_text \= row\_data\[col\_map\['p\_value'\]\]
\# 2\. 懒分裂 (Lazy Split)
lines\_a \= cell\_a\_text.split('\\n')
lines\_b \= cell\_b\_text.split('\\n')
lines\_p \= cell\_p\_text.split('\\n')
\# 3\. 确定对齐基准(取最大行数)
max\_lines \= max(len(lines\_a), len(lines\_b), len(lines\_p))
\# 4\. 逐行验证 (Line-by-Line Validation)
for i in range(max\_lines):
\# 安全获取当前行的数据(处理长度不一致情况)
val\_a \= lines\_a\[i\] if i \< len(lines\_a) else ""
val\_b \= lines\_b\[i\] if i \< len(lines\_b) else ""
\# P 值匹配策略:
\# 如果 P 值列只有 1 行,但数据有 N 行 \-\> 广播机制 (Broadcast)
\# 如果 P 值列有 N 行 \-\> 一一对应 (One-to-One)
if len(lines\_p) \== 1 and max\_lines \> 1:
val\_p \= lines\_p\[0\] \# 策略 A: 共享 P 值
else:
val\_p \= lines\_p\[i\] if i \< len(lines\_p) else "" \# 策略 B: 独立 P 值
\# 跳过空行
if not val\_a or not val\_b or not val\_p:
continue
\# 执行具体的统计验证
\# 传入 line\_index=i 以便报错时定位
error \= validate\_single\_line(val\_a, val\_b, val\_p, line\_index=i)
if error:
issues.append(error)
return issues
### **3.2 优势分析**
1. **兼容性强**:完美支持您截图中的 颅内出血 | 85 | 90 | P=0.01 这种每行独立 P 值的场景。
2. **鲁棒性**:如果只有第一行有 P 值(合并单元格视觉效果),代码中的 Broadcast 逻辑也能兜底。
3. **定位精准**:报错信息可以包含 line\_index告诉前端是单元格里的第几行出错了。
## **4\. 前端渲染规范 (Frontend Layer)**
**目标**:使用最简单的 Web 技术还原 Word 样式,避免过度设计。
### **4.1 HTML 渲染策略**
后端返回的 html 字段中,直接将 \\n 替换为 \<br\>。
**Python 端处理:**
def generate\_html\_cell(text):
\# 转义 HTML 特殊字符,并将换行转为 \<br\>
safe\_text \= html.escape(text)
return safe\_text.replace("\\n", "\<br\>")
**前端展示效果:**
\<td\>
277 (14.65)\<br\>
85 (4.49)\<br\>
94 (4.97)
\</td\>
### **4.2 错误高亮策略**
由于我们不再拆分表格行DOM 结构),高亮的最小单位是 **Cell单元格**
* **交互设计**
* 当发现第 2 行子数据错误时,**高亮整个单元格**。
* **Tooltip 提示**:鼠标悬停时,显示具体错误信息:“第 2 行数据 P 值校验不通过”。
* **进阶优化V2.1 可选)**
* 如果确实需要高亮某一行Python 生成 HTML 时可以用 \<span\> 包裹每一行: \<span id="r3c2\_L0"\>277 (14.65)\</span\>\<br\>\<span id="r3c2\_L1"\>85 (4.49)\</span\>
* 但 MVP 阶段建议**只高亮单元格**,性价比最高。
## **5\. 总结**
| 模块 | 核心动作 | 复杂度 |
| :---- | :---- | :---- |
| **Python 提取** | 保持 \\n不拆行输出标准 JSON | ⭐ (低) |
| **Python 验证** | split('\\n'),循环对齐,独立计算 | ⭐⭐ (中) |
| **前端渲染** | 使用 \<br\> 换行CSS 控制对齐 | ⭐ (低) |
| **前端高亮** | 高亮整个单元格Tooltip 说明行号 | ⭐ (低) |
**这是目前最务实、风险最低的实施路径。** 请开发团队以此为准。