25-backend-contract-gaps.md 25 KB

25: 后端契约缺口待办(跨领域两项 + 补契约清单)

Status: ready-for-human Labels: ready-for-human Category: enhancement Blocked by: None

不阻塞 23 张实现票的 mock 阶段;阻塞的是这些票接真实接口。

This was generated by AI during triage.

Why ready-for-human

结论来自 24: 面板字段与后端契约覆盖调研(已 resolved)、2026-09-17 两轮对后端仓库的复核,以及主会话的逐条核实。缺口分两类:

  1. 后端补契约——需要后端负责人实现。本仓库工作区写权限只覆盖 E:\City-Lifeline-Cockpit-TvT,且后端仓库当时有并行会话的在途改动,不适合由本票直接改。
  2. 业务定义确认——需要业务方回答,本票不发明结论。

可直接交付给后端项目经理的建票草案已单独产出:后端契约缺口交付包。

复核记录(2026-09-18 第八轮:BT-5 第 1 片落地,票未关)

BT-5(Gogs #63)按人类裁定走「纵向样板」:完成 map-snapshot 一片的真实数据接线,余 21 片未动,票保持 open(约 5%)。

  • 裁定:本轮范围=map-snapshot 纵向样板(不追求 22 片全接);井盖口径「以数据库为准」。
  • 落地:新增 BusinessCockpitMapSnapshotAdapter(@Primary),组合 monitor_point / equipment_point_rel / equipment_status / early_warning / work_order / equipment_type 六张既有表与服务,不新增表、不加投影,复用 BT-1…BT-4 已冻结的服务层(过滤/分页/mapFilter/坐标校验均不改)。
  • 真实库证据(只读,KingBase 192.168.110.30:54321/pipi_ner):接线后产出 7 个真实点位(2 个带设备)、3 条有效设备关联、34 台未关联设备、5 台报警、1 台离线 —— 非空且与库一致。
  • 测试:新增 BusinessCockpitMapSnapshotAdapterTest 4 例;全量 mvn -pl zksy-admin -am test 465 测试 0 失败。
  • 实测出的真实数据缺口(阻塞后续切片,已全部写进 #63):
    1. 设备→点位关联极稀疏(仅 3 条有效,覆盖 2/7 点位)→ BT-1 的 deviceCodes/WS monitoringPointCode 在真实数据下近乎全空(数据缺口,非代码缺陷);
    2. 现网无坐标校核字段 → 按冻结字典一律 renderable=false(不上图),要上图需数据侧补标志或裁定「默认已校核」;
    3. monitor_point 无行业列,点位类型只能在关联设备类型唯一时推导;
    4. 点位状态/类型中英文脏值(正常/预警 vs ACTIVE);
    5. 工单状态值域跨端不一致:现网 0-based、cockpit 冻结 1-based;
    6. 窨井(井盖)缺契约位:库里有独立 manhole_base(3 条)/manhole_device_rel(6 条)与 manhole 类型根,前端筛选也有「井盖」项,但后端正式行业枚举只有 3 个;
    7. 窨井坐标脏(1212,1212)。

wayfinder 记法:同前几轮——本票属后端 Gogs tracker,不挂在任何 wayfinder map 之下,故 gist 记在本票(其父台账)。

复核记录(2026-09-18 第七轮:BT-4 已交付)

BT-4(Gogs #62)事件行补坐标校验与报警阈值完成并关闭:

  • 落地:events/current 的 EventItem 增加 coordinateValidation(state/reason/renderable/crs)与 thresholdMinValue/thresholdMaxValue(报警族在数据可得时有值,预警族 null);快照源补 coordinateVerified(报警族另补阈值)。校验复用 CockpitCoordinateValidator,与地图/分布/态势同一实现。
  • 不臆造验证:适配器未给 coordinateVerified 时按未验证处理(UNVERIFIED + renderable=false),符合字典「未验证禁止渲染」;接线后按真实标志放行。
  • 适用面:events/history-analysis 的行是小时桶聚合、无逐事件行,不适用该字段(与 BT-1 的结论一致)。
  • 入册:README 第 4 节三条口径 + current-warnings-demo.html 增「上图」列(标记只画 renderable=true 的事件)。
  • 证据:CockpitCurrentEventsControllerTest 14 例(含 INVALID/LONGITUDE_OUT_OF_RANGE、UNVERIFIED/UNVERIFIED_COORDINATE、报警阈值断言);全量 mvn -pl zksy-admin -am test 453 测试 0 失败。
  • 口径说明:本票与 BT-5 不在「11 判定项 + 3 业务问题」的计分口径内,故进度仍记 79%;但它们同属交付包里的后端缺口,BT-1…BT-4 现已全部交付,只剩 BT-5(真实数据接线)与 3 条业务口径问题。

wayfinder 记法:同前几轮——本票属后端 Gogs tracker,不挂在任何 wayfinder map 之下,故 gist 记在本票(其父台账)。

复核记录(2026-09-18 第六轮:BT-3 已交付,B 关闭——11 个契约判定项全部达成)

BT-3(Gogs #61)趋势窗口可声明完成并关闭:

  • 落地:GET /overview/warning-settings 增加 range(LAST_24_HOURS/LAST_7_DAYS/LAST_30_DAYS,同 infrastructure/operating-information)与 startTime/endTime(显式 ISO 区间,成对且 startTime ≤ endTime);range{type,start,end} 回显生效区间(显式区间 type=CUSTOM,不声明时维持 CURRENT_BASELINE + null);trend[] 按窗口过滤(桶为业务时区日期,含端点,顺序沿用适配器)。
  • 错误口径:非法 range、单边区间、startTime > endTime、时间戳不可解析 → 400 INVALID_REQUEST,文案与兄弟切片一致。
  • 入册:docs/cockpit/README.md 第 3 节端点参数 + 第 4 节新增「时间范围口径」。
  • 证据:CockpitOverviewWarningSettingsControllerTest 9 例 + ServiceTest 3 例;全量 mvn -pl zksy-admin -am test 453 测试 0 失败。
  • 本轮据此更新:判定项 B ⚠️→✅。至此 11 个契约判定项(A、B、C、D、E、F、G1、G2、G3、G4、H)全部交付;剩余只有 BT-4(#62 事件坐标校验)、BT-5(#63 真实数据接线)与 3 条业务口径问题。

wayfinder 记法:同前两轮——本票属后端 Gogs tracker,不挂在任何 wayfinder map 之下,故 gist 记在本票(其父台账)。

复核记录(2026-09-18 第五轮:BT-2 已裁定并交付,G1+G2 关闭)

BT-2(Gogs #60)路径裁定 + 落地完成并关闭:

  • 裁定:走路径①完整——地图取数以 map-snapshot 为准(不用 monitoring/distribution 供数),map-snapshot 承接全局筛选。理由:前端全局条件是「范围(scope) + 行业」两维,只加 industry 会让范围对地图无效;且票 08 的装载器已按 map-snapshot 的扁平分页形状验收关闭。
  • 落地:map-snapshot 增加 industry/region/deviceType 三个入参;逐点补 region/industry/typeCode/typeName(未关联设备同样补);响应新增 mapFilter{industry,region,deviceType,pointCodes,deviceCodes} 回显生效范围;coordinateValidation 汇总改为「筛选范围内全量口径」;默认不筛时不排除任何对象(行业不可推导为 null)。
  • 入册:结论写入 docs/cockpit/README.md 第 3 节「地图筛选路径(冻结结论)」(票面验收第 1 条)。
  • 证据:CockpitMapSnapshotControllerTest 14 例(含筛选、回显、非法行业 400、带筛选翻页快照锁);全量 mvn -pl zksy-admin -am test 450 测试 0 失败。
  • 本轮据此更新:判定项 G1 ❌→✅、G2 ❌→✅;AC1 达成。至此契约判定项只剩 B 一处(overview/warning-settings 趋势窗口,Gogs #61),另有 BT-4(#62 事件坐标校验)与 BT-5(#63 真实数据接线)。

wayfinder 记法:同第四轮——本票属后端 Gogs tracker,不挂在任何 wayfinder map 之下,故 gist 记在本票(其父台账)。

复核记录(2026-09-18 第四轮:BT-1 已交付并关闭)

BT-1(Gogs #59)实施完成并关闭——设备→点位回联三件套全部落地:

  • ① REST:CockpitMonitoringPointSummary 新增 deviceCodes(从 SourceMonitoringPoint.devices 投影,保序去重),map-snapshot 点位摘要现在能回联设备。
  • ② WS:四个增量 DTO 新增 monitoringPointCode;DeviceStatusRedisListener 按 equipment_base.equipment_code → equipment_point_rel → monitor_point.point_code 解析,未关联显式 null(帧序列化 WriteMapNullValue),查询异常降级不阻断推送。
  • ③ 事件行:EventItem 新增 monitoringPointCode/monitoringPointName(快照源与 EventRow 同步补字段)。history-analysis 的 row 是小时桶聚合行,无逐事件行,不适用该字段。
  • 证据:mvn -pl zksy-admin -am test(全量 zksy-admin 与 zksy-system)445 个测试 0 失败(含 REST 契约与 WS 增量两侧新增断言)。
  • 本轮据此更新:判定项 G4 由 ❌ 转为 ✅;AC2 的候选 ①②③ 全部实现,结论达成。

wayfinder 记法:本票属后端 Gogs tracker,不挂在任何 wayfinder map 之下(后端仓库无 map.md),故 gist 记在本票(其父台账)而非某张 map 的「Decisions so far」。

复核记录(2026-09-18 第三轮:建票完成)

承接第二轮结论,重新只读复核后端(HEAD 仍 ed0ace5、远端仍 e2b4e45,G1/G2/G4/BT-3/BT-4 证据逐条复验成立),并把交付包草案在 Gogs 建成真实工单:

BT Gogs 票号 标题 标签
BT-1 #59 BT-1 Cockpit device-to-point linkage(REST + WebSocket) needs-triage
BT-2 #60 BT-2 全局行业筛选落图:路径裁定 + 落地 needs-triage
BT-3 #61 BT-3 warning-settings 趋势窗口可声明 needs-triage
BT-4 #62 BT-4 事件行补 coordinateValidation 与报警阈值 needs-triage
BT-5 #63 BT-5 真实数据接线(程序级) needs-triage
  • 每张票正文 = 交付包对应小节 + 一行来源说明(前端 tracker 票 25 / handoff/backend-contract-gaps.md)。
  • 标签统一 needs-triage:这些票都含待后端负责人裁定的点(BT-2 路径二选一、BT-1 ①②③、BT-5 排期),应由后端 PM 评估后转 ready-for-agent。
  • BT-6(situation 的 monitoringState 过滤)按草案标注为可选,未建。
  • 本轮两处事实修正:①「06(全局筛选)」错引改为 18(票 18 验收项「面板筛选可作用于地图点位」,filterStore 已在票 01 落地);② 适配器计数改为精确口径(23 接口 / 22 空实现 / 1 真实,不计 /foundation 自检则 22/21)。
  • 本票与交付包均已同步上述修正。

复核记录(2026-09-17 第二轮,替代同日第一轮)

第一轮复核时后端 HEAD 为 #36、#37 未提交,当时判定「8 组补契约中 4 组已交付」。同日后端又落地 #37–#43,第二轮结论大幅前移:11 个契约判定项中 7 项已交付,1 项只剩一处,3 项未交付。

复核方式:只读阅读后端仓库 E:\pipe-ner-server 的控制器、响应类、适配器与 docs/cockpit/README.md;未改动后端任何文件,未跑构建或调试命令。

  • 后端本地 HEAD:ed0ace5(test(cockpit): add contract integration environment and handoff (#43))。
  • 远端 origin HEAD 仍是 e2b4e45(#42)——#43 未推送,联调前需确认部署来源提交。

第二轮逐项判定

项 内容 状态 证据
A 跨设备事件读模型(当前 + 历史) ✅ 已交付 GET /events/current(mode 必填并校验,level/industry/status/分页)与 GET /events/history-analysis(eventFamily 必填并校验 + startTime/endTime);EventItem 含 eventNo/eventType/level/levelColor/status/eventTime/value/unit/deviceCode/deviceName/location/industry/longitude/latitude/workOrderSummary;历史侧回显 Range{type,startTime,endTime}。残留 monitoringPointCode 与 coordinateValidation(分别见 G4、BT-4)
B 趋势时间范围可声明 ✅ 已交付(2026-09-18,Gogs #61) overview/warning-settings 增加 range 三档 + startTime/endTime,回显 range{type,start,end},趋势桶按窗口过滤;其余切片早已支持范围参数
C 响应/关闭时长聚合 ✅ 已交付 GET /events/handling-efficiency:averageDuration{value,unit,sampleCount,state,reason} + durationTrend[] + 工单 durationHours;口径冻结为 basis = CLOSED_WORK_ORDERS_OVER_TOTAL_EVENTS
D 应急保障域三件套 ✅ 已交付 GET /infrastructure/emergency-support:Totals{emergencyResourceCount,hazardSourceCount,protectionTargetCount} + 三 section + eventSummary
E 管理信息域 ✅ 已交付 GET /infrastructure/management-information:organizations + ownershipDistribution + unmaintained
F 设施/行业运行信息 ✅ 已交付 GET /infrastructure/operating-information:metrics + capacityValue/loadRatio/loadState + trend + range/from/to
G1 全局行业筛选落到地图点位 ✅ 已交付(2026-09-18,Gogs #60) 裁定走路径①:map-snapshot 增加 industry/region/deviceType 入参,服务端过滤 + mapFilter 回显生效范围;分页与 snapshotAt 语义不变;结论冻结在 docs/cockpit/README.md 第 3 节
G2 点位摘要补 industry、类型、徽标 ✅ 已交付(2026-09-18,Gogs #60) CockpitMonitoringPointSummary 补 region/industry/typeCode/typeName;徽标所需的设备数由 BT-1 的 deviceCodes 直接得出
G3 未关联设备补 industry、设备类型 ✅ 已交付 CockpitMonitoringDistributionResponse.UnassociatedEquipmentMarker
G4 设备编码回联点位 ✅ 已交付(2026-09-18,Gogs #59) 点位摘要 deviceCodes + 四个 WS 增量 DTO 的 monitoringPointCode(真实库映射查询,未关联显式 null)+ 事件行 monitoringPointCode/monitoringPointName;REST 与 WS 契约测试两侧覆盖
H 跨设备设备状态清单 ✅ 已交付 GET /monitoring/situation:abnormalEquipment[]{deviceCode,deviceName,deviceType,industry,region,abnormalType,status,statusReasons,longitude,latitude,coordinateValidation} + 分页 + mapFilter.deviceCodes

已交付但仍需注意的两条事实

  1. #43 交付了一份移交与联调手册:E:\pipe-ner-server\docs\cockpit\README.md(契约总则、字典冻结、端点清单、分页/快照/错误口径、WebSocket 增量、启动与联调检查表、容器化评估、已知未验证项)。票 25 里「字段名与语义」类问题已由它回答,不必再建票。
  2. 契约已冻结,真实数据未接线:23 个 cockpit 适配器接口中 22 个只装配了 Empty*Adapter(返回 ...Snapshot.empty(...)),唯一接入真实数据的是 BusinessCockpitWorkOrderReadAdapter(工单,@Primary 覆盖同名 Empty 实现)。前端切到真实接口会拿到全空快照(200 + freshness.state = EMPTY)。这是当前最大的交付差距,已作为 BT-5 写入交付包。(口径:若不计 /foundation 契约自检,则为 22 个读模型接口 / 21 个空实现。)

G1 全局行业筛选落不到地图点位(2026-09-18 已由 Gogs #60 交付:路径①完整)

CONTEXT.md 定义行业筛选是作用于整个驾驶舱的全局条件,但 map-snapshot 至今无法过滤地图点位:

  • GET /api/cockpit/v1/map-snapshot 无 industry 入参(CockpitMapSnapshotController)。
  • CockpitMonitoringPointSummary 没有 industry 与点位类型,服务端与客户端都无从过滤。
  • 对照:overview/monitoring、infrastructure/base-archives、monitoring/overview、monitoring/distribution 都已支持 industry 入参。

需要后端定路径(二选一或都做):① map-snapshot 增加 industry 入参,CockpitMonitoringPointSummary 增加 industry 与点位类型字段;② 正式声明地图筛选以 /monitoring/distribution 为准——它已有 industry/deviceType/pointStatus/region 入参与逐点 industry/deviceType,但需在契约手册写明结论,前端实现票据此改取数路径。

G2 map-snapshot 丢弃设备编码,WS 增量无法回联点位(2026-09-18 已由 Gogs #59 / #60 交付:deviceCodes + WS monitoringPointCode + 事件行点位 + 点位 industry/类型)

  • 内部快照 CockpitMapSnapshot.SourceMonitoringPoint.devices 存在,但 CockpitMapSnapshotService.monitoringPoint()(145–160 行)只用它解析点位状态,没有把设备编码写进响应。
  • WS cockpitDeviceStatusDelta 增量只带 deviceCode + 状态,前端拿到增量后无法知道它属于哪个监测点,点位状态无法联动。
  • 事件行同样没有归属点位:CockpitCurrentEventsResponse.EventItem 与 history-analysis 的行都缺 monitoringPointCode。
  • 现有替代路径代价高:GET /monitoring-points/{monitoringPointCode} 的 devices[].deviceCode 可反推 device→point,但需要逐点请求(N+1)。
  • 后端内部已持有该映射(SourceMonitoringPoint.devices;applyDeviceStatusDelta 能按 deviceCode 解析到点位),改动集中在响应层。
  • 另注:cockpitSubscribe 回帧只有 {scope, serverUpdatedAt},无初始状态数组(后端注释明确 REST 是初始快照、WS 只发增量——契约本身成立,前端按此实现);线上帧状态键是 data.status,而 DTO 字段名是 monitoringState,接入时注意别名。

需要后端:二选一或全做——① CockpitMonitoringPointSummary 输出关联设备编码列表;② WS 增量帧带上 monitoringPointCode;③ 事件行补 monitoringPointCode。

补契约清单(A–H)

11 个有缺口面板的完整字段表与分组补契约建议(含字段名、语义、是否需要新端点)见 research/panel-field-coverage.md 第 4 节,共 8 组;各组今日状态见上「第二轮逐项判定」:

  • A 跨设备事件读模型(阻塞 currentEvents、historyAnalysis、eventAnalysis、operationOverview)— ✅ 已交付
  • B 趋势时间范围可声明(阻塞 historyAnalysis、situationSummary)— ✅ 已交付(range 三档 + 显式区间)
  • C 响应/关闭时长聚合(阻塞 responseEfficiency)— ✅ 已交付
  • D 应急保障域三件套(阻塞 emergency 整版)— ✅ 已交付
  • E 管理信息域 — ✅ 已交付
  • F 设施运行信息域 — ✅ 已交付
  • G 地图行业/类型维度 — G1 ✅ / G2 ✅ / G3 ✅ / G4 ✅(2026-09-18 由 Gogs #59、#60 全部交付)
  • H 跨设备设备状态清单 — ✅ 已交付(monitoring/situation)

实现票 17–20 的 mock 阶段可按已有的面板级聚合响应形状建模:/overview/infrastructure、/overview/monitoring、/overview/warning-settings、/infrastructure/base-archives、/infrastructure/operating-information、/infrastructure/management-information、/infrastructure/emergency-support、/monitoring/overview、/monitoring/distribution、/monitoring/situation、/events/current、/events/history-analysis、/events/handling-efficiency、/events/multidimensional-analysis。

业务问题(待业务方确认,本票不发明结论)

三条仍未答复;下列为复核后掌握的现状与建议口径,供业务方确认或否决:

  1. 「故障」是否等同 stale? 现状:点位六态 ALARM/WARNING/WORK_ORDER/NORMAL/OFFLINE/EMPTY;指标六态 NORMAL/WARNING/ALARM/EXPIRED/OFFLINE/UNKNOWN,且字典明确 EXPIRED 不与 OFFLINE 合并;situation.abnormalEquipment.abnormalType 是异常分类。建议:业务确认「故障」是否即这些集合的子集,还是要独立桶。
  2. 「处置率」是否就是 handled/total(含已取消事件)? 现状:后端已冻结口径 basis = CLOSED_WORK_ORDERS_OVER_TOTAL_EVENTS(已结案工单数 ÷ 事件总数,见契约手册第 2 节),并显式给出 cancelledCount 等分量。建议:业务确认这就是所说的处置率,面板标注分子分母。
  3. 「管理单位」与后端 maintainer(维护单位)是否同一概念? 现状:management-information 以 organizations + ownershipDistribution + unmaintained 建模,与 maintainer 分开,倾向「不是同一概念」。建议:业务确认「管理单位 = 管理机构/权属单位,maintainer = 维护单位」并回写术语表。

影响的实现票

票 影响
08 地图摘要 ✅ G1/G2 已交付(Gogs #60):map-snapshot 承接 industry/region/deviceType 并回显 mapFilter;票 08 的分页/快照形状不变,装载器无需改动。另需注意真实数据未接线(BT-5)
15 WebSocket ✅ G4 已交付(Gogs #59):增量帧带 monitoringPointCode,未关联显式 null
17 基础设施面板 D/E/F 契约已交付,可对接;真实数据待接线
18 运行监测面板(含筛选联动地图) ✅ G1/G2 已交付(Gogs #60):票 18 只需把 filterStore 的 scope/industry 传给 map-snapshot 的 region/industry 入参,并按 mapFilter 回显生效范围;filterStore 已在票 01 落地。F/G/H:monitoring/overview、monitoring/distribution、monitoring/situation 可对接
19 预警处置面板 ✅ 契约已齐:A/C 已交付(events/current、history-analysis、handling-efficiency、multidimensional-analysis);monitoringPointCode 由 BT-1(#59)交付,coordinateValidation 与报警阈值由 BT-4(#62)交付。接真实接口前只剩真实数据未接线(BT-5)
20 总体概览面板 ✅ B 已交付(Gogs #61):overview/warning-settings 支持 range/startTime/endTime,可直接声明「近 7 日」并回显生效区间;真实数据待接线(BT-5)

Acceptance criteria(后端负责人)

  • map-snapshot 支持 industry 入参并在点位摘要中返回 industry 与点位类型。已达成(2026-09-18,Gogs #60 已关闭):裁定走路径①,落地为 industry/region/deviceType 三入参 + 逐点 industry/typeCode/typeName + mapFilter 回显;结论写入契约手册第 3 节。
  • 点位摘要返回关联设备编码列表,WS 增量可回联点位。已达成(2026-09-18,Gogs #59 已关闭):候选 ① 点位摘要 deviceCodes、② WS 增量帧 monitoringPointCode、③ 事件行 monitoringPointCode 三者全部实现;REST 与 WS 契约测试两侧覆盖。
  • A–H 各组补契约与后端负责人逐项确认排期(或明确拒绝并记录理由)。当前:11 个判定项全部已交付(A、B、C、D、E、F、G1、G2、G3、G4、H);Gogs 票 #59、#60、#61 已关闭,#62(事件坐标校验)、#63(真实数据接线)待排期。
  • 3 个业务问题得到业务方答复并回写本票。当前:0/3,待业务方确认(见上「业务问题」)。

进度:79%

据实更新(第一轮 30% → 第二轮 55% → 第四轮 61% → 第五轮 75%,第六轮因 #61 交付 B 上修):

  • 计分口径:11 个契约判定项(A、B、C、D、E、F、G1、G2、G3、G4、H)+ 3 个业务问题 = 14 项。已交付 11 项,合计 11/14 ≈ 79%。
  • 未完成,不 close。理由:AC4 三条业务问题 0 答复;AC3 余 BT-4(#62)与 BT-5(#63)未排期。
  • 本票未改动任何实现票的验收项;后端改动分别经 Gogs #59 / #60 / #61 走后端仓库自身流程。

下一步

  1. ✅ 已建票(2026-09-18):后端契约缺口交付包 的五张草案已在 Gogs 建成 #59–#63;BT-1(#59)、BT-2(#60)已实施并关闭,其余待排期;BT-6 可选,未建。
  2. 后端负责人(待办):BT-5 真实数据接线(#63)已开工未完成——按裁定先做 map-snapshot 纵向样板(第 1 片已落地,见第八轮),余 21 片待续;并需裁定第八轮列出的口径(坐标校核默认值、工单状态值域、窨井行业枚举)。BT-1…BT-4(#59–#62)均已交付并关闭。
  3. 地图筛选结论已冻结:以 map-snapshot 为准(industry/region/deviceType + mapFilter),见 docs/cockpit/README.md 第 3 节;/monitoring/distribution 不作为地图取数路径。
  4. 后端(程序级):真实数据接线进行中——map-snapshot 已接真实库(第 1/22 片),其余 21 片仍为空实现;这是接真实接口的最大差距,#63 未关闭。
  5. 业务方:答复上「业务问题」三条口径。
  6. 前端实现票 08/15/17–20(含 18 的筛选联动地图):mock 阶段不受阻;接真实接口前先取第 2、3 项结论,避免按错端点建模。
  7. 提醒:后端本地 #43 未推送,远端仍是 #42;各切片 *-demo.html 是 fixtures,不是真实数据。