文档目录
小程序模块

简介

本文档面向 DouPHP 小程序模块开发者,系统说明小程序的整体架构、页面与组件体系、状态管理、与主站 API 的数据同步机制、功能模块实现要点、样式与主题、以及发布与版本管理。目标是帮助开发者快速理解并高效扩展小程序能力。

项目结构

小程序代码位于 miniprogram 目录下,默认模板为 default,企业版模板为 company。以 default 为例:

  • app.json:页面注册、全局窗口配置、tabBar、全局组件注册等
  • app.ts:应用生命周期、全局错误处理、自动更新、推广解析、Store 引导
  • config/site.ts:站点运行期配置(根域名、API 地址、调试开关等)
  • services/http.ts:统一 HTTP 层(信封解析、拦截器、缓存、去重、错误封装)
  • stores/*:基于 MobX 的状态管理(认证、购物车、通用信息等)
  • pages/*:按业务域划分的页面集合(首页、商品、订单、用户中心等)
  • components/*:可复用组件(如 navbar、mp-html)
  • utils/*:工具函数(路由、格式化、国际化、UI 提示等)
  • style/*:全局样式与第三方样式(WeUI、图标等)
graph TB
A["小程序入口<br/>app.ts"] --> B["HTTP 层<br/>services/http.ts"]
A --> C["状态管理聚合<br/>stores/index.ts"]
C --> D["认证 Store<br/>stores/auth.ts"]
C --> E["购物车 Store<br/>stores/cart.ts"]
A --> F["站点配置<br/>config/site.ts"]
G["页面<br/>pages/*"] --> B
G --> C
H["组件<br/>components/*"] --> G
I["工具<br/>utils/*"] --> G

核心组件

  • 统一 HTTP 层(services/http.ts)
    • 标准信封解析:code/message/data/errors/request_id
    • 请求拦截器/成功拦截器/错误拦截器
    • 内存缓存 + TTL + SWR(revalidate)
    • GET 请求去重(inflight)
    • 统一错误类型 ApiError,附带 request_id 便于追踪
    • 提供 get/post/put/del/clearCache 等方法
  • 状态管理(stores/*)
    • authStore:登录态持久化、恢复、鉴权标志位、登出清理
    • cartStore:购物车数据与 tabBar 角标联动
    • commonStore:站点信息、语言、特性开关、导航等
    • bootstrapStores:启动时先 hydrate(秒开),再 refresh(网络刷新)
  • 应用入口(app.ts)
    • onLaunch:注册 http.onError 统一未授权登出;解析推广 user_sn;初始化全局尺寸;自动更新;开启 vConsole(调试)
    • onError/onUnhandledRejection/pageNotFound:全局异常与调试弹窗
  • 站点配置(config/site.ts)
    • root_url/mp_url:后端根地址与 API 地址
    • debug_enable/rewrite_enable/douLoading:运行时开关

架构总览

小程序通过统一的 HTTP 层访问后端 API,使用 MobX 进行跨页面状态共享,页面按需订阅 store 变化。应用启动时完成环境探测、推广参数解析、store 预热与网络刷新,保证首屏体验与一致性。

sequenceDiagram
participant U as "用户"
participant P as "页面<br/>pages/index/index.ts"
participant S as "HTTP 层<br/>services/http.ts"
participant R as "路由/控制器<br/>api/route/*.php"
participant M as "状态管理<br/>stores/*"
U->>P : 打开首页
P->>S : http.get(route('index'))
S->>R : 发起请求携带 Authorization
R-->>S : 返回信封 {code,message,data,...}
S-->>P : 解析后返回 data
P->>M : 更新视图数据
Note over P,S : 支持缓存/去重/拦截器

详细组件分析

统一 HTTP 层(services/http.ts)

  • 职责
    • 信封解析:仅接受 code/message/data/errors/request_id 的标准格式
    • 默认头注入:Content-Type 与 Authorization(Bearer api_token)
    • 拦截器:onRequest/onSuccess/onError,可扩展
    • 缓存与去重:GET 可选 cache/ttl/revalidate;相同请求飞行中复用 Promise
    • 错误处理:统一 ApiError,包含 code/statusCode/errors/data/request_id
  • 关键流程
    • 命中内存缓存且未过期直接返回
    • 非 2xx 或业务码非 OK 走错误拦截器链
    • 成功响应附加不可枚举元信息 message/request_id 便于调试
    • 提供 clearCache(prefix?) 按前缀清空缓存
flowchart TD
Start(["进入 request"]) --> CheckCache{"是否启用缓存且命中?"}
CheckCache --> |是| ReturnCache["返回缓存数据"]
CheckCache --> |否| Dedupe{"是否 GET 且飞行中?"}
Dedupe --> |是| Reuse["复用 inflight Promise"]
Dedupe --> |否| DoReq["发起 wx.request"]
DoReq --> Resp{"HTTP 状态码 2xx?"}
Resp --> |否| ParseHttp["解析信封并构造 ApiError"]
ParseHttp --> ErrChain["执行错误拦截器"]
ErrChain --> Reject["reject(ApiError)"]
Resp --> |是| ParseBody["解析信封"]
ParseBody --> Ok{"code === 'OK'?"}
Ok --> |否| BizErr["构造业务 ApiError"]
BizErr --> ErrChain
Ok --> |是| AttachMeta["附加 __message/__request_id"]
AttachMeta --> CacheWrite{"是否写入缓存?"}
CacheWrite --> |是| Write["写入 memoryCache"]
CacheWrite --> |否| Skip["跳过缓存"]
Write --> Success["resolve(data)"]
Skip --> Success
Reuse --> Success
ReturnCache --> End(["结束"])
Reject --> End
Success --> End

认证与登录态(stores/auth.ts)

  • 存储真相源:api_token、user_id、loginEd
  • 能力降级:当 commonStore.features.user === false 时,is_login 恒为 false,避免无效请求
  • 恢复流程:优先从 storage 读取,再调用 user/index 获取最新鉴权标志位
  • 登录/登出:写入/清除 storage,并同步 store 状态;登出同时清理推广 user_sn
  • ensureLogin:未登录则跳转默认登录页
sequenceDiagram
participant App as "App"
participant Auth as "authStore"
participant Http as "http"
participant API as "user/index"
App->>Auth : hydrate()
App->>Auth : restore()
Auth->>API : http.get(user/index)
API-->>Auth : {dou.auth : {is_login,...}}
Auth->>Auth : applyAuthFlags(...)
Note over Auth : 若 UNAUTHORIZED 则清空 is_login

首页与商品列表(pages/index/index.ts)

  • 加载站点信息与分类,展示轮播与分类横滑进度条
  • 分页加载商品列表,触底追加
  • 根据工作身份(is_work)在工作台与首页间跳转
  • 使用 route('product') 动态生成接口路径
sequenceDiagram
participant Page as "首页"
participant Http as "http"
participant Route as "route()"
Page->>Route : route('index')
Route-->>Page : /api/?route=index
Page->>Http : http.get(index)
Http-->>Page : {product_category,...}
Page->>Route : route('product')
Route-->>Page : /api/?route=product
Page->>Http : http.get(product, {id : 0, page})
Http-->>Page : {product_list : [...]}
Page->>Page : setData({product_list,...})

小程序与主站数据同步机制

  • 路由与命名空间
    • 小程序通过 utils/route 将业务名映射到 /api/?route=xxx
    • 后端路由文件位于 api/route/*.php,声明式定义各模块的 GET/POST 动作
  • 认证与鉴权
    • 请求头 Authorization: Bearer &lt;api_token>
    • 服务端对未授权返回 UNAUTHORIZED,前端统一触发登出
  • 数据信封
    • 统一 {code,message,data/errors,request_id} 格式
    • 成功时 code='OK',失败时携带 errors 与 request_id 便于定位
  • 缓存策略
    • 内存级 GET 缓存(可配置 ttl/revalidate)
    • 适合静态或低频变动的数据(如站点信息、分类)
    • 写操作后建议调用 http.clearCache(prefix) 失效相关缓存

依赖关系分析

  • 入口依赖
    • app.ts 依赖 http、stores、site、promotion、env 等
  • 页面依赖
    • 页面通过 http 访问后端,通过 stores 共享状态,通过 utils 辅助
  • 后端依赖
    • api/route/*.php 声明式路由,指向具体控制器
  • 配置依赖
    • config/config.php 定义 MINIPROGRAM_DIR、DOU_APP_KEY、DOU_DEBUG 等
    • config/module.php 控制模块显示与菜单可见性
graph LR
App["app.ts"] --> Http["services/http.ts"]
App --> Stores["stores/index.ts"]
Stores --> Auth["stores/auth.ts"]
Stores --> Cart["stores/cart.ts"]
Pages["pages/*"] --> Http
Pages --> Stores
Http --> Routes["api/route/*.php"]
Config["config/*.php"] --> App

性能与缓存策略

  • 首屏优化
    • bootstrapStores 先 hydrate(storage 秒开),再 refresh(网络刷新)
    • 全局尺寸与导航栏高度在 onLaunch 计算并缓存至 globalData
  • 请求优化
    • GET 去重:相同请求在飞行中复用同一 Promise
    • 内存缓存:可配置 ttl,支持 revalidate 强制刷新
    • 拦截器:集中处理鉴权、日志、错误提示
  • 渲染优化
    • 使用 store 绑定减少重复 setData
    • 列表分页加载与触底追加,避免一次性拉取大量数据
  • 调试与监控
    • 调试模式开启 vConsole,错误弹窗提示
    • 每个请求附带 request_id,便于前后端联调

开发指南与示例

创建新页面

  • 在 app.json 的 pages 数组中注册页面路径
  • 在 pages/&lt;feature>/ 下创建 .ts/.wxml/.wxss/.json 四件套
  • 如需 tab 页,需在 tabBar.list 中添加对应条目与图标

添加新功能(页面内调用 API)

  • 使用 http.get/post 调用后端接口
  • 通过 route('xxx') 生成稳定路径,避免硬编码
  • 使用 stores 管理跨页面状态(如 authStore.is_login)

自定义组件

  • 在 components/ 下新建组件目录,并在 app.json 的 usingComponents 中注册
  • 推荐复用现有 navbar、mp-html 等组件

用户登录流程(微信登录)

  • 调用 user/weixin/login 获取会话凭证
  • 成功后调用 authStore.login 持久化 token 与用户标识
  • 后续请求由 http 自动注入 Authorization 头

商品浏览与分页

  • 使用 route('product') 获取商品列表
  • 维护 page/nomore/loadpage 状态,实现触底加载更多

订单管理

  • 订单相关页面位于 pages/order/*,涉及下单、支付、查询、工作台等
  • 通过 http 调用 order 模块接口,结合 cartStore 与 authStore 完成下单流程

个人中心

  • 用户中心位于 pages/user/*,涵盖资料编辑、密码修改、联系方式管理等
  • 通过 user 模块接口实现数据读写

样式系统与主题定制

  • 全局样式
    • app.wxss 作为全局样式入口
    • style/* 存放 WeUI、图标字体等公共样式
  • 组件样式
    • 页面与组件各自维护 wxss,遵循模块化
  • 主题定制
    • 可通过替换 images/tabbar_* 等图标资源实现主题切换
    • 在 app.json 的 tabBar 中配置选中/未选中图标与颜色
  • 响应式布局
    • 使用 rpx 单位适配不同屏幕
    • 利用 globalData 中的 statusBarHeight/navigationBarHeight 做顶部安全区适配

发布流程与版本管理

  • 本地调试
    • 使用微信开发者工具导入 miniprogram/default
    • 在 site.ts 中配置 mp_url 指向后端 API
    • 调试模式开启 vConsole,便于查看请求与错误
  • 构建与上传
    • 在开发者工具中点击“编译”、“预览”、“上传”
    • 确保 app.json 中 pages 与 tabBar 配置正确
  • 自动更新
    • 应用内置自动更新逻辑,检测到新版本会提示用户重启
  • 版本回滚
    • 通过微信公众平台管理小程序版本,必要时回滚到上一版本

故障排查

  • 常见错误
    • UNAUTHORIZED:检查 api_token 是否存在且有效,确认后端鉴权中间件
    • NETWORK_ERROR:检查网络环境与 mp_url 配置
    • HTTP_5xx:查看服务端日志,结合 request_id 定位
  • 调试技巧
    • 开启 vConsole,观察请求与响应
    • 使用 http.getLastRequestId() 获取最近一次请求 ID
    • 在错误拦截器中打印上下文信息
  • 缓存问题
    • 写操作后调用 http.clearCache(prefix) 失效相关缓存
    • 使用 revalidate 强制刷新热点数据

结论

DouPHP 小程序模块采用统一 HTTP 层与 MobX 状态管理,具备完善的缓存、去重、拦截器与错误处理能力。通过声明式路由与标准信封协议,前后端解耦清晰。开发者可基于现有组件与工具快速扩展页面与功能,并通过主题与样式定制满足多样化需求。配合自动更新与调试能力,保障线上质量与迭代效率。

添加日期:2026-10-05