Files
pbf/Codex_指令_NavSea_Pickup_当前点击解读_迁移到_React_MapLibre.md

11 KiB
Raw Blame History

Codex 指令:把 NavSea pickup 的“当前点击解读”迁移到 React + MapLibre

最后更新:2026-04-11
项目根:/root/sourceserver/pbf

1. 这份文档的用途

这是一份给 Codex 的中文任务指令。

目标不是讨论方案,而是让 Codex 在目标前端项目里,直接把当前 NavSea 测试页上的 pickup / 当前点击解读 逻辑迁移到 React + MapLibre。

这份指令要求实现结果尽量与当前测试页一致,而不是重新发明一套新逻辑。

2. 你要实现的目标

请在目标前端项目中实现一套 NavSea 海图点击能力,点击后返回并展示“当前点击解读”。

这套逻辑必须满足:

  1. 如果点击命中海面上或露出水面的可见对象:
    • 直接返回这个对象是什么
    • 例如:
      • 灯塔
      • 灯标
      • 浮标
      • 建筑物
      • 地标
      • 防波堤
      • 栈桥
      • 陆地
      • 桥梁
      • 危险物
  2. 如果点击更适合按海底信息解释:
    • 返回当前水深
    • 返回物体名(有的话)
    • 返回一句简单、普通钓鱼人能看懂的水底情况说明
    • 返回“判断理由”
  3. 不要让用户看见一堆内部调试术语。
  4. 不要默认优先海底解释。
    • 只要用户明确点到了看得见的物体,就优先按物体解释。

3. 当前实现的唯一参考来源

迁移时,请以本仓库下面这些文件为准,不要自己脑补一套新规则:

当前测试页里真正要迁移的核心行为,重点看:

  • handlePickup
  • buildDepthContext
  • collectTerrainSamples
  • buildTerrainInterpretation
  • buildFriendlyClickInterpretation
  • shouldPreferBBoxPrimary

4. 当前业务口径

迁移时请严格保持下面这些口径。

4.1 主键口径

  • 主对象 id 使用:
    • feature.id
  • 当前前端可把它视为:
    • fid

4.2 图层口径

  • 不允许前端手写一套新的 layer 名单
  • 统一从:
    • navsea-pickup-rules.v1.json 读取:
    • render_layer_groups.primary
    • render_layer_groups.area
    • render_layer_groups.info
    • render_layer_groups.ignore

4.3 点击优先级口径

  • 用户点到可见对象时:
    • 优先按对象解释
  • 用户没点到明确对象时:
    • 再回退到海底信息解释

4.4 “附近”口径

  • 当前业务定义:
    • 附近 = 100 米内
  • 不能再直接用固定 px 当业务口径
  • 正确做法:
    1. 先把 100m 换成当前 zoom 下对应的屏幕半径
    2. 用这个半径做 queryRenderedFeatures
    3. 再用真实 distance_m 二次过滤
    4. 只有 distance_m <= 100 的对象,才算“附近”

4.5 用户文案口径

  • 要用普通用户能看懂的话
  • 不要把下面这些词直接当最终用户文案:
    • 坡折
    • 脊
    • 槽
    • bathymetry
    • contour evidence
  • 可以保留在内部调试结构里
  • 但正式展示应尽量写成:
    • 这里水底起伏比较明显,像一道坎。
    • 这里像水底一条沟的边上。
    • 这里像水底一个小包或小凸起边上。
    • 这里水底看起来比较平。
    • 这附近像礁边,鱼容易沿边活动。
    • 当前位置只有少量海底辅助线证据,暂不判断明显坎沟。

5. 需要迁移的功能拆分

请把实现拆成下面几层,不要把所有逻辑塞进一个组件里。

A. pickup rules loader

负责:

  • 加载 navsea-pickup-rules.v1.json
  • 对外提供:
    • primary / area / info / ignore
    • display_name_overrides
    • layer_rules

B. rendered feature interpreter

优先复用或移植:

负责:

  • 把 queryRenderedFeatures 返回的 feature 转成统一解释结构
  • 对每个 feature 输出:
    • fid
    • source_layer_std
    • object_domain
    • object_class
    • canonical_object_type
    • title
    • details
    • render
    • score
    • distance_m

C. pickup query adapter

负责把 React + MapLibre 的 map 实例封装成统一查询接口。

至少提供:

  1. queryExactFeatures(point)
  2. queryBBoxFeatures(point, radiusPx)
  3. queryRawFeatures(point, radiusPx)

要求:

  • exact 查询层:
    • area + primary + info
  • bbox 查询层:
    • primary + info

D. depth context service

负责:

  • 在对象未命中时,返回最近深度上下文

必须保持与测试页同样口径:

  • 当前采用:
    • 100 米 口径
  • 返回:
    • nearest_depth_m
    • nearest_label
    • nearest_render_layer
    • nearest_distance_m
    • candidate_count
    • candidates

E. terrain interpretation service

负责:

  • 采样 100 米 内的海底证据
  • 做规则判读

当前只看下面这些强相关层:

  • 深度/海底线:
    • depth-contours
    • depth-contours-major
    • depth-contour-labels
    • depth-contours-major-labels
    • bathymetry-support
    • bathymetry-depth-labels
  • 底质:
    • bottom-material-labels
  • 结构:
    • submerged-structures
    • fishery-areas
    • hazard-polygons
    • navigation-hazard-polygons

返回:

  • local_depth_range_m
  • nearest_depth_m
  • contour_density
  • seabed_material
  • nearby_structures
  • hints

F. friendly click interpretation service

这是最重要的一层。

负责把内部 pickup / depth / terrain 结果,变成前端真正展示的“当前点击解读”。

输出必须分两种模式:

  1. 海面/露出物
  2. 海底信息

并返回:

  • mode
  • headline
  • depth_text
  • object_name
  • shape_text
  • reason_text
  • extra_text

6. 必须保留的关键逻辑

6.1 exact 与 bbox 的双阶段查询

不要只做一个 queryRenderedFeatures。

必须保留:

  1. exact point query
  2. bbox query

理由:

  • 海图小符号太小
  • 单点容易漏
  • bbox 用来补小灯标/小浮标/小地标

6.2 nearby primary 抢回规则

当前逻辑里,如果:

  • exact 命中的是 broad area / 次级对象
  • bbox 命中了 nearby primary

则允许 nearby primary 抢回。

但下列层不能被轻易抢走:

  • land_area
  • onshore_structure_area
  • onshore_structure_line
  • bridge_structure

也就是:

  • 陆地、建筑物、桥这种可见对象
  • 一旦已经被命中
  • 不应再被附近别的点对象夺走

6.3 可见建筑/地标点必须纳入主入口

当前规则里,这些层已经属于正式 pickup 主入口,迁移时必须保留:

  • facility-points
  • landmark-points
  • landmark-point-fallback

不能只顾海底,不关注建筑/地标。

6.4 海底解释不要黑箱

“当前点击解读”里必须展示:

  • 判断理由

当前要求至少能显示:

  • 当前水深取最近可见深度,约多少米
  • 100米 内样本深度范围与跨度
  • 附近等深线数量
  • 深度标签数量
  • 海底辅助线数量
  • 附近结构或底质

7. React 侧建议数据结构

请实现一个统一返回结构,例如:

export type NavSeaClickInterpretation = {
  resultType: "surface_object" | "seabed_context" | "empty";
  primary: null | {
    fid: string | null;
    title: string;
    sourceLayerStd: string;
    objectDomain: string;
    objectClass: string;
    canonicalObjectType: string | null;
    distanceM: number | null;
    details: Array<{ field: string; label: string; value: unknown }>;
  };
  currentDisplay: {
    mode: "海面/露出物" | "海底信息" | "未命中";
    headline: string;
    depthText: string;
    objectName: string;
    shapeText: string;
    reasonText: string;
    extraText: string;
  };
  depthContext: unknown;
  terrainInterpretation: unknown;
  candidates: unknown[];
  debug?: {
    exactFeatures: unknown[];
    bboxFeatures: unknown[];
    rawFeatures: unknown[];
  };
};

8. React 组件层要求

请在目标前端项目里落一个正式的点击结果 panel。

至少显示下面这些字段:

  • 结果类型
  • 主显示
  • 当前水深
  • 物体名
  • 水底情况
  • 判断理由
  • 补充提示

要求:

  • 样式简洁,不需要复刻测试页调试风格
  • 但字段含义必须保留
  • JSON 调试块可以放到开发模式或 debug 开关下

9. 不要做的事

请不要做下面这些事:

  1. 不要另造一套新的对象分类体系
  2. 不要手写一套新的 layer 白名单
  3. 不要把 附近 再改回固定像素半径
  4. 不要把所有用户都按“海底信息”解释
  5. 不要为了“更聪明”擅自引入复杂插值算法
  6. 不要删掉当前 判断理由
  7. 不要把内部调试术语直接暴露给普通用户

10. 你应该产出的内容

请在目标前端项目里至少完成:

  1. 一个可复用的 pickup service / hook
  2. 一个可复用的 current click interpretation 解释器
  3. 一个前端 panel 组件
  4. 把 map 点击事件接到这套逻辑上
  5. 必要的类型定义
  6. 一份简短说明,写清:
    • 主要新增了哪些文件
    • 如何接入
    • 当前有哪些限制

11. 验收标准

实现完成后,至少满足下面这些验收条件:

  1. 点到灯塔、灯标、浮标、建筑物、地标、防波堤、栈桥、桥梁时:
    • 优先返回具体物体
  2. 点到空白水域时:
    • 不直接返回空
    • 返回海底信息
  3. “附近”口径稳定为:
    • 100 米内
  4. “当前水深”和“判断理由”使用同一套证据口径
  5. 海底解释文案对普通钓鱼人基本可理解
  6. 不会出现:
    • 明明点到建筑物,却解释成海底
  7. 不会出现:
    • 当前水深和判断理由互相打架

12. 建议给 Codex 的直接执行口令

如果你把这份文档直接发给另一个 Codex,可以在前面加上这段:

请在当前 React + MapLibre 项目中,严格按照这份文档实现 NavSea 的 pickup “当前点击解读”。

要求:

1. 先阅读文档中列出的参考文件。
2. 不要另造规则,尽量复用现有 pickup 规则字典和解释器结构。
3. 直接在项目里完成实现,不要只给方案。
4. 完成后给出:
   - 改了哪些文件
   - 如何接入
   - 还剩哪些限制

13. 当前一句话总结

迁移时请记住唯一重点:

  • 可见对象优先按对象解释
  • 海底信息只作为未命中明确对象时的回退解释
  • “附近”统一按 100 米
  • “当前点击解读”必须带判断理由