Appearance
uniapp 前端开发指引
沐禾健康 C 端(uniapp Vue3 + TS + Vite CLI 工程)开发指引 — 源仓库 qingmu2026/qm-frontend
api分支。 本文由人工精写 + 脚本生成(scripts/gen_uniapp_docs.py)混合维护,最后更新 2026-09-20。
文档分工边界(必读)
四套文档并存,各写各的、不互相复述 —— 接触面只有"锚点",接触面越窄越不会互相矛盾:
api/*.md只写「前端函数 → action → 必需 payload 键 → 响应读法 → 失败时的前端动作」; 字段表、错误码、curl 一律见 前端联调 API 手册。
| 内容 | 唯一归属 | 另一侧怎么写 |
|---|---|---|
| 请求/响应字段表(类型、必填、可空)、错误码具体码值、全部 curl | 前端联调 API 手册(契约权威) | 本文只写读法路径(res.data.calorie.budgetKcal)与前端动作(「提示并回退重拉」)+ 指锚点;不写类型、不写 curl |
| 通用约定 G1-G7(统一包络 / X-Env / 鉴权三档 / 401 分档 / rotate 单飞 / snake_case 例外 / 响应无 schema) | 手册 · 通用约定 | 本文只写一句「与 手册 G2 一致」 |
| 10 条头号坑位 | 手册 头号坑位速查 + 联调台账 | 本文只在自己页面确实踩到时指锚点 |
真机/框架坑(编译器锁版本、t.__f__ 崩溃、www 缓存、adb logcat、验证码渲染三定律) | 本文(本页铁律) | 手册一字未提 —— 这是本文的独占资产 |
页面 ↔ API 映射、调用链时序、storage 键名、乐观更新写法 | 本文 pages/*.md + api/*.md | 手册只在 page-direct.md 涉及 3 端点 |
生成装置(gen_uniapp_docs.py / _meta.json / CONTRIBUTION.md) | 本文 | 手册无此维度 |
| OAuth 从零施工手册(拷 SDK、自定义基座、微信登录 manifest) | OAuth 登录链落地手册 | 该页页首已声明「契约见手册」,本文不复述其施工步骤 |
⚠️ 一致性由脚本兜底,不靠自觉:
scripts/check_uniapp_api_docs.py(pre-commit 钩子)机械校验 「矩阵 30 端点覆盖 / 已证伪字面量 / 字段路径层级 / 跨目录死链」四项 —— 文档字段与本目录任何一处对不上,提交即拦。
这是什么
面向「给 C 端加页面 / 改功能 / 调后端接口」的开发者。四件事:
- 看结构 — structure.md:uniapp CLI 编译要求的规范目录树,现状对照与改进标注
- 看页面/组件 —
pages/(34 页)与components/(20 组件)说明:职责 / 依赖 / 调用的 API / git 变更记录 - 调接口 —
api/(9 页):调用契约(oauth 登录链 / user 向导链 / splash 开机屏 / device 设备线 / training 训练计划 / stats 今日概览 / agreement 协议 / page-direct 页面直调 + 目录总览)—— 消费视角(读法路径 + 前端动作),字段表 / 错误码 / curl 零复述、一律指向手册(见上「文档分工边界」) - 看差异 — comparison.md:三层对比(仓库两代形态 / V1 小程序↔V2 功能映射 / CNB↔本地同步)
工程速览
| 维度 | 现状 |
|---|---|
| 框架 | uniapp Vue3 + TypeScript + Vite(CLI 形态,无 HBuilderX) |
| 编译器 | @dcloudio/* 3.0.0-5020420260813001(精确锁版本,caret 会拉 alpha 崩) |
| 注册页面 | 34(含 2 个 .nvue 原样渲染页:run/index、run/sport-index) |
| 组件 | 20 个 qm-* 项目组件 + uview(u-popup/u-picker/u-icon) |
| API 层 | src/api/*.ts 6 文件(agreement / device / login / splash / training / user;导出函数 27 个)+ 仅剩首页 index.vue 内联 request 2 处(getTodayOverview / myTodayHealth — 按手册口径归「页面直调」,非收敛缺口);api/stats.ts、api/sport.ts 尚未建 |
| 请求封装 | src/utils/request.ts:业务码 "0" 判定 + resolve(body) 不解包(调用方必须 ?.data)+ 401 rotate 单飞续期 |
| 后端 | QM-ServerV2(action 协议 POST + REST 混合),X-Env: Dev|Prd 双库路由 |
目录
- structure.md — 规范结构树
- comparison.md — 三层差异对比
- page-api-reference.md — ⭐ 前端页面 × 后端 API 反向索引(36 页 × 54 端点)
- api/ — 总览 / oauth / user / splash ⏳ / device / training / stats / agreement / page-direct
pages/*.md— 页面说明(34 篇,P2 批量生成)components/*.md— 组件说明(20 篇,P2)CONTRIBUTION.md— 多用户提交记录(P2,脚本生成)
关键铁律(新人必读,血泪沉淀)
- request 返回整个 body 不解包:
const res = await xxxApi(); res.data 才是业务数据— 漏?.data会在远端爆 TypeError(真机实锤:向导 enroll 三连 bug) - 编译器锁版本:
package.json中@dcloudio/*禁止改 caret - APP 端模板事件:绑具名方法(内联箭头 →
t.__f__ is not a function崩) - JS 静默崩调试:
adb logcat -d | grep -i console直接看 APP 端报错 - 每次重装 APK 必须清 www 缓存:
rm -rf /sdcard/Android/data/<pkg>/apps/__UNI__F1DDAB4/www
平台差异坑速查表(App / H5 / 小程序)
本表原在 OAuth 登录链落地手册 §7,2026-09-20 并入本页铁律(避免同一坑三处各写一份); 该页 §7 现只留一个指回本页的指针。本页是唯一维护处。
| 坑 | H5 | App | 小程序 | 应对 |
|---|---|---|---|---|
rich-text 渲染 SVG | ✅ | ❌ | 部分 | 服务端直出 PNG(captcha 响应的 png 字段,data:image/png;base64)→ <image :src> 全端直显 |
| localStorage / storage | 异步语义 | 同步 | 同步 | 统一用 uni.getStorageSync(src/utils/storage.ts 已封装) |
| 跨域 | dev proxy | 无跨域概念 | 无 | App/H5 生产包必须 HTTPS;manifest 不留 http 明文白名单 |
| http 明文 | 浏览器允许 | manifest 白名单控制 | 域名校验 | 生产全 HTTPS |
| cookie | 自动携带 | 不自动 | 不自动 | 本链路不依赖 cookie(SDK 用 header token)✅ |
| 微信登录 | ❌ | ✅ 需自定义基座 | — | HBuilderX 标准基座测不了(原生 SDK);见落地手册 §5 |
文档如何再生成
bash
# ⚠️ --frontend 必须指向 canonical 工作区(与 contract-matrix.json / 手册同源):
# 旧写法 `<qm-frontend工作区>` 曾漂到 qm-frontend/.claude/worktrees/api-fix → 文档状态系统性滞后一版
python3 scripts/gen_uniapp_docs.py \
--frontend ~/Documents/Claude/Projects/qm-frontend-api \
--out docs/guide/uniapp/_meta.json --gen-md脚本输出元数据 JSON(页面/组件/工具/git 记录/API 调用),文档批量生成基于它 — 源码变更后重跑即可刷新 git 记录与调用清单。 生成后请跑 scripts/check_uniapp_api_docs.py 校验链接与字段(pre-commit 也会拦)。