Skip to content

Run Share 跑步分享图 + finishRun 接线(前端调用视角) ​

路由:POST /api/v1/sport(action 协议:{"action":"...", "payload":{...}}) 涉及 action:finishRun(前置接线)+ runShareImage(分享图生成) 鉴权:需登录(Authorization: Bearer <access_token>) 错误码段:40418xxx 后端契约权威:api-docs/v1/sport · src/app/sport/interface/api/sport_actions.py

一句话 ​

跑步结束必须调 finishRun(当前前端未接 — 见必读①);用户点「分享」时调 runShareImage, 后端用已上报的轨迹生成地图分享图存 COS,直接返回图片 URL —— 前端不传轨迹数组。

跑步数据上报的完整链路(现状 + 缺口) ​

(2026-10-10 运动数据闭环 v3 — Redis 登记簿 + 后端分配 sessionId + 清洗归一)

startRun {activityType, location?{provice,city,area,address,lng,lat}, deviceId?}
                                        → {sessionId(后端分配), resumed, resumedFromDevice?}
                                          ⭐ 单活跃幂等:同用户 8h 内重复 go → 同 ID
  ↓ 跑步全程 —— 高德 SDK 本地记录,零请求(App 被杀 → myActiveRun 查活跃恢复现场)
submitRun {sessionId, points[{lat,lng,ts}]≤20000, duration(毫秒), calories?, avgHr?, steps?,
           activityType?(离线补交必带), distance?(米—上报口径), startedAt?, deviceId?}
                                        → {summary(上报口径主), cleanedDistanceKm,
                                           routePointCount, newPointsInserted}
                                          ⭐ 单事务四写:run_session + 清洗点 +
                                            raw_event 留档 + sport_record 归一
                                            (vendor='app_run' — 运动记录列表可见)
  ↓ 用户点分享
runShareImage {sessionId}                → {imageUrl, pointCount}

⭐ v3 变更要点(2026-10-10):① startRun 不再收前端 sessionId(旧参数静默忽略 — 宽容兼容);② location 随开始上报,落库到运动记录(详情地址条/轨迹图地址自动填充); ③ 点数上限 5000→20000(全马可收;需 nginx client_max_body_size ≥ 2m); ④ 提交后立即可查 sportRecords(同事务归一,强一致);⑤ distance(米)可选 — 前端 SDK 实时里程,给了以它为主口径(cleanedDistanceKm 披露去漂移值)。

⚠️ 旧链 reportRunCoordinate(逐点上报)已下线(返 unknown action)—— 前端 reporter 若还在调需移除(此前实为 mock 未发真请求)。finishRun 保留但不再是主路径(submitRun 已含收尾定稿)。

submitRun 契约速览(v3 — 结束上报) ​

jsonc
{ "action": "submitRun",
  "payload": {
    "sessionId": "run-8f3a2b",                 // ✅ startRun 返回的那个
    "points": [{"lat": 28.2, "lng": 112.9, "ts": 1791374400000}, …],  // ✅ ≤20000 · ≥2
    "duration": 1962000,                       // ✅ 毫秒(含暂停累计)
    "distance": 5000.0,                        // ⬜ 米(SDK 实时里程 — 给了以它为主口径)
    "activityType": "running",                 // ⬜ 登记里有;离线补交必带
    "calories": 379, "avgHr": 123, "steps": 2807,
    "startedAt": 1791374400000                 // ⬜ 离线补交必带
  }}
// data → { summary(上报口径), cleanedDistanceKm(清洗披露), routePointCount, newPointsInserted }

五验硬拒(400 · 40418001):≥2 点 · ≥50 米 · ≤20000 点 · ≤24h · 段速物理上限(清洗后判定——GPS 偶发尖刺先被滤除,仅全程超限才拒)。 时间戳乱序由服务端自动排序(客户端无需预处理;原始顺序留档可溯源)。 全字段表 + 完整语义见 API Docs → sport;排障见 run-submit-debug。

runShareImage 契约 ​

请求 ​

json
{ "action": "runShareImage", "payload": { "sessionId": "running-1790000000000" } }
字段类型必填说明
sessionIdstring✅startRun 返回的客户端会话 id(与 finishRun 同一个值)

成功响应 ​

json
{
  "code": "0", "msg": "ok",
  "data": {
    "imageUrl": "https://cos-cdn.qingmulife.cn/share/run/running-1790000000000.png",
    "pointCount": 342
  }
}
字段类型说明
imageUrlstring分享图 CDN 地址(可直接展示 / 下载 / 分享)
pointCountint后端实际使用的轨迹点数(服务端库内全量,非前端上报截断)

后端做了什么(前端无需关心,仅供理解) ​

读库轨迹(reportRunCoordinate 已落库的全量点)→ 等步长抽稀 ≤200 点 → 高德静态地图 (轨迹线自动居中)→ Pillow 叠数据卡片(距离/时长/配速/日期 + 品牌)→ 传 COS。

⚠️ 必读四条 ​

  1. finishRun 当前前端未接线 — 跑步收尾只有本地 stopRun,服务端 session 永远收不了尾 (无终值、分享图取到的汇总不完整)。接分享图前必须先补 finishRun: {sessionId, distance(米), duration(毫秒), calories?, avgHr?, steps?}。 ⚠️ 不要把轨迹 points 塞进 finishRun —— 后端 extra="ignore" 会静默丢弃(轨迹 属于 reportRunCoordinate 逐点上报,已在线上跑)。
  2. 轨迹点不足会报错(诚实空态) — 40418001「该记录轨迹点不足」= GPS 未记录 (室内/权限拒绝)。前端按业务错处理并提示,不要重试。
  3. 生成失败可重试(502 段) — 40418012「分享图生成失败」= 高德/COS 任一环抖动, 幂等(同 sessionId 重试安全),建议前端给「重试」按钮而非死报错。
  4. imageUrl 同 session 恒定 — COS key 固定 share/run/{sessionId}.png,重复生成覆盖 同一地址(可放心缓存 URL;但重新生成会覆盖旧图,无多版本)。

错误码 ​

codeHTTP场景前端处理
40418001400sessionId 空 / 轨迹点 <2提示「本次运动未记录到轨迹」
40418002401未登录跳登录
40418004404session 不存在(或非本人 — 跨用户查不到)提示记录不存在
40418012502高德/COS 生成失败(含 AMAP_WEB_KEY 未配置)可重试按钮

调用时序(推荐) ​

点「分享」
  → 若本次跑步未 finishRun:先 finishRun(拿 routePointCount 校验轨迹完整)
  → runShareImage {sessionId}
      ├─ code=0 → 展示 imageUrl(uni.previewImage / 下载 / 分享)
      ├─ 40418001 → 「未记录到轨迹」空态
      └─ 40418012 → 「生成失败」+ 重试

相关 ​

  • 后端完整契约:api-docs/v1/sport
  • 逐点上报契约(已接线):src/api/sport.ts ↔ run-coordinate-reporter.ts
  • 城市里程榜(另一条榜线):api/city-ranking