# 01 · 架构设计 ## 1. 技术选型理由 选 **原生小程序 + 云开发**,因为: - 云开发是微信官方为原生小程序量身打造,集成度最高、免运维、免自建鉴权。 - 汪圈 V1 是单机闭环,无跨端(App / H5 / 支付宝)需求,原生比 Taro / uni-app 更直接。 - 云函数里 `cloud.getWXContext().OPENID` 直接拿到可信用户标识,省掉整套登录鉴权后端。 ## 2. 整体架构 ``` ┌─────────────────────────────────────────────┐ │ 微信小程序客户端 │ │ pages/ (12屏) · components/ · utils/ │ │ globalData + 事件总线 │ └───────────────────┬─────────────────────────┘ │ wx.cloud.callFunction ┌────────────┴────────────┐ ▼ ▼ ┌───────────────┐ ┌───────────────┐ │ 云函数 │ │ 云数据库 │ │ login │◄───────►│ users │ │ dogManage │ │ dogs │ │ walkSave │ │ walks │ │ walkManual │ │ dog_achievements│ │ getDogDetail │ └───────────────┘ │ getHistory │ └───────────────┘ │ │ ▼ ▼ ┌───────────────┐ 成就判定/统计累加 │ 云存储 │ │ 头像/照片/分享图 │ └───────────────┘ ``` **核心原则:写操作 + 敏感计算全部走云函数**,客户端只读(或经云函数读聚合结果)。连续天数、成就解锁、补记规则等绝不在客户端算。 ## 3. 工程目录结构 ``` Pet3/ ├── cloudfunctions/ # 云函数(Node.js) │ ├── login/ # 登录 + 首次建用户 │ │ ├── index.js │ │ └── package.json │ ├── dogManage/ # 狗狗增改查 │ ├── walkSave/ # 保存遛狗 + 触发统计/成就 │ ├── walkManual/ # 手动补记 │ ├── getDogDetail/ # 狗狗主页聚合数据 │ └── getHistory/ # 历史/记录 Tab 列表聚合 │ ├── miniprogram/ │ ├── app.js # 初始化 wx.cloud、globalData │ ├── app.json # 路由、tabBar、分包 │ ├── app.wxss # 全局样式 + 设计 token │ ├── pages/ │ │ ├── login/ # 0a 登录 │ │ ├── dog-edit/ # 0b 建档/编辑(复用) │ │ ├── home/ # 1 我的(tab) │ │ ├── walking/ # 2/2b 遛狗中(含暂停态) │ │ ├── summary/ # 3 成果卡 │ │ ├── dog-detail/ # 4 狗狗主页 │ │ ├── history/ # 5 遛狗历史 │ │ ├── records/ # 6/6b 记录(tab,含空状态) │ │ └── achievements/ # 7 完整成就页 │ ├── components/ │ │ ├── dog-card/ # 狗狗卡片 │ │ ├── walk-row/ # 历史/记录行 │ │ ├── stat-grid/ # 统计三宫格 │ │ ├── achievement-medal/ # 成就勋章(解锁/锁定) │ │ ├── multi-dog-sheet/ # 0c 多狗选择弹层 │ │ └── manual-add-sheet/ # 补记弹层 │ ├── utils/ │ │ ├── cloud.js # callFunction 统一封装 + 错误处理 │ │ ├── format.js # 时长/距离/日期格式化 │ │ ├── dogStep.js # 狗步换算(体型档位/步幅/体重校准) │ │ └── store.js # 全局状态 + 订阅 │ └── images/ # 本地图标/占位图 │ ├── docs/ # 设计文档(本目录) ├── wangquan-prototype.html # 交互原型 └── project.config.json ``` ## 4. 全局状态(store) 不引入重型状态库。`miniprogram/utils/store.js` 维护: ```js const store = { userInfo: null, // { openid, nickname, avatar, joinedAt, walkCount } dogs: [], // 当前用户的狗狗列表 currentDogId: null, // 默认/上次选中的狗 walkSession: null, // 进行中的遛狗会话(见下) }; ``` **遛狗会话(walkSession)** 是 V1 最关键的运行时状态,需支持小程序退到后台后恢复: ```js walkSession = { dogIds: ['xxx'], // 本次遛的狗(支持多狗) startAt: 1719230000000, pausedTotal: 0, // 累计暂停时长(ms),结算时扣除 pausedAt: null, // 当前暂停起点,null=进行中 pooped: false, // 便便打卡 locationEnabled: false, // 是否获得定位授权 distanceMeters: null, // GPS 累计距离;未授权为 null lastLocation: null, // 最近一次有效定位点,用于增量累计距离 status: 'walking' | 'paused', } ``` 落地策略:会话写入 `wx.setStorageSync('walkSession')`,App `onShow` 时恢复,避免锁屏/切后台丢失计时。计时基于 `startAt` 与当前时间差实时计算,**不依赖 setInterval 累加**(后台被冻结也不丢)。定位为可选增强:获得授权时累计 GPS 距离并换算狗步;未授权时 `distanceMeters` / `dogStepsByDog` 为 `null`,界面隐藏距离与狗步,闭环仍成立。 ## 5. 设计 Token(迁移自原型) 原型 CSS 变量直接转为 `app.wxss` 全局变量,保证视觉一致: | Token | 值 | 用途 | |-------|-----|------| | `--bg` | `#F2EDE6` | 页面背景 | | `--surface` | `#FBF8F3` | 卡片 | | `--ink` | `#2E2A24` | 主文字 | | `--ink-2` | `#6E665B` | 次文字 | | `--accent` | `#E8A04B` | 主色(按钮/FAB) | | `--accent-deep` | `#C77E2E` | 主色深 | | `--success` | `#6B8E5A` | 遛狗中 | | `--warn` | `#D98A4E` | 暂停态 | | `--danger` | `#C25A4E` | 结束/二次确认 | > 小程序 WXSS 支持 CSS 变量,可直接 `var(--accent)`。不引第三方组件库,全部基础 UI(按钮、卡片、chip、toggle、勋章等)按原型纯手写为 `components/` 下的可复用组件。