Files
everything-is-suitable/docs/adr/2026-08-13-daily-fortune-push.md
zhangxiang e6488cdab9 docs: 添加订阅与每日运势推送功能的设计文档
- ADR-002: 订阅与每日运势推送功能设计决策
- PRD: 订阅与每日推送功能需求规格说明
- 实现计划文档
2026-08-13 08:06:01 +08:00

134 lines
5.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ADR-002: 订阅与每日运势推送功能设计
## 状态
✅ 已采纳
## 日期
2026-08-13
## 背景
用户希望在小程序端获得每日运势推送功能,无需手动打开应用即可在每日固定时间收到个性化运势推送。
## 需求
1. 用户可订阅每日运势推送服务
2. 每日固定时间(默认 07:00)推送当日运势
3. 推送内容基于用户生辰信息的紫微斗数命盘,由现有算法本地生成
4. 用户可自定义推送时间
5. 仅限微信小程序平台
## 约束
1. 纯客户端 → 需引入轻量后端用于推送(微信订阅消息要求服务端调用)
2. 微信订阅消息模板需在微信小程序后台申请,使用 `wx.subscribeMessage.send` 接口
3. 云函数运行环境为 Node.js,需兼容现有 TypeScript 算法
## 数据模型
### 云数据库:subscriptions 集合
```typescript
interface Subscription {
_id: string // 云数据库自动 ID
openid: string // 用户微信 openid(唯一索引)
templateId: string // 微信订阅消息模板 ID
birthInfo: { // 用户生辰信息(用于服务器端生成运势)
birthDate: string // 公历出生日期 YYYY-MM-DD
birthHour: number // 出生小时 (0-23)
birthMinute: number // 出生分钟 (0-59)
birthPlace: string // 出生地名称
longitude: number // 出生地经度
latitude: number // 出生地纬度
gender: 'MALE' | 'FEMALE'
}
pushTime: string // 推送时间,格式 "HH:mm",默认 "07:00"
pushEnabled: boolean // 是否开启推送
subscribedAt: Date // 订阅时间
lastPushDate: string // 最后推送日期 YYYY-MM-DD(防重复推送)
expireAt: Date // 订阅过期时间(微信订阅消息有效期)
}
```
### 小程序端本地存储(新增)
| Key | 类型 | 存储内容 | 生命周期 |
|-----|------|---------|---------|
| `eis_push_subscription` | `Subscription` | 订阅信息缓存 | 持久化,订阅/取消时更新 |
## 决策
### 决策1:推送方案 — 微信订阅消息 + 微信云开发
**方案**:微信订阅消息(`wx.subscribeMessage.send`+ 微信云开发(CloudBase
**选择理由**
- 微信订阅消息是微信小程序原生推送能力,用户可在"服务通知"中收到推送
- 微信云开发提供云函数 + 云数据库 + 定时触发器,与微信生态无缝集成
- 无需额外服务器,按量计费,小规模使用在免费额度内
- 云函数定时触发器(cron)支持每日定时执行
**替代方案排除**
- 自建后端服务器:运维成本高,超出当前项目规模
- 纯本地推送:H5 不支持后台推送,小程序端无法跨平台
- 第三方推送服务:增加外部依赖和费用
### 决策2:算法复用方案 — 共享算法包
**方案**:将现有运势算法(纯函数层)抽取为独立 npm 包,小程序和云函数共享
**选择理由**
- 现有运势算法(`fortuneStrategy.ts``ziweiAlgorithm.ts``fortune.ts`)是纯函数,无 UI 依赖
- 输入 `ZiweiChart + Date` 输出 `DailyFortune`,可在 Node.js 环境直接运行
- 结果一致性保障:小程序端和云函数推送使用同一份代码
- 后续算法更新只需维护一份代码
**依赖映射**
```
共享算法包 @everything-suitable/algorithm/
├── fortuneStrategy.ts # 运势生成策略(纯函数)
├── fortune.ts # 综合运势生成(纯函数)
├── ziweiAlgorithm.ts # 紫微算法基础(纯函数,含幸运色/数字/方位)
├── types.ts # 类型定义
├── enums.ts # 枚举定义
└── index.ts # 导出入口
```
### 决策3:数据流设计
**订阅流程**
```
小程序端 → 用户订阅 → 收集生辰信息 → 上传至云函数 → 存储至云数据库
```
**每日推送流程**
```
云函数定时触发器 (07:00) → 查询当日所有订阅 → 对每用户调用共享算法生成运势
→ 调用 wx.subscribeMessage.send → 用户收到服务通知
```
### 决策4:推送模板结构
| 模板字段 | 内容 | 数据来源 |
|---------|------|---------|
| `date1` | 今日日期 | `new Date().toLocaleDateString('zh-CN')` |
| `thing2` | 综合运势评分 + 等级 | `overallScore` + `overallLuck` |
| `thing3` | 各维度运势建议 | `careerAdvice` / `wealthAdvice` / `relationshipAdvice` / `healthAdvice` |
| `thing4` | 幸运色 + 幸运数字 | `luckyColor` + `luckyNumber` |
## 影响
1. **新增目录**`everything-is-suitable-uniapp/cloudfunctions/`(云函数目录)
2. **新增目录**`packages/algorithm/`(共享算法包)
3. **新增依赖**`@everything-suitable/algorithm`(共享算法包的本地引用)
4. **新增页面**:小程序端订阅管理页面(订阅/取消/配置推送时间)
5. **新增存储**:微信云开发环境配置(云数据库、云函数、定时触发器)
6. **不影响现有功能**:现有运势页面、紫微排盘、黄历查询不受影响
7. **不影响现有测试**:共享算法包抽取后,现有测试仍可正常运行
## 术语表
| 术语 | 定义 |
|------|------|
| 微信订阅消息 | 微信小程序提供的消息推送能力,用户订阅后可在"服务通知"中收到消息 |
| 微信云开发 | 微信生态内的 Serverless 云服务,提供云函数、云数据库、存储等 |
| 云函数 | 运行在微信云端的 Node.js 函数,通过定时触发器或事件触发 |
| 定时触发器 | 云函数的 cron 触发机制,支持按指定时间定期执行 |
| 共享算法包 | 从应用中抽取的纯算法模块,可在多环境(小程序/云函数)复用 |
| 生辰信息 | 用户的出生日期、时间、地点、性别等用于紫微斗数排盘的数据 |
| 服务通知 | 微信内用户接收订阅消息的入口,位于微信聊天列表"服务通知" |