---
url: /docs/guide/uniapp/api/sport-record-share.md
---
# Sport Record Share Image 运动记录轨迹图（前端调用视角）

> 路由：`POST /api/v1/device`（action 协议：`{"action":"...", "payload":{...}}`）
> action：**`sportRecordShareImage`** — 运动记录 → 高德地图轨迹图（详情页用）
> 鉴权：Bearer（未登录 `40403002`）
> 错误码段：**40403xxx**
> 后端契约权威：`src/app/device/interface/api/device_actions.py` · 2026-10-09 上线
>
> 📚 **三接口完整篇**（列表 sportRecords / 详情 sportRecordDetail / 轨迹图 + 调用样例 + 真实响应）：
> [api/sport-records](./sport-records) —— 本页是轨迹图**专题**（卡片参数细节）

## 场景（运动详情页）

运动数据 → 点记录 → **详情页的「轨迹图」区域**：调本 action 拿图片 URL → 直接 `<image>` 展示。
**无需前端地图组件** —— 后端出图：高德底图 + **红色轨迹线 + 起终点圆点**（Web Mercator
投影后端自画）+ 底部**数据卡片**（记录名/距离/时长/配速/类型/心率/卡路里/地址/日期/品牌）。

## 请求

```json
{
  "action": "sportRecordShareImage",
  "payload": {
    "externalId": "qm-qingmu_band-xxx",
    "name": "周日夜跑 · 麓松路沿线",
    "location": {
      "provice": "湖南省",
      "city": "长沙市",
      "area": "岳麓区",
      "address": "麓松路沿线",
      "lng": "112.9388",
      "lat": "28.2282"
    }
  }
}
```

| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `externalId` | string | ✅ | 记录 id（`sportRecords` 列表项 `id` 原样回传，同 `sportRecordDetail`） |
| `name` | string | ⬜ | **记录名**（如「周日夜跑 · 麓松路沿线」；前端本地已有该名生成逻辑）—— 给了 → 卡片首行显示；不给 → 该行不显示 |
| `location` | object | ⬜ | 位置结构 —— **给了 → 卡片显示地址行**；不给 → 该行不显示 |
| `location.provice` | string | ⬜ | 省（⚠️ 沿用既有拼写 `provice`；后端同时兼容 `province`，将来修拼写无需后端改码） |
| `location.city` / `.area` / `.address` | string | ⬜ | 市 / 区 / 详址（拼接顺序：省 市 区·详址） |
| `location.lng` / `.lat` | string | ⬜ | 经纬度（当前不参与出图 —— 轨迹以服务端数据为准；保留透传） |

> `lng/lat` 说明：图片轨迹**以服务端存储的轨迹为准**（`sportRecordDetail.track` 同源），
> 前端传的坐标不会覆盖轨迹。若将来需要「图上标当前位置点」再扩展。

## 响应

```json
{ "code": "0", "msg": "ok",
  "data": { "imageUrl": "https://cos-cdn.qingmulife.cn/share/sport/qm-qingmu_band-xxx.png",
            "pointCount": 42 } }
```

| 字段 | 类型 | 说明 |
|---|---|---|
| `imageUrl` | string | 图片 CDN 地址（1200×1600 PNG；底图 + 红色轨迹线 + 起终点圆点 + 底部数据卡片） |
| `pointCount` | int | 轨迹点数（服务端抽稀后参与出图的点数） |

## ⚠️ 必读四条

1. **幂等可缓存**：同 `externalId` 永远返回同一 URL（COS 覆盖写）—— 可放心缓存 URL；但**重新生成会覆盖旧图**（记录更新后若需刷图，加时间戳参数即可，本项目不做）。
2. **无轨迹记录有明确空态**：打卡类记录无 GPS 轨迹 → `40403009`「该记录无轨迹数据」→ 前端显示「本次运动未记录轨迹」空态，**不要重试**。
3. **生成失败可重试**：`40403008`（502）= 高德/COS 抖动 → 给「重试」按钮（幂等无害）。
4. **首次生成约 1-3 秒**（拉高德底图 + 传 COS）→ 前端给 loading 态；生成后再调同 `externalId` 秒回（已是 CDN 图可直接缓存本地）。

## 错误码

| code | HTTP | 场景 | 前端处理 |
|---|---|---|---|
| `40403001` | 400 | payload 校验失败 / unknown action | 检查传参 |
| `40403002` | 401 | 未登录 | 跳登录 |
| `40403004` | 404 | 记录不存在（或非本人 —— 跨用户查不到） | 提示记录不存在 |
| `40403008` | 502 | 轨迹图生成失败（高德/COS） | 可重试按钮 |
| `40403009` | 400 | 该记录无轨迹数据（打卡类） | 「未记录轨迹」空态，勿重试 |

## 调用时序（推荐）

```
进入详情页
  → sportRecordDetail {externalId}          ← 页面数据（距离/配速/心率曲线…）
  → sportRecordShareImage {externalId, location?}
      ├─ code=0 → <image :src="imageUrl">（轨迹图区）
      ├─ 40403009 → 「本次运动未记录轨迹」空态
      └─ 40403008 → 「生成失败」+ 重试
```

## 顺带修复：sportRecords 新增累计时长

`sportRecords.summary` 新增 **`totalDurationSec`**（秒）—— 列表页顶部「累计运动用时」
此前显示 `--` 是因为该字段缺失，前端改用此字段即可：

```
summary: { totalDistanceKm, totalCalories, totalCount, totalDurationSec }
```

## 相关

* **三接口完整篇**：[api/sport-records](./sport-records)（列表 / 详情 / 轨迹图 + 调用样例 + 生产真实响应）
* 跑步会话分享图（另一条线）：[api/run-share](/guide/uniapp/api/run-share)
