9.9 KiB
Taro 前端对接指南
更新时间:2026-06-28
目标:用一套 Taro 工程同时服务微信小程序和 H5 Web 题库,并采用“Supabase Auth/JWT + apps/api 业务 API 优先”的混合架构,支持多租户、品牌主题、地区题库、会员权益、销售追踪和对象存储资源。
建议新建:
F:\project\apps\taro
旧前端参考:
F:\project\参考\旧题库项目\src
启动流程
H5
- 从
window.location.host获取当前域名。 - 调用
GET /api/tenant/resolve?host=<host>。 - 保存
tenant.id、tenant.slug、branding、features、publicConfig。 - 初始化主题、Logo、页面标题、功能开关。
- 检查本地 session token,调用
GET /api/auth/me。 - 如果未登录,进入登录页;如果已登录,加载个人中心和首页数据。
微信小程序
- 从编译环境或小程序启动参数读取
tenantCode。 - 推广码、销售码、分享码从
options或scene中解析。 - 调用
GET /api/tenant/resolve?tenantCode=<tenantCode>。 - 如存在 referral 参数,先调用
/api/referral/resolve和/api/referral/track-event。 - 登录后再调用
/api/referral/bind完成首绑保护。
请求封装
本项目不采用“前端直接写 Supabase 表替代业务命令层”的模式。Supabase 官方允许前端在 RLS 和最小权限下使用 Data API,但本系统的订单、支付、权益、租户后台、内容导入、CRM、对象存储签名等都需要服务端事务、密钥、审计和幂等,所以复杂业务命令默认调用 RPC、apps/api、Edge Function 或 worker。
前端可以使用 Supabase client 的范围:
- H5 Auth session/JWT。
- 小程序端在兼容性验证通过后的 Auth session/JWT。
- 低风险公开只读数据,且必须已经有 RLS、grant、跨租户测试。
- Realtime 非敏感通知。
前端必须调用 apps/api 的范围:
- 题库练习、答题、错题、收藏。
- 订单、支付、激活码、优惠券、权益。
- 私有 PDF、资料、视频、对象存储签名。
- 租户后台、平台后台、内容导入、CRM、销售/代理。
前端应封装一个统一 API client,所有页面禁止直接散写 Taro.request。
本地迁移期仍可兼容旧请求头,但新的 Taro 请求封装必须按下面目标实现:
Authorization: Bearer <tk_session>
x-tenant-id: <tenantId> # 仅作为登录前/公开目录租户上下文;登录后必须与 session 租户一致
生产目标:
Authorization: Bearer <supabase_access_token_or_server_session>
前端不应再传 x-user-id、query/body userId 来表示当前用户。后端已经实现 session 优先解析:如果 Authorization 存在,用户态接口以 session 用户为准;如果请求里伪造了不同的 userId 会返回 AUTH_USER_MISMATCH,伪造不同租户会返回 AUTH_TENANT_MISMATCH。
生产或云端测试建议设置:
ALLOW_LEGACY_AUTH_HEADERS=false
ALLOW_PLATFORM_ADMIN_KEY=false
这样旧式 x-user-id 和平台管理 key 会被拒绝,前端可以提前发现未按 session 接入的页面。
前端环境变量只允许包含:
TARO_APP_API_BASE_URL
TARO_APP_SUPABASE_URL
TARO_APP_SUPABASE_PUBLISHABLE_KEY
禁止把 Supabase secret key、service role key、数据库连接串、对象存储密钥、支付私钥放进 Taro。
统一错误处理:
| HTTP | 前端动作 |
|---|---|
| 400 | 展示表单错误或参数错误 |
| 401 | 清 session,跳登录 |
| 403 | 展示无权限或会员升级 |
| 404 | 展示空状态 |
| 409 | 展示业务冲突,例如激活码已用 |
| 413 | 提示上传/导入文件过大 |
| 429 | 倒计时重试,例如短信冷却 |
| 500 | 展示系统异常并上报日志 |
全局状态建议
| Store | 内容 |
|---|---|
| tenantStore | tenant、branding、theme、features、publicConfig |
| authStore | session、user、roles、permissions、loginState |
| regionStore | 当前地区、可选地区、地区权益 |
| catalogStore | content entries、nodes、collections、blueprints |
| entitlementStore | SVIP 权益、视频权益、资料下载权益 |
| referralStore | inviteCode、referrer、scene、bindState |
| uiStore | 当前主题、tab、loading、toast、modal |
注意缓存必须带租户维度,例如:
tenant:<tenantId>:catalog:entries
tenant:<tenantId>:profile
tenant:<tenantId>:theme
切换租户或切换小程序环境时必须清理旧租户缓存。
页面/API 映射
| 页面 | 主要接口 |
|---|---|
| 启动页 | GET /api/tenant/resolve |
| 登录页 | POST /api/auth/sms/send、POST /api/auth/sms/verify、后续微信/QQ provider |
| 首页 | /api/catalog/content-entries、/api/catalog/banners、/api/catalog/announcements、/api/profile/me |
| 选地区 | /api/catalog/regions、/api/commerce/entitlements/check |
| 题库入口 | /api/catalog/content-entries |
| 分类树 | /api/catalog/content-nodes?entryId=...&parentId=root |
| 题目列表 | /api/catalog/question-collections、/api/catalog/question-collections/questions |
| 开始练习 | POST /api/learning/practice-sessions |
| 提交答案 | POST /api/learning/answers |
| 错题本 | GET /api/learning/wrong-questions、POST /api/learning/wrong-questions/resolve |
| 收藏夹 | GET/POST /api/learning/favorites/questions |
| 题目视频 | GET /api/questions/{questionId}/videos、POST /api/questions/videos/batch |
| 背单词 | /api/catalog/vocabulary-units、/api/catalog/vocabulary-words |
| 单词进度 | /api/learning/vocabulary/progress、/api/learning/vocabulary/stats |
| 单词收藏 | /api/learning/vocabulary/favorites |
| 知识手册 | /api/catalog/handbook-subjects、handbook-chapters、handbook-entries |
| 分数线 | /api/scoreline/fields、schools、majors、records、trend、years |
| 资料下载 | /api/catalog/assets、/api/catalog/assets/download |
| 商城 | /api/catalog/svip-plans、POST /api/commerce/orders |
| 订单/权益 | /api/commerce/orders、/api/commerce/entitlements |
| 激活码兑换 | POST /api/commerce/activation-codes/redeem |
| 个人中心 | GET/PATCH /api/profile/me |
| 销售分享 | /api/referral/resolve、track-event、bind |
题库新模型接入方式
旧项目常按“地区 -> 科目 -> 章节/试卷”固定层级处理。新项目不要写死层级,按下面模型渲染:
content_entries
-> content_nodes 任意深度分类树
-> question_collections 题目列表/试卷/章节/题型集合
-> practice_blueprints 顺序/随机/全真模拟规则
前端建议:
entryType=question_practice渲染为刷题入口。entryType=vocabulary渲染为背单词入口。entryType=handbook渲染为知识手册入口。markerType=school或markerType=exam_track可作为学生目标院校/专业意向采集。- 不同地区节点层级可以不同,页面组件必须支持递归树和面包屑。
多租户前端优化
- Logo、标题、主题色、客服信息全部来自
tenant/resolve。 - 功能开关控制菜单显示,但接口权限仍以后端为准。
- 私有图片、PDF、视频不要直接拼 URL,一律通过后端签名。
- 支付渠道从后端返回或租户配置读取,不在页面硬编码。
- 小程序分享路径必须带 tenantCode 和 referral code。
- 用户首绑归属由后端保护,前端不要提供“换绑销售”入口。
- 管理后台菜单按
GET /api/tenant-admin/permissions和用户权限渲染。 - H5 自定义域名下要注意缓存隔离,不能把 A 租户主题缓存用到 B 租户。
第一阶段页面建议
pages/bootstrap/index- 租户解析、主题初始化、登录态恢复。
pages/login/index- 先接短信登录;后续接微信小程序登录。
pages/home/index- Banner、公告、题库入口、会员入口、资料入口。
pages/region/index- 地区选择和权益提示。
pages/catalog/index- entry/node/collection/blueprint 通用导航。
pages/practice/index- 刷题、答题、解析、错题、收藏。
pages/vocabulary/index- 单词单元、学习、收藏。
pages/handbook/index- 手册目录和阅读。
pages/scoreline/index- 动态字段筛选和趋势。
pages/profile/index
- 会员、订单、激活码、学习数据。
租户后台前端建议
租户后台可以先做 H5 管理台,也可以后续使用 Taro H5 复用部分组件。优先页面:
- 概览:
/api/tenant-admin/overview - 品牌/主题/域名/公开设置
- 支付账户/登录 provider/密钥引用
- 用户与成员权限
- 内容入口/分类树/题目集合/练习蓝图
- 题目/单词/知识手册/分数线/视频维护
- JSON 导入 preview/import/issues
- Banner/FAQ/公告/激活码/优惠券
- 销售/代理/CRM 队列
租户后台不应在前端自行决定权限;隐藏菜单只是体验优化,接口仍会校验权限。
联调顺序
- 启动页和租户解析。
- 短信登录和
auth/me。 - 首页、地区、内容入口、题库树。
- 练习 session、答题、错题、收藏。
- 背单词、知识手册、分数线。
- 会员套餐、订单、激活码。
- 资料下载、视频解析。
- 销售追踪和分享链路。
- 租户后台内容维护和导入。
- 正式鉴权、真实支付、对象存储生产联调。
Supabase Client 验证任务
前端 scaffold 后先做一个最小兼容性验证:
- H5:
@supabase/supabase-js初始化、session 持久化、token refresh、logout。 - 微信小程序:验证自定义 storage/fetch/URL polyfill 是否稳定。
- API:用 Supabase access token 调
apps/api,后端解析出可信用户。 - 安全:确认前端 bundle 中不存在 secret/service role/database/payment/storage 私钥。
如果微信小程序端 supabase-js 兼容性不稳定,小程序端改走 apps/api/auth/* 登录适配层,H5 继续使用 Supabase client 管理 Auth。