小程序
微信小程序客户端。TypeScript + glass-easel + TDesign 组件库,默认 WebView 渲染,Skyline 仅在性能关键页按页开启(当前未开)。通信层抽象了微信云托管与自托管两种传输,身 份基于 wx.login + 后端 code2Session 解析 openid。
工程约定
app.js为纯 JS(require),避免app.ts/app.js冲突;utils/、config/为.ts(ES 导出,编译为 CommonJS)。componentFramework: "glass-easel"(全局,app.json)。navigationStyle: "custom",每页手写自定义导航栏。- 设计 token 定义在
app.wxss(page选择器上的 CSS 变量)。
渲染策略
- 不在
app.json设全局"renderer": "skyline";rendererOptions.skyline只是声明"开 Skyline 时的选项",不等于开启。 - Skyline 仅在性能关键页按页开启:在该页
page.json加"renderer": "skyline",必须用scroll-view承载滚动内容(Skyline 无页面级滚动),并保持navigationStyle: custom。 - 当前所有页面均为 WebView;接入真实大列表的页面再按页评估开启 Skyline。
- 低版本微信/PC 端会自动 fallback 到 WebView,按页开启是安全的。
- TDesign 对 Skyline 支持是部分的(Cascader/Calendar 在 Skyline 下不可用),默认 WebView 可用完整组件库。选型背景见仓库根
agents/TDesign-Skyline-兼容性调查报告.md。
页面
页面清单与 tabBar 以 app.json 为准,此处不逐页罗列(页面数量与状态会随开发持续变化,逐页描述必然过时)。
通信与传输
配置在 miniapp/config/api.ts。ApiConfig 字段:transport(callContainer | http)、cloudEnv(云环境 id,callContainer 用)、serviceName(作为 X-WX-SERVICE 头,callContainer 用)、baseUrl(后端地址,http 用)、timeout。
- devConfig:
transport: 'http',baseUrl: 'http://localhost:8080'。 - prodConfig:
transport: 'callContainer',cloudEnv/serviceName填真实云托管值(当前为占位 TODO)。 - 自动切换:
resolveConfig读wx.getAccountInfoSync().miniProgram.envVersion——develop(开发者工具)走devConfig,trial/release(真机)走prodConfig。 - 强制覆盖:
FORCE_TRANSPORT(设'http'或'callContainer')可无视envVersion全局强制,便于在工具里测云端传输。
自托管(非微信云)
仅改配置、不改代码:把 FORCE_TRANSPORT 设为 'http',并把 devConfig.baseUrl 改成你的后端地址(无尾斜杠)。localhost 需在开发者工具勾选「详情 → 本地设置 → 不校验合法域名」;真实域名需加入微信「request 合法域名」白名单。身份机制(wx.login/code2Session)非云专属,自托管同样可用。
请求层
miniapp/utils/request.ts 导出 request<T>(opts),在 callContainer 与 wx.request 之上做了统一 Promise 封装:
opts:path、method、data(体)、params(查询串,自动 URL 编码)、header、auth(默认true,附 JWT)、timeout。auth !== false时:从getToken()取 JWT,设Authorization: Bearer <token>;callContainer分支额外附X-WX-SERVICE头。默认Content-Type: application/json。- 网络层失败:reject
{ statusCode: 0, message: '网络异常,请检查网络后重试' }。 - HTTP 401 且
auth !== false:触发已注册的onUnauthorized(由auth.ts接到clearAuth+wx.reLaunch('/pages/login/login'))。 - 非 2xx:抛
ApiError { statusCode, message, data },message取自data.error或data或默认'请求失败'。 - 2xx:resolve
data。
身份与鉴权
客户端只持有 JWT(storage key token)和 user 对象(key user),从不接触 openid——openid 由后端用 AppSecret 调 code2Session 解析,AppSecret 只在后端 env。
| 动作 | 流程 | 端点 |
|---|---|---|
| 静默登录 | wx.login 取 code → POST { code }(auth: false)→ 后端 code2Session 解析 openid → 返回 { token, user } | POST /api/auth/wx-login |
| 绑定账号 | wx.login + 用户名密码 → POST { username, password, code }(auth: false)。首次绑定,openid 必须未绑过 | POST /api/auth/wx-bind |
| 解绑 | POST(需鉴权) | POST /api/auth/wx-unbind |
| 页面守卫 | ensureAuth():有 token 即放行;否则尝试静默登录;遇 404(openid 未绑)→ reLaunch 到 login?notBound=1 | 客户端逻辑 |
安全约束:后端因网页端需要必须公网暴露,故 X-WX-OPENID 云网关头可伪造、不可信任;openid 只信后端 code2Session 的结果。绑定规则:账号 openid 必须为 NULL 才允许绑定(防劫持),唯一索引防一个 openid 绑多账号。JWT 为 HS256、24h,网页端与小程序共用,Authorization: Bearer <token>。