hookehuyr

docs: 重构 README 文档以提供更清晰的项目概览与架构说明

- 将项目介绍重构为更清晰的功能概览与技术栈说明
- 详细阐述项目结构、关键实现(如认证、离线兜底)与可复用能力
- 增加项目优缺点分析与明确的后续优化建议
- 移除过时的优化建议条目,更新为当前状态
Showing 1 changed file with 139 additions and 125 deletions
1 -## 项目介绍 1 +# 西园寺预约微信小程序(xyxBooking-weapp)
2 - 2 +
3 -本项目是将原有H5预约系统迁移至微信小程序的实现。基于 Taro4 + Vue3 + NutUI 开发,保留了原有的功能和UI风格。 3 +将原有 H5 预约系统迁移至微信小程序的实现,基于 Taro 4 + Vue 3 + NutUI 开发,保留原有业务流程与 UI 风格,并补充了弱网/离线兜底能力。
4 - 4 +
5 -## 功能模块 5 +## 功能概览
6 - 6 +
7 -1. **预约流程** 7 +- 预约流程:须知 -> 日期/时段选择 -> 选择参观者 -> 提交订单 -> 支付 -> 查看预约码与记录
8 - * 日期与时间段选择 (`pages/booking/index`) 8 +- 参观者管理:新增/删除参观者、证件号校验、脱敏展示
9 - * 预约信息确认与提交 (`pages/submit/index`) 9 +- 预约码展示:我的当日预约码、预约记录详情中的预约码
10 - * 预约记录查看 (`pages/bookingList/index`) 10 +- 证件号查询:通过身份证号查询预约码(用于识别进闸机)
11 - * 预约详情 (`pages/bookingDetail/index`) 11 +- 弱网/离线模式:弱网提示、离线预约记录列表/详情、离线预约码
12 - 12 +- 义工核销:义工登录(权限预检)-> 扫码核销 -> 展示核销结果
13 -2. **参观者管理**
14 - * 参观者列表 (`pages/visitorList/index`)
15 - * 添加/编辑参观者 (`pages/addVisitor/index`)
16 - * 支持身份证号校验与脱敏显示
17 -
18 -3. **个人中心**
19 - * 预约码展示 (`pages/bookingCode/index`)
20 - * 我的页面 (`pages/me/index`)
21 - * 邀请码/证件号查询 (`pages/search/index`)
22 -
23 -4. **弱网与离线模式**
24 - * 弱网提示页 (`pages/weakNetwork/index`)
25 - * 离线预约记录列表 (`pages/offlineBookingList/index`)
26 - * 离线预约记录详情/离线二维码 (`pages/offlineBookingDetail/index`)
27 - * 离线预约码入口页 (`pages/offlineBookingCode/index`)
28 - * 离线预约缓存刷新与轮询 (`src/composables/useOfflineBookingCache.js`, `src/composables/useOfflineBookingCachePolling.js`)
29 - * 网络从可用变为弱网/无网时,弹窗提示并可一键进入离线模式(`src/app.js`
30 -
31 -5. **义工核销**
32 - * 义工登录与权限预检 (`pages/volunteerLogin/index`)
33 - * 核销页(扫码核销 + 结果展示)(`pages/verificationResult/index`)
34 -
35 -6. **公共功能**
36 - * 全局路由封装 (`hooks/useGo`)
37 - * API 请求封装 (`utils/request`, `api/index`)
38 - * 登录授权流程 (`pages/auth/index`)
39 - * 弱网提示文案统一管理 (`utils/uiText.js`)
40 13
41 ## 技术栈 14 ## 技术栈
42 15
43 -* **框架**: Taro 4.x 16 +- 框架:Taro 4.1.9 + Vue 3(setup 语法糖)
44 -* **UI库**: NutUI 4.x (Vue3) 17 +- UI:NutUI 4(@nutui/nutui-taro + icons-vue-taro)
45 -* **语言**: JavaScript (Vue3 Setup 语法糖) 18 +- 状态管理:Pinia(taro-plugin-pinia)
46 -* **样式**: Less + TailwindCSS (部分) 19 +- 网络请求:axios-miniprogram(封装拦截器与认证续期)
47 -* **状态管理**: Pinia 20 +- 样式:Less + TailwindCSS(小程序端通过 weapp-tailwindcss 兼容)
48 -* **路由**: Taro Router + 自定义 Hooks 21 +- 构建:Webpack 5(Taro 默认)
22 +
23 +## 开发命令
24 +
25 +```bash
26 +pnpm install
27 +pnpm dev:weapp
28 +pnpm build:weapp
29 +pnpm lint
30 +```
49 31
50 ## 项目结构 32 ## 项目结构
51 33
52 -* `src/api`: 接口定义 34 +```text
53 -* `src/assets`: 图片等静态资源 35 +config/ Taro 构建配置(alias、designWidth、tailwind 插件等)
54 -* `src/components`: 公共组件 (qrCode, qrCodeSearch, reserveCard等) 36 +doc/ 需求/说明文档(弱网离线、核销等)
55 -* `src/composables`: 组合式函数 (离线缓存/轮询等) 37 +src/
56 -* `src/pages`: 页面文件 38 + app.js 应用入口(启动授权、网络监听、离线缓存预加载/轮询)
57 -* `src/hooks`: 组合式函数 (useGo等) 39 + app.config.js 小程序路由与窗口配置
58 -* `src/stores`: Pinia 状态管理 (main/router 等) 40 + api/ API 常量与封装(含 wx 支付、义工核销)
59 -* `src/utils`: 工具函数 (request, authRedirect, network, uiText 等) 41 + assets/ 静态资源(images、styles)
60 - 42 + components/ 业务组件(预约码、预约记录卡、离线二维码等)
61 -## 项目运行 43 + composables/ 组合式逻辑(离线缓存、轮询)
62 - 44 + hooks/ 路由封装(useGo/useReplace)
63 -1. 安装依赖 45 + pages/ 页面(按 pages/<name>/index.vue 组织)
64 - ```bash 46 + stores/ Pinia store(router/main/host/counter)
65 - pnpm install 47 + utils/ 工具(request/authRedirect/network/uiText/wechatPay 等)
66 - ``` 48 +```
67 - 49 +
68 -2. 运行开发环境 50 +### 路径别名
69 - ```bash 51 +
70 - pnpm dev:weapp 52 +[config/index.js](config/index.js) 配置:
71 - ``` 53 +
72 - 54 +- @/utils -> src/utils
73 -3. 打包构建 55 +- @/components -> src/components
74 - ```bash 56 +- @/assets -> src/assets
75 - pnpm build:weapp 57 +- @/api -> src/api
76 - ``` 58 +- @/stores -> src/stores
77 - 59 +- @/hooks -> src/hooks
78 -## 离线预约缓存轮询说明 60 +- @/composables -> src/composables
79 - 61 +
80 -### 目标 62 +### 设计宽度体系
81 - 63 +
82 -在「已授权 + 网络可用」时,定时刷新离线预约记录缓存(本地 storage:`OFFLINE_BOOKING_DATA`),用于弱网/离线兜底页面展示。 64 +[config/index.js](config/index.js) 的 designWidth 做了双设计宽度:
83 - 65 +
84 -### 相关文件 66 +- NutUI 组件按 375 设计稿计算
85 - 67 +- 其他页面按 750(Taro 默认)计算
86 -* 离线缓存刷新:`src/composables/useOfflineBookingCache.js` 68 +
87 - * 核心方法:`refresh_offline_booking_cache({ force })` 69 +## 关键实现说明
88 -* 轮询与网络监听:`src/composables/useOfflineBookingCachePolling.js` 70 +
89 - * 核心方法:`enable_offline_booking_cache_polling(options)` / `disable_offline_booking_cache_polling()` 71 +### 认证与会话续期
90 -* 启动入口:`src/app.js` 72 +
91 - * 在授权成功后调用 `enable_offline_booking_cache_polling()` 73 +- 启动时在 [app.js](src/app.js) 尝试静默授权:`silentAuth()`
92 - 74 +- 会话凭证使用 `sessionid` 存储在 Taro Storage(cookie 字符串)
93 -### 启动条件 75 +- 请求层在 [utils/request.js](src/utils/request.js) 动态注入 cookie,并在 401 时触发刷新会话、重放原请求(配合 [utils/authRedirect.js](src/utils/authRedirect.js)
94 - 76 +- 授权失败时跳转授权页,并保存来源页,授权成功后回跳(router store 持久化路径)
95 -轮询启动需要同时满足: 77 +
96 - 78 +### 弱网/离线兜底
97 -1. `ref_count > 0`:表示当前确实有人需要轮询(应用级启用会占用 1 个引用) 79 +
98 -2. `network_usable === true`:网络类型可用(由 `src/utils/network.js` 判定) 80 +两处兜底入口:
99 - 81 +
100 -### 运行流程 82 +- 启动阶段:在 [app.js](src/app.js) 检测网络类型,弱网/无网时提示并可一键进入离线列表
101 - 83 +- 请求阶段:在 [utils/request.js](src/utils/request.js) 捕获超时/网络错误,优先跳转离线列表;否则提示用户检查网络
102 -1. `enable_offline_booking_cache_polling(options)` 84 +
103 - * 缓存最后一次 `options`(用于网络恢复时重启轮询) 85 +离线数据来源:
104 - * 增加 `ref_count` 86 +
105 - * 注册 `Taro.onNetworkStatusChange`(仅注册一次) 87 +- 离线预约记录缓存:`OFFLINE_BOOKING_DATA`(见 [useOfflineBookingCache.js](src/composables/useOfflineBookingCache.js)
106 - * 如果当前网络可用,则启动定时器,默认每 `60000ms` 刷新一次 88 +- 轮询刷新:见 [useOfflineBookingCachePolling.js](src/composables/useOfflineBookingCachePolling.js)(引用计数 + 网络监听,避免重复启动)
107 -2. 定时器 tick: 89 +
108 - * 调用 `refresh_offline_booking_cache({ force: !!options?.force })` 90 +离线页面:
109 - * 内部会再次校验授权与网络,避免无效请求 91 +
110 -3. 网络变更监听: 92 +- 离线预约记录列表:`pages/offlineBookingList/index`
111 - * 变为弱网/无网:立即停止轮询定时器 93 +- 离线预约记录详情:`pages/offlineBookingDetail/index`
112 - * 恢复为可用网络:若 `ref_count > 0`,用最后一次 `options` 重新启动轮询 94 +- 离线预约码入口:`pages/offlineBookingCode/index`
113 -4. `disable_offline_booking_cache_polling()` 95 +
114 - * 释放一次 `ref_count` 96 +### 支付/退款(对接位)
115 - *`ref_count === 0` 时:停止轮询并注销网络监听器 97 +
116 - 98 +- 支付拉起封装:见 [utils/wechatPay.js](src/utils/wechatPay.js)[api/wx/pay.js](src/api/wx/pay.js)
117 -### options 说明 99 +- 取消预约(退款接口):`icbcRefundAPI`(见 [api/index.js](src/api/index.js)),在预约详情页调用并刷新离线缓存
118 - 100 +
119 -* `interval_ms`:轮询间隔(毫秒),默认 `60000` 101 +### 义工核销
120 -* `immediate`:是否立即刷新一次,默认 `true` 102 +
121 -* `force`:透传给 `refresh_offline_booking_cache`,用于强制刷新(默认 `false` 103 +- 核销端 API:见 [api/redeem.js](src/api/redeem.js)
122 - 104 +- 页面:`pages/volunteerLogin/index`(权限预检/登录)与 `pages/verificationResult/index`(扫码核销与结果展示)
123 -## 优化建议 (TODO) 105 +
124 - 106 +## 可复用能力(迁移到其他项目的价值)
125 -* [x] 小程序授权流程有问题 - 已处理 107 +
126 -* [ ] 完善支付流程(目前为模拟/H5跳转)- 后端配合联调 108 +- 请求层:`src/utils/request.js`
127 -* [ ] 优化图片资源加载(考虑使用 CDN 或分包)- 有离线模式看情况处理 109 + - 默认参数合并、cookie 注入、弱网降级
128 -* [x] 弱网环境下的离线预约记录 - 已实现(本地缓存 + 离线列表/详情) 110 + - 401 自动续期与原请求重放(与 authRedirect 配合)
129 -* [ ] 义工核销接口联调与核销结果字段展示优化(依赖后端返回结构稳定) 111 +- 认证/回跳:`src/utils/authRedirect.js` + `src/stores/router.js`
130 -* [ ] 增强网络请求的错误处理与重试机制 112 + - 静默授权单例锁(避免并发登录)
131 -* [ ] 补充单元测试 113 + - 保存来源页与授权后回跳
114 +- 弱网/离线缓存:`src/composables/useOfflineBookingCache*.js`
115 + - 离线数据结构抽取、缓存读写、轮询刷新、网络切换处理
116 +- 路由工具:`src/hooks/useGo.js`
117 + - 短路径补全、query 序列化、tabbar 兼容处理(可扩展)
118 +- 弱网文案统一:`src/utils/uiText.js`
119 + - 将 toast/modal 文案集中管理,避免页面散落硬编码
120 +
121 +## 项目优缺点
122 +
123 +### 优点
124 +
125 +- 业务链路完整(预约、支付、预约码、记录、核销),页面目录清晰
126 +- 认证流程健壮:会话续期、并发合并、授权回跳可控
127 +- 弱网/离线兜底完善:启动检查 + 请求降级 + 离线列表/详情闭环
128 +- 工具化程度高:request/authRedirect/useGo/uiText 等可复用模块明确
129 +- 样式体系兼容小程序:Less + Tailwind(配合 weapp-tailwindcss)
130 +
131 +### 不足
132 +
133 +- 自动化测试缺失(暂无单元测试/集成测试与 CI 校验)
134 +- 部分工具函数存在重复实现(例如证件号脱敏在多处出现)
135 +- 轮询逻辑仅在卸载时清理,页面 onHide 场景可能仍在请求(可优化为按页面可见性启停)
136 +- Webpack 持久化缓存未开启(`config/index.js` 中 cache.enable=false)
137 +- 少量文件头部元信息/注释规范不一致(例如个别文件仍为“文件描述”占位)
138 +
139 +## 优化建议(下一步)
140 +
141 +- 补充测试:优先覆盖 request/authRedirect/offline cache 的关键边界
142 +- 抽离通用工具:证件号脱敏、时间格式化、状态映射等统一放到 utils
143 +- 优化轮询策略:结合页面生命周期 onShow/onHide 控制轮询启停
144 +- 资源优化:CDN 图片策略、分包策略、首屏关键资源预加载
145 +- 构建性能:评估开启 Webpack 持久化缓存,缩短二次编译时间
......