You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

35 lines
2.8 KiB

2 days ago
# 04 · 嵌套 DTO 字段表展开(静态反射器递归化)
**Type:** task
**Status:** resolved
**Blocked by:** —
## Question
把静态反射器 `.scratch/a4-doc-fields/complete_a4_doc_fields.py`(逐行状态机,当前只展开一层)改造为**递归下钻嵌套类型**,写回 6 处引用文件,使嵌套 DTO 字段表展开到字段级。
**用户点名案例**:`客户详情\联系人图谱\图谱全量读.bru` 的 `nodes List<GraphNodeDTO>` / `edges List<GraphEdgeDTO>` 必须展开——GraphNodeDTO.java 已有 9 个 @Schema 字段(id/name/phone 脱敏/jobTitle/level/levelSource 等),GraphEdgeDTO.java 同样带注解,机械抽取即可。
**其余 4 处**:`List<CustomerSimilarHitDTO>`(查重命中明细,×4 文件)。
**展开形态**:子表形式(`nodes[].xxx` 点路径行)或独立小节子表,与 a4-doc-fields 既有字段表风格一致;深度上限 2 层(List<List<...>> 不存在,遇 Map/JSON 字符串退化为类型+说明)。源码缺 @Schema 的嵌套字段先补注解再抽取(与 a4-doc-fields 票 03 同纪律:源码是说明的单一真源)。
**产物**:改造后反射器 + 6 文件写回 + verify 对账(结构不被破坏,示例块不动——示例真值化归票 05)。
## Answer
**2026-09-11 resolved(范围随票 03 普查修正:6 → 26 文件)**
工具 `.scratch/customer-integration-ready/expand_nested.py`(v4):复用 a4-doc-fields 反射器内核,新增类声明切片解析 + 花括号配对 + 同文件优先消歧 + **泛型形参绑定**(`BatchResult<F>` + `List<F>``List<CustomerBatchFailItem>` 实参替换)。
落地 26 文件全写回(dry-run 抽查 → apply),覆盖 (c) 全部四种形态:
- DTO-zero(similarHits 零子行)×5 文件
- 图谱 nodes 8 子字段 / edges 2 子字段(用户点名案例)
- type-F(`List<F>` 占位类型)×12 文件:failures → `List<CustomerBatchFailItem>` + id/reason/message 子行
- DTO-flat(交接 details / 导入 rows 扁平悬挂)×6 文件:重建成 `content[].details[].xxx` 点路径
- partial(quickAdd/batchEdit failedRows)×2 文件
**踩坑记录**:①`Row`/`DetailRow` 等是静态嵌套类,全仓首见 class_index 会撞名(ImportPreviewDTO.Row vs ContactImportPreviewDTO.Row)且 parse_class_fields 不识别类边界致外层/内层字段合并——重写为按声明切片+同文件优先;②type_bodies 首版 `pos=c+1` 跳过外层花括号区间漏扫全部嵌套类;③page 形态须补 `content[].` 前缀;④rows 为空必须跳过写回(防清空表)。
**验证**:残留核查(排除标量类型)= 0;page 前缀抽查正确;缺 @Schema = 无(源码注解齐全,无需回写源码)。DetailRow 缺 createTime 行归票 06(SKIP_FIELDS 全局跳过 createTime 所致,非本票范围)。