文档目录
目录结构设计

简介

本文件面向 DouPHP 小程序的目录结构设计,聚焦 miniprogram 下的 company 与 default 两个版本。文档从职责划分、文件命名规范、页面/组件/服务/状态管理/工具等模块的组织方式入手,解释两套版本的差异与适用场景,并给出最佳实践建议,帮助开发者快速理解并正确组织小程序代码结构。

项目结构

DouPHP 小程序采用“按能力分层 + 按业务域分目录”的混合组织方式:

  • pages:页面目录,每个业务域一个子目录(如 product、order、user),页面内包含 .ts/.wxml/.wxss/.json 四件套。
  • components:可复用 UI 组件(如 mp-html、navbar)。
  • services:网络请求、上传、验证码、权限等业务服务封装。
  • stores:基于 MobX 的状态管理(auth、cart、common、persist 等)。
  • utils:通用工具函数(路由、格式化、国际化、环境判断、标题、推广、TabBar 等)。
  • config:站点级运行配置(site.ts)与设置(setting.php)。
  • style:全局样式与第三方样式(如 weui.wxss、iconfont.wxss)。
  • types:类型声明(api.d.ts、store.d.ts、wx-ext.d.ts)。
  • images:静态资源图片。
  • libs:第三方库或类型定义(如 mobx-miniprogram、miniprogram-api-typings)。
  • 根级配置文件:app.json、app.ts、app.wxss、project.config.json、sitemap.json、tsconfig.json。
graph TB
A["小程序根目录"] --> B["pages 页面目录"]
A --> C["components 组件目录"]
A --> D["services 服务层"]
A --> E["stores 状态管理"]
A --> F["utils 工具函数"]
A --> G["config 站点配置"]
A --> H["style 全局样式"]
A --> I["types 类型声明"]
A --> J["images 静态资源"]
A --> K["libs 第三方库"]
A --> L["根配置 app.json / app.ts / app.wxss"]

核心组件

  • 应用入口 app.ts:统一初始化 HTTP 拦截器、引导全局 store、解析推广参数、自动更新、全局错误钩子、设备信息计算等。
  • 网络服务 services/http.ts:统一信封解析、默认头注入、拦截器机制、缓存与去重、调试增强、RESTful 方法伪装。
  • 站点配置 config/site.ts:由后台整文件覆盖的运行时配置(root_url、mp_url、rewrite_enable、debug_enable、douLoading)。
  • 页面组织 pages/*:以业务域为维度组织页面,每个页面遵循 ts/wxml/wxss/json 四件套。
  • 状态管理 stores/*:基于 MobX 的全局状态(认证、购物车、通用数据、持久化等)。
  • 工具 utils/*:提供路由、UI、格式化、国际化、环境判断、推广、标题、TabBar 等能力。

架构总览

小程序启动流程与关键交互如下:

  • App.onLaunch:注册 HTTP 错误拦截(UNAUTHORIZED 登出)、解析推广参数、引导全局 store、计算导航栏高度、开启自动更新、调试模式开关。
  • 页面加载:通过 services/http.ts 发起 API 请求,统一信封解析后返回 data;失败时抛出 ApiError,支持缓存与去重。
  • 状态管理:stores 提供全局状态,页面通过绑定使用,实现跨页面共享与响应式更新。
  • 站点配置:config/site.ts 暴露 root_url/mp_url 等,供各层直接引用。
sequenceDiagram
participant U as "用户"
participant APP as "App(app.ts)"
participant HTTP as "HTTP服务(services/http.ts)"
participant STORE as "Stores(stores/*)"
participant PAGE as "页面(pages/*)"
U->>APP : 启动小程序
APP->>APP : 注册HTTP错误拦截(UNAUTHORIZED)
APP->>APP : 解析推广参数(user_sn)
APP->>STORE : bootstrapStores()
APP->>APP : 计算导航栏高度/自动更新/调试开关
U->>PAGE : 打开首页
PAGE->>HTTP : GET /index (带缓存/去重)
HTTP-->>PAGE : data<T> 或 ApiError
PAGE->>STORE : 更新本地状态
PAGE-->>U : 渲染界面

详细组件分析

应用入口(app.ts)

  • 职责:统一初始化 HTTP 拦截器、引导全局 store、解析推广参数、自动更新、全局错误钩子、设备信息计算。
  • 关键点:
    • UNAUTHORIZED 统一登出:在 HTTP 错误回调中触发 authStore.logout()。
    • 推广解析:兼容 scene 与 query 中的 user_sn,写入本地存储。
    • 设备信息:计算 statusBarHeight、navigationBarHeight 等,用于自定义导航栏布局。
    • 自动更新:检测新版本并提示重启。
    • 调试模式:非正式版开启 vConsole。
flowchart TD
Start(["App.onLaunch"]) --> InitHttp["注册HTTP错误拦截<br/>UNAUTHORIZED -> logout"]
InitHttp --> ParsePromo["解析推广参数 user_sn"]
ParsePromo --> Bootstrap["引导全局 store"]
Bootstrap --> DeviceInfo["计算导航栏高度等"]
DeviceInfo --> AutoUpdate["检查并提示更新"]
AutoUpdate --> DebugMode{"是否调试环境?"}
DebugMode --> |是| EnableDebug["开启vConsole"]
DebugMode --> |否| End(["完成"])
EnableDebug --> End

网络服务(services/http.ts)

  • 职责:统一信封解析、默认头注入、拦截器机制、缓存与去重、调试增强、RESTful 方法伪装。
  • 关键点:
    • 信封解析:code === 'OK' 视为成功,否则构造 ApiError。
    • 默认头:Content-Type=application/x-www-form-urlencoded、Authorization: Bearer &lt;api_token>。
    • 缓存与去重:内存缓存(ttl)、GET 去重(inflight)。
    • 调试:request_id 装饰、服务端异常弹窗(仅调试环境)。
    • RESTful:PUT/DELETE 通过 _method 伪装。
classDiagram
class Http {
+get(url, data, opts) Promise
+post(url, data, opts) Promise
+put(url, data, opts) Promise
+del(url, data, opts) Promise
+request(config, opts) Promise
+clearCache(prefix) void
+onRequest(fn) void
+onSuccess(fn) void
+onError(fn) void
}
class ApiError {
+code string
+statusCode number
+errors object
+data object
+request_id string
}
Http --> ApiError : "构造/抛出"

站点配置(config/site.ts)

  • 职责:暴露站点级运行数据(root_url、mp_url、rewrite_enable、debug_enable、douLoading),由后台整文件覆盖。
  • 使用方式:业务侧直接 import 引用,无需额外薄壳。

页面组织(pages/*)

  • 组织方式:按业务域划分目录(如 product、order、user),每个页面包含 .ts/.wxml/.wxss/.json。
  • 示例:首页 index 页面通过 http.get 获取数据,结合 stores 进行状态绑定与展示。

依赖关系分析

  • app.ts 依赖 services/http.ts、stores/*、utils/env.js、utils/promotion.js、config/site.ts。
  • 页面依赖 services/http.ts、stores/、utils/。
  • services/http.ts 依赖 types/api.d.ts、utils/env.js。
  • 配置 site.ts 被 app.ts 与各层直接引用。
graph LR
APP["app.ts"] --> HTTP["services/http.ts"]
APP --> STORES["stores/*"]
APP --> UTILS["utils/*"]
APP --> CONFIG["config/site.ts"]
PAGE["pages/*"] --> HTTP
PAGE --> STORES
PAGE --> UTILS
HTTP --> TYPES["types/api.d.ts"]

性能考量

  • 网络层优化:
    • 内存缓存与 TTL:减少重复请求,提升首屏速度。
    • GET 去重:避免并发重复请求。
    • 信封解析与错误分类:统一处理,降低业务分支复杂度。
  • 启动优化:
    • 延迟加载第三方框架,避免阻塞首帧。
    • 按需启用调试功能(vConsole),生产环境关闭。
  • 渲染优化:
    • 动态计算导航栏高度,适配不同设备。
    • 合理使用 setData 与 store 绑定,减少频繁更新。

故障排查指南

  • 未捕获 JS 异常:App.onError 记录日志,调试期弹出 modal。
  • 页面不存在:App.onPageNotFound 记录路径,调试期弹出 modal。
  • 接口错误:ApiError 携带 code/message/errors/request_id,调试期弹窗显示服务端异常堆栈。
  • 认证失效:HTTP 错误码 UNAUTHORIZED 触发统一登出。

结论

DouPHP 小程序采用清晰的分层与模块化组织,通过统一的网络层、状态管理与配置中心,实现了高内聚、低耦合的代码结构。company 与 default 两套版本在页面清单与主题色上存在差异,但整体架构一致,便于维护与扩展。建议遵循本文档的目录规范与最佳实践,确保代码可读性与可维护性。

附录

company 与 default 版本差异与适用场景

  • 差异点:
    • 主题色:default 的 tabBar 选中色为红色系,company 为蓝色系。
    • 页面清单:两者均包含相同业务域页面,具体以 app.json 的 pages 数组为准。
  • 适用场景:
    • default:适用于通用模板或演示场景。
    • company:适用于企业定制版,品牌色与企业标识更贴合。

目录与文件命名规范

  • 页面目录:pages/&lt;业务域>/&lt;页面名>,每个页面包含 .ts/.wxml/.wxss/.json。
  • 组件目录:components/&lt;组件名>,组件内同样遵循四件套。
  • 服务层:services/&lt;能力>.ts,如 http.ts、upload.ts、captcha.ts。
  • 状态管理:stores/&lt;领域>.ts,如 auth.ts、cart.ts、common.ts。
  • 工具函数:utils/&lt;工具>.ts,如 route.ts、format.ts、i18n.ts。
  • 配置:config/site.ts 由后台整文件覆盖,勿手动修改。
  • 样式:style/*.wxss,集中管理全局样式与第三方样式。
  • 类型:types/*.d.ts,集中声明类型。

设计原则与最佳实践

  • 单一职责:每个模块只负责一件事,保持高内聚。
  • 明确边界:页面只关注视图与交互,逻辑下沉至 services/stores/utils。
  • 可测试性:网络层与工具函数独立,便于单元测试。
  • 可配置性:站点配置集中管理,支持后台动态覆盖。
  • 可扩展性:新增业务域只需在 pages 下新建目录,并在 app.json 注册。
添加日期:2026-10-05