简介
本文件面向 DouPHP 小程序端的工具类组件,系统化梳理并文档化以下能力:
- 日期与数字格式化
- 验证码倒计时控制
- 统一 HTTP 请求封装(信封解析、缓存/去重、拦截器、调试)
- 本地存储与鉴权联动(登录态校验)
- 路由生成与 URL 拼接
- UI 辅助(提示、跳转、分享菜单)
- 国际化字符串读取
- TabBar 运行时判定
目标读者包括前端开发者与后端接入者,帮助快速理解各工具函数的使用方法、参数说明、返回值格式,并提供实际使用场景的参考路径与最佳实践。
项目结构
DouPHP 小程序端工具集中在 miniprogram/default/utils 与 miniprogram/default/services 两个目录:
- utils:通用工具函数(格式化、倒计时、环境探测、路由、UI、URL、国际化、TabBar)
- services:业务级服务封装(HTTP 网络层、文件上传)
graph TB
subgraph "工具(utils)"
F["format.ts<br/>数字/时间格式化"]
C["countdown.ts<br/>验证码倒计时"]
E["env.ts<br/>运行环境探测"]
R["route.ts<br/>命名路由生成"]
U["ui.ts<br/>toast/跳转/分享"]
UR["url.ts<br/>历史URL拼接(弃用)"]
I["i18n.ts<br/>语言包读取"]
T["tabbar.ts<br/>TabBar运行时判定"]
end
subgraph "服务(services)"
H["http.ts<br/>统一HTTP层"]
UP["upload.ts<br/>文件上传/删除"]
end
H --> E
H --> R
UP --> H
UP --> R
U --> T
U --> R
核心组件
- 数据格式化:format.ts 提供数字补零与时间格式化,保证展示一致性。
- 倒计时:countdown.ts 提供验证码按钮倒计时,自动管理定时器与页面状态。
- 网络请求:services/http.ts 提供统一 HTTP 层,支持信封解析、缓存/TTL、请求去重、拦截器、调试增强。
- 文件上传:services/upload.ts 封装选图、上传、删除流程,并与鉴权联动。
- 路由与URL:utils/route.ts 提供命名路由生成;utils/url.ts 保留历史兼容。
- UI 辅助:utils/ui.ts 提供 toast、跳转策略、分享菜单等。
- 国际化:utils/i18n.ts 提供运行时语言包读取。
- 环境探测:utils/env.ts 提供开发/生产环境判断与服务端调试开关。
- TabBar:utils/tabbar.ts 提供运行时 TabBar 判定,避免硬编码。
架构总览
小程序工具层以“服务 + 工具”分层组织:
- 服务层(services):对外暴露稳定接口(如 http.get/post、upload.filebox),内部复用工具与配置。
- 工具层(utils):无副作用或低耦合的纯函数,供服务层与页面调用。
sequenceDiagram
participant Page as "业务页面"
participant Http as "http.ts"
participant Env as "env.ts"
participant Route as "route.ts"
participant Wx as "微信API"
Page->>Http : 调用 get/post/put/del
Http->>Env : isDebugEnv()
Http->>Wx : wx.request(...)
Wx-->>Http : success/fail
Http->>Http : 解析信封/缓存/去重/拦截器
Http-->>Page : Promise<T> 或 ApiError
Note over Page,Http : 错误时记录 request_id,便于追踪
详细组件分析
数据格式化(format.ts)
- 功能
- formatNumber(n): 将数字转为两位字符串,不足补前导零。
- formatTime(date): 将 Date 对象格式化为 "YYYY/M/D HH:MM:SS"。
- 参数与返回
- formatNumber: 入参 number;返回 string。
- formatTime: 入参 Date;返回 string。
- 使用场景
- 列表时间列统一显示格式。
- 表单输入框数值对齐显示。
- 复杂度
- O(1) 时间与空间。
验证码倒计时(countdown.ts)
- 功能
- captchaCountdown(page, options): 为 Page 实例注入 start/stop 方法,驱动 data.countdown 字段变化。
- 参数与返回
- page: WechatMiniprogram.Page.TrivialInstance。
- options.field: 可选,绑定的 data 字段名,默认 'countdown'。
- options.seconds: 可选,默认秒数,默认 60。
- 返回: { start(seconds?), stop(): void }。
- 使用示例(概念性)
- onLoad: this.countdown = captchaCountdown(this)
- 发送成功后: this.countdown.start(60)
- onUnload: this.countdown.stop()
- 注意事项
- 确保在页面卸载时停止定时器,避免内存泄漏。
统一 HTTP 层(services/http.ts)
- 职责
- 信封解析:code === 'OK' 视为成功,否则抛出 ApiError。
- 默认头注入:Content-Type=application/x-www-form-urlencoded、Authorization: Bearer <api_token>。
- 拦截器:onRequest/onSuccess/onError。
- 去重:相同 GET 在飞行中复用同一 Promise。
- 缓存+TTL:opts.cache 命中且未过期直接返回;opts.revalidate 强制刷新。
- 调试:request_id 装饰、Console/vConsole 打点、服务端异常 modal(仅调试环境)。
- 关键类型
- RequestConfig: url/data/method/header/responseType。
- RequestOpts: cache/ttl/revalidate/dedupe。
- ApiError: code/statusCode/errors/data/request_id。
- 主要 API
- request(config, opts?): Promise<T>
- get/post/put/del(url, data?, opts?)
- clearCache(prefix?)
- getLastRequestId(): string
- http.onRequest/onSuccess/onError(fn)
- 流程图(请求生命周期)
flowchart TD
Start(["进入 request"]) --> BuildCfg["构建默认请求配置<br/>注入Header/Token"]
BuildCfg --> Interceptors{"执行请求拦截器"}
Interceptors --> CacheCheck{"启用缓存且未revalidate?"}
CacheCheck --> |是| HitCache["命中内存缓存直接返回"]
CacheCheck --> |否| DedupeCheck{"GET且去重开启且有进行中请求?"}
DedupeCheck --> |是| ReusePromise["复用进行中Promise"]
DedupeCheck --> |否| DoRequest["发起wx.request"]
DoRequest --> Success{"HTTP状态码2xx?"}
Success --> |否| ParseHttpErr["解析信封构造ApiError"]
ParseHttpErr --> ErrorIntercept["执行错误拦截器"]
ErrorIntercept --> Reject["reject(ApiError)"]
Success --> |是| ParseBody["解析信封"]
ParseBody --> Ok{"code==='OK'?"}
Ok --> |否| BizErr["构造业务ApiError"]
BizErr --> ErrorIntercept
Ok --> |是| AttachMeta["附加__message/__request_id"]
AttachMeta --> SaveCache["写入内存缓存(若启用)"]
SaveCache --> SuccessIntercept["执行成功拦截器"]
SuccessIntercept --> Resolve["resolve(data)"]
HitCache --> Resolve
ReusePromise --> Resolve
文件上传与删除(services/upload.ts)
- 功能
- filebox(params, callback): 选择图片并上传至 user/filebox,回调返回 img_list。
- fileDel(params, callback): 删除已上传图片,回调返回剩余 img_list。
- 参数与返回
- params.dataset.type/module/item_id/folder/draft_token: 上传元信息。
- params.dataset.number: 删除的文件编号。
- callback(imgList): 回调返回图片数组。
- 鉴权联动
- 先 authStore.ensureLogin(),未登录自动跳转登录页。
- 使用场景
- 商品详情多图上传、草稿箱附件上传。
命名路由生成(utils/route.ts)
- 功能
- route(name, params?): 根据后台同步的路由表生成最终 URL,支持占位符替换与 query 拼接。
- 行为
- 当 rewrite_enable 关闭时回退 index.php?route= 形态。
- 缺失路由键抛错,便于早期发现。
- 使用场景
- 所有页面跳转与外链生成统一走此函数,避免硬编码路径。
历史 URL 拼接(utils/url.ts)
- 功能
- douUrl(module, ...args): 历史兼容的 URL 拼接工具,已标记弃用。
- 建议
- 新代码一律改用 route(name, params)。
UI 辅助(utils/ui.ts)
- 功能
- douGetCurrentPages(): 获取当前页带参数的相对路径。
- douPageTo(url): 智能跳转(已在栈内则回退;tabBar 页 switchTab;其余 redirectTo)。
- douMsg(message, url='back', time=2000): 提示后按规则跳转。
- showShareMenu(): 开启转发与朋友圈分享。
- 使用场景
- 操作反馈与导航一体化,减少重复逻辑。
国际化读取(utils/i18n.ts)
- 功能
- lang(key, fallback?): 从 commonStore.lang 读取译串,未命中返回 fallback 或 key。
- 使用场景
- wx.showModal / wx.showToast 等运行时提示文案。
运行环境探测(utils/env.ts)
- 功能
- isDebugEnv(): 非正式版(develop/trial)返回 true,release 恒 false。
- isServerDebug(): 镜像 site.ts 的 debug_enable,用于服务端调试开关。
- 使用场景
- 仅在调试环境打印日志或弹出堆栈提示。
TabBar 运行时判定(utils/tabbar.ts)
- 功能
- normalizePagePath(p): 规范化页面路径(去前缀斜杠、去查询串、去渲染后缀)。
- resolveTabIndex(pagePath): 返回 tabBar.list 中的真实下标,不在则 -1。
- isTabBarPath(pagePath): 是否 tabBar 页。
- 使用场景
- 决定跳转方式(switchTab vs redirectTo/navigateTo),避免写死路径白名单。
依赖关系分析
- http.ts 依赖 env.ts(调试开关)、route.ts(可选,用于生成 URL)、微信 API。
- upload.ts 依赖 http.ts、route.ts、authStore(鉴权)。
- ui.ts 依赖 tabbar.ts(TabBar 判定)、route.ts(跳转目标)。
- route.ts 依赖 site.ts 配置(mp_url、rewrite_enable)与 routes.generated.ts。
- i18n.ts 依赖 commonStore(语言包)。
graph LR
HTTP["http.ts"] --> ENV["env.ts"]
HTTP --> ROUTE["route.ts"]
UPLOAD["upload.ts"] --> HTTP
UPLOAD --> ROUTE
UI["ui.ts"] --> TABBAR["tabbar.ts"]
UI --> ROUTE
性能考虑
- 网络请求
- 合理使用 cache 与 ttl 降低重复请求;对热点列表数据可设置较长 TTL。
- 利用 dedupe 避免并发重复请求,减少服务器压力。
- 使用 revalidate 实现 SWR 模式,兼顾时效性与性能。
- 内存与定时器
- 倒计时务必在页面卸载时 stop,防止内存泄漏。
- 清理 http.clearCache 避免长期驻留大对象。
- 渲染与跳转
- 使用 isTabBarPath 动态决策跳转方式,避免写死导致的不必要重绘。
- 批量 setData 减少频繁更新。
- 调试开销
- 仅在 isDebugEnv 下执行额外日志与弹窗,生产环境保持静默。
故障排查指南
- 网络请求失败
- 检查 ApiError.code 与 statusCode,定位 HTTP 错误或业务错误。
- 通过 getLastRequestId() 与服务端日志对照。
- 在调试环境查看可能弹出的服务端异常堆栈。
- 缓存问题
- 确认是否设置了 cache/revalidate;必要时调用 clearCache(prefix) 清理。
- 跳转异常
- 使用 isTabBarPath 判断是否为 tabBar 页,再选择 switchTab/redirectTo。
- 使用 route() 生成 URL,避免手写路径不一致。
- 倒计时不生效
- 确认 field 绑定正确,且在 onUnload 中调用 stop。
- 国际化缺失
- 确认 commonStore.lang 已加载,lang(key, fallback) 提供兜底文案。
结论
DouPHP 小程序工具类组件围绕“稳定、可观测、可扩展”的目标设计:
- 通过统一 HTTP 层屏蔽底层差异,提供缓存、去重、拦截器与调试能力。
- 工具函数聚焦单一职责,便于复用与测试。
- 借助运行时 TabBar 判定与命名路由,提升可维护性与跨站点适配能力。 建议在业务中优先采用这些工具,遵循本文的最佳实践以获得更稳定的体验与更高的性能。
附录:扩展与自定义规范
- 新增工具函数
- 放在 utils 下,保持无副作用或最小副作用,明确入参与返回值类型。
- 如需访问配置,优先从 config/site.ts 读取,避免 getApp().mp_url。
- 扩展 HTTP 层
- 通过 http.onRequest/onSuccess/onError 注册拦截器,集中处理认证、埋点、重试等。
- 对特定模块可封装专用 service,复用 http 与 route。
- 自定义上传流程
- 基于 upload.ts 扩展新的业务字段,保持鉴权前置。
- 路由与 URL
- 统一使用 route(name, params),不再手写路径;历史兼容仅限过渡期。
- 国际化
- 新增 key 需同步到语言包,并在 i18n.ts 侧提供 fallback 保障。
- 调试与监控
- 使用 isDebugEnv 控制调试输出;结合 getLastRequestId 进行问题追踪。