URL 参数深链精确选址 (Deep Link with ID-based Location Resolution)
深链(Deep Link) 通过 URL 参数直达应用内某个业务状态:分享一个 baseurl.com/navigate?id=xxx,打开页面即自动进入路线面板(route-panel)并填好目的地(结束点),经纬度由 id 在数据集中解析,而不是把坐标写死在 URL 里。
为什么用 id,而不是把坐标塞进 URL
- id 稳定:
uid是业务主键;坐标会因坐标系(WGS84 / GCJ02 / BD09)或数据修订而变,写进 URL 的坐标只是快照,会过期。 - 链接友好:
?lng=121.56&lat=29.82&name=xxx又长又乱码;?id=<uid>短、可读、可分享。 - 单一数据源:客户端统一从公开数据集解析,搜索列表与深链解析用同一份数据,前端/后端口径一致。
全栈实现链路(本项目实际落地)
后端深链路由:FastAPI 加
GET /navigate?id=<uid>,白名单透传参数(id/dst/ak/backend),302 到真实静态页/navi/index.html。- 为什么 302 而不是直接 FileResponse:导航页用相对路径引用资源(
styles.css、app.js、../logo.png)。若直接在/navigate返回文件,浏览器会把相对路径解析成/styles.css→ 404。302 到静态页,让浏览器按真实目录解析相对路径。
- 为什么 302 而不是直接 FileResponse:导航页用相对路径引用资源(
- 数据接口:
/browse输出全部 POI(含uid与导航坐标navi_location,本项目为 BD09),搜索与 id 解析共用,不新增端点。 - 页面解析参数:读
?id=存入pendingDestinationId;等待「地图就绪 + POI 数据加载完成」两个条件同时满足后,按 uid 匹配 POI →selectDestination()填好路线面板并规划。 - 多触发点、幂等消费:initializeMap / 定位成功回调 / 数据加载完成 三处都调用同一个
tryResolvePendingId();内部命中后清空pendingDestinationId。保证无论数据先到还是定位先到,都只触发一次——不重复定位、不漏触发。 - 入口复用同一 id:SPA 聊天里「智能导航选项」卡片按钮把同一个
uid作为?id=传给内嵌 iframe;卡片附「复制链接」按钮生成可分享 URL,全链路统一。
关键设计决策
- 经纬不进 URL,由 id 解析;未来换坐标系只改数据集,链接永不过期。
- 深链路由用 302,保持静态页相对路径语义(深链路由常见坑)。
- 参数白名单透传,不原样转发整段 query,防无关参数/注入。
- iframe 与整页两种形态共用一套参数协议(
?id=/?dst=/backend)。APK 与网页端差异只在backend:APK 内经 SPA 注入公网后端地址让导航页跨域 fetch(CORS 已开),网页端同源无需传。
验证方法
curl -i baseurl.com/navigate?id=<uid>应返回302且location: /navi/index.html?id=<uid>。- 手机浏览器直接打开分享链接,应自动进入路线面板、填好目的地,定位后规划路线。
- 无效 id 有兜底提示(本项目 toast「未找到该目的地」);数据加载失败也有独立提示。
常见坑 / 适用边界
- 静态页相对路径 + 深链路由:直接 FileResponse 会 404 资源,必须 302(或改写相对路径)。
- 就绪顺序不确定:id 解析必须「数据 + 地图」双条件齐全;多处触发要幂等,否则重复定位或漏触发。
- 坐标系:解析出的坐标必须匹配目标地图(百度 BMapGL 用 BD09;高德用 GCJ02)。
- 适用场景:一切「分享/收藏一个带业务实体的页面并自动填表」——预约链接、商品详情、打卡页同理。
关联
- URL Scheme (URL 协议)——深链的协议基础。
- 项目落地:
校园导航 Android Webview AI-canpus Map仓库 README「导航深链(URL 传参)」章节,代码见server.py的/navigate与frontend/public/navi/app.js的tryResolvePendingId。
本文归档于个人知识库 · 领域:CS & AI · 模块:04 Project_CS_AI/Web