Skip to content

前端联调 · 设备线(device.ts) ​

归属:前端联调 API 手册 → src/api/device.ts 端点:4 个(授权中心 2 + 设备绑定 action 2) 错误码段:40403xxx(全表见 错误码注册表) 错误契约:HTTP 400 / 401 / 404 + {code, msg, data} 取值语义:取值速查 · device —— 12 家厂商 meta.id 清单、authType 四值各自的交互形态、status 四态的判定优先级、platform 的静默归一(iOS → web) 深入说明:Device 设备线 API Docs · 授权中心四态

本页 curl 变量 ​

bash
BASE_URL=https://api.qingmulife.cn   # 本地:http://localhost:3000
ACCESS=<access_token>
ENV=Prd                              # Dev | Prd —— 全程必须一致
VENDOR=honor_oauth                   # meta.id —— 全表固定值,勿硬编码中文名

全部端点需 Bearer access + X-Env。

端点一览 ​

#方法路径场景
1GET/api/v1/device/vendors授权中心列表(12 平台 + 四态)
2POST/api/v1/device/vendors/{id}/auth-url发起厂商授权(拿 authUrl 给 webview)
3POST/api/v1/device myBindings我的绑定设备列表
4POST/api/v1/device unbind解绑设备

listVendors ​

一句话:拉厂商清单 + 每家的健康状态与四态绑定状态 —— 授权中心页(mine/data/device-list)进入时。

curl ​

bash
curl -s "$BASE_URL/api/v1/device/vendors" \
  -H 'X-Env: Prd' \
  -H "Authorization: Bearer $ACCESS"

请求 ​

字段类型必填说明
Authorizationheader✔Bearer <access>
X-Envheader✔双库路由(厂商清单与健康状态也按库算)

无 body / query。

响应 data ​

字段类型可空说明
vendors[].meta.idstring否机器键:honor_oauth / zepp / xiaomi / suunto + 9 家占位 —— unbind 与 auth-url 都传这个值
vendors[].meta.displayName.zh / .enstring否展示名
vendors[].meta.logoUrlstring | null是厂商 logo(CDN)
vendors[].meta.authTypestring否oauth | ble | import | sync
vendors[].meta.dataWindowDaysnumber否可回溯数据天数
vendors[].meta.capabilities.sportStat / sampleSets / healthRecord / realtimeboolean ×4否能力位
vendors[].health.okboolean否厂商服务是否可用
vendors[].health.detailstring | null | undefined—🔴 后端不存在此键!对应物是 health.message
vendors[].health.configured / health.serviceReadyboolean否后端返回、前端未声明(不消费无影响)
vendors[].health.messagestring | null是健康状态说明 —— 要展示文案就用这个,不是 detail
vendors[].statusstring否四态:'bound' | 'available' | 'reviewing' | 'error'(优先级 bound > available > error > reviewing)

🔴 坑位 · health.detail:前端 VendorEntry 声明了 health.detail?(optional),但后端没有这个键 —— 展示时恒 undefined。 因 optional 且当前 UI 只消费 meta / status,运行时不炸;要用健康文案请改读 health.message(或让后端补 detail 别名)。

错误码 ​

业务码HTTP触发条件前端建议处置
40403002401未登录 / token 无效走拦截器 401 分档

status 四态 → UI 建议 ​

状态含义前端展示
bound已绑定「已连接」+ 可解绑
available可授权「去授权」按钮可点
reviewing厂家审核中(占位厂家)⚠️ 12 平台全部展示(2026-09-19 决策回滚了更早的「隐藏」口径)—— 整行可点,点击 toast 引导预期,见 device-list.vue:207
error服务异常 / 未配置置灰 + 提示稍后再试

getAuthUrl ​

一句话:发起厂商授权 —— 拿 authUrl 丢给 webview 加载(授权中心点「去授权」)。

curl ​

bash
# body 传空对象即可(zepp 三端才需要 platform)
curl -s "$BASE_URL/api/v1/device/vendors/honor_oauth/auth-url" \
  -H 'Content-Type: application/json' \
  -H 'X-Env: Prd' \
  -H "Authorization: Bearer $ACCESS" \
  -d '{}'

# zepp 三端(platform 可选)
curl -s "$BASE_URL/api/v1/device/vendors/zepp/auth-url" \
  -H 'Content-Type: application/json' \
  -H 'X-Env: Prd' \
  -H "Authorization: Bearer $ACCESS" \
  -d '{"platform":"android"}'

请求 ​

字段类型必填说明
{vendor_id} (path)string✔传 vendors[].meta.id(如 honor_oauth)—— 不是中文名
platformstring✖仅 zepp 三端需要;缺省合法
Authorization / X-Envheader✔

响应 data ​

字段类型可空说明
authUrlstring否厂商授权页 URL → webview 加载
sessionKeystring | null是授权会话键(部分厂商返回)
requireProfileCompletionboolean否后端恒返回第三键,前端未声明(不消费,无影响)

错误码 ​

业务码HTTP触发条件前端建议处置
40403004404未知 vendor id(registry 查不到)用 meta.id,别用中文名拼
40403002401未登录走拦截器 401 分档
40403006400厂家审核中(占位厂家)「该设备正在接入中」置灰
40403007400厂商形态不支持该方法按 authType 隐藏入口

myBindings ​

一句话:我的绑定设备列表 —— 设备页显示已连接设备。

curl ​

bash
curl -s "$BASE_URL/api/v1/device" \
  -H 'Content-Type: application/json' \
  -H 'X-Env: Prd' \
  -H "Authorization: Bearer $ACCESS" \
  -d '{"action":"myBindings","payload":{}}'

请求 ​

字段类型必填说明
actionstring✔固定 "myBindings"
payloadobject✖忽略

响应 data ​

字段类型可空说明
list[].idstring否绑定记录 id(前端类型写成 number | string,更宽 ✓)
list[].vendorstring否厂商键(honor_oauth / zepp / xiaomi / suunto…)
list[].statusstring否active | revoked…
list[].vendorUserIdstring | null是厂商侧用户 id
list[].lastSyncAtstring ISO | null是最后同步时刻
list[].createdAtstring ISO否非空(前端类型声明 string | null,更宽 ✓)

✅ 契约干净。注意 list[].vendor 与 vendors[].meta.id 同值域 —— unbind 直接传它即可精确匹配。

错误码 ​

业务码HTTP触发条件前端建议处置
40403002401未登录走拦截器 401 分档

unbind ​

一句话:解绑设备 —— 设备列表点「解除绑定」。

curl ​

bash
curl -s "$BASE_URL/api/v1/device" \
  -H 'Content-Type: application/json' \
  -H 'X-Env: Prd' \
  -H "Authorization: Bearer $ACCESS" \
  -d '{"action":"unbind","payload":{"vendor":"honor_oauth"}}'

请求 ​

字段类型必填说明
actionstring✔固定 "unbind"
payload.vendorstring✔1–40 字符;传 meta.id / binding.vendor(页面传 device.id)—— 精确匹配,无模糊

响应 data ​

字段类型可空说明
okboolean否恒 true

错误码 ​

业务码HTTP触发条件前端建议处置
40403005404该用户未绑定此厂商(BINDING_NOT_FOUND)toast「未找到绑定记录」+ 刷新列表
40403001400vendor 缺失 / 超 40 字符 / 未知 action检查调用点
40403002401未登录走拦截器 401 分档

⚠️ 40403005 实测记录(2026-09-21 真机联调) ​

实测报文(18569401013 / 无任何 IoT 绑定的账号):

json
{"code":"40403005","msg":"binding not found","data":null}

两个必须知道的点:

  1. msg 是英文技术黑话,且会直接弹给用户。utils/request.ts 在业务码非 0 时统一 toast(body.msg) —— 所以用户看到的就是 binding not found 这句英文。本手册的「前端建议处置」列并不生效: 前端若不自造文案,透传的就是后端原文。 → 契约层面应要求后端返回中文用户文案(如「该设备尚未绑定」), 而不是让每个客户端各写一份映射(那就是 DBG-009 那类「改一处漏一处」)。

  2. 「刷新列表」这一列不是可选建议,是必需。 本码的语义是**「你的本地状态已过期」**(TOCTOU:下拉列表是 onShow 的快照, 用户读到点击之间状态可能已变)。不刷新 = 幽灵状态持续存在,用户会重复撞同一个错。

边界说明:本码的存在是刻意的 —— 后端 DeviceErrorCode.BINDING_NOT_FOUND → HTTP 404 是 V1 兼容(注释自陈「V1 Errors.notFound」),不是缺陷。缺陷只在 msg 与前端处置。