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.
 
 
 
 
 

6.1 KiB

status
accepted

联系人图谱 demo 接真实 API(contact-graph 票 06)

Context

customer-contact-graph effort 票 06(spec §三/§七修订⑧):原型 demo(prototype-contact-graph.html)此前数据内联(mock 9 人 + 内置字典 + auto 边引擎),票 03/04/05 后端已落地(图谱/增强/导入三组端点 + 字典零新端点)。票面四条:①API 接线清单 + 修订⑧回写 ②mock→API 替换 ③导入 UI 三段式 ④验证(node --check + 静态路径对账 + 既有冒烟不回归;图谱交互 Playwright 归票 08)。

修订⑧(spec §七冻结)四条必须先回写 demo 再谈接线:①砍自动生成边引擎 ②公司边派生化(不可删、摘线=降级)③无否决/tombstone 交互 ④level 来源标记在页内编辑-职务变更联动上体现。

Considered Options

  • 数据层形态:mock/真机双轨开关 vs 单一 fetch 层(选中)——统一 API_BASE = URL ?api= 覆盖、apiGet/apiPost/apiDownload 单入口、Result 信封 {code,success,message,data} code==0 成功解析收敛在 apiEnvelope。双轨会留下两套数据语义(mock 修复不等于真机修复),票 06 的目的就是消灭 mock 死代码。
  • auto 边引擎:demo 保留模拟 vs 随修订⑧删除(选中)——autoParentsOf/rebuildAutoEdges/vetoed tombstone 全删;edges 收敛为纯手动边 {id:parent+'>'+child};公司边由 derivedCompanyEdges() 派生渲染(虚线浅蓝、无 ×、不入 save 快照)。保留模拟会让 demo 与 spec D6/D8 冻结口径分叉,验收者看到的规则面板与后端行为不一致。
  • 层级一致性清理:保留 auto 重建 + 清理 vs sanitizeManualEdges 单职责(选中)——层级变化(拖格子定级/职务变更联动)后只做「非法边清理」(父层级 ≤ 子层级的 committed/pending 边移除并记日志),不再生成任何边;非法边落库由 save 67018 兜底(后端口径:batchEdit 不动边)。
  • 自检策略:起真服 HTTP 冒烟 vs Playwright route 内存后端桩(选中)——pg.route('http://mock-api/**') 接管全部 /api/**,页址带 ?api=http://mock-api;桩实现 14 端点含状态变更(graph/save 版本 CAS、quickAdd 追加、batchEdit 四列联动 bump、导入三段式固定预检)。起服冒烟归票 07 E2E,本票自检只验证 demo 自身行为契约;桩把 method 语义钉住(template 必须 GET,否则 405)防止同类回归。
  • 二进制端点 method:apiDownload 一律 POST vs 按后端映射(选中)——import/template 后端是 @GetMapping(读操作),export@PostMapping;apiDownload 增加 method 参数(默认 POST),模板调用显式传 GET。静态对账时发现的原型 bug(实机 405),桩不校验 method 时 Playwright 冒烟暴露不了。
  • 页内编辑-职务变更(D1/D2 体现):jobFull option value 用类别 code vs 职务 code(选中)——option value = 职务字典 code(applyCellEditj.code === v 反查联动四列 + levelSource=1),提交 jobTitleCode 与后端契约一致;排查中发现 value 误写类别 code 导致联动静默失效,静态对账 + 冒烟步骤 8 双重暴露。
  • 脱敏回显提交口径:phone 一律 11 位校验 vs 含 * 放行(选中)——saveListAll 前端校验对脱敏回显形态(131****3272,loadGraph 重拉后的未修改值)放行提交,后端口径「脱敏形态回传=不改,明文=修改」;否则职务变更保存被脱敏回显误拦(冒烟实测暴露)。

Decision

  1. demo 数据层收敛为单一 fetch 层:API_BASE 从 URL ?api= 读(默认同源),loadDicts(job_title 两级树 + contact_source 启用项)/loadGraph(graph/detail 全量 → contacts/edges/graphVersion)/applyGraph 落地;JacksonConfig 全局 Long→String,demo 侧 id 统一 String() 防精度丢失。初始化 async init():字典+图谱加载失败 toast 提示 ?api= 用法。
  2. 修订⑧回写:auto 边引擎/否决交互全删;公司边派生视图渲染(edge-company class 虚线浅蓝、无 ×,.edge-del 仅渲染在手动边上);撤级检查豁免公司边(childEdges 过滤 child !== COMPANY_ID);tryConnect 无向 pair 查重覆盖 committed+pending;删手动边直接进 pendingDeletes(无确认弹窗);saveGraph 全量快照 POST(nodes 全员等级终态 + 手动边终态集),67017 冲突提示并 loadGraph 重拉重置基准。
  3. 导入三段式 modal(impStep1 模板+上传 / impStep2 预检表 / impStep3 结果轮询+失败明细),六端点中接线五端点(template/upload/confirm/result/failures;page 为列表侧分页不在 demo 范围);轮询 1s,status=2/3 终态停表并 loadGraph().then(renderAll)(导入 bump 后版本重拉)。
  4. 自检(selfcheck.py)改造:内存后端桩接管 14 端点 + 修订⑧断言适配(边计数口径 = 1 manual + 3 derived company 与原 4 auto 边数值巧合保持;收尾A 改为「无幽灵边自由降级」断言;步骤 8 断言 4 = 后端不动边拉回非法边;步骤 9 重写为公司边无 × + 手动边删免确认 + save 版本推进;新增步骤 11 导入三段式冒烟)——59 步全绿。

Consequences

  • demo 与后端单一事实源对齐:字典/节点/边/版本全部来自 API,mock 配置死代码清零;后续 UI 演进(票 08 Playwright 图谱交互)在同一 fetch 层上做,无需再碰数据层。
  • 桩与真机的剩余差异(登录态 cookie、数据权限、真实 xlsx 解析)由票 07 E2E 起服验证承接:三段式 HTTP 冒烟 + 票 02 enabled-list 断言 + 图谱 save CAS。
  • 静态路径对账结论:demo 14 端点 ↔ 后端四 Controller(Graph/Enhance/Contact/ContactImport)+ DictItem 映射全对齐,无幽灵路径;import/page demo 未接(列表分页后续票)。
  • 三个原型缺陷在冒烟/对账中暴露并修复(jobFull value 错绑类别 code、脱敏回显误拦保存、模板下载 method 405)——「桩把后端契约钉住」的自检形态在后续原型票复用。