docs: 添加订阅与每日运势推送功能的设计文档

- ADR-002: 订阅与每日运势推送功能设计决策
- PRD: 订阅与每日推送功能需求规格说明
- 实现计划文档
This commit is contained in:
2026-08-13 08:06:01 +08:00
parent 7f0ef622e7
commit e6488cdab9
3 changed files with 773 additions and 0 deletions
@@ -0,0 +1,241 @@
# PRD: 订阅与每日运势推送功能
## 1. 概述
### 1.1 产品名称
万事宜 — 订阅与每日运势推送
### 1.2 目标用户
已输入生辰信息并使用紫微斗数运势功能的微信小程序用户
### 1.3 核心价值
用户无需手动打开小程序,每日自动收到个性化运势推送,提升日活与用户粘性
### 1.4 约束条件
- 仅限微信小程序平台
- 依赖微信云开发(CloudBase)作为轻量后端
- 推送内容由现有算法本地/云端生成,无需外部数据源
## 2. 功能范围
### 2.1 范围内(MVP
| 功能 | 说明 |
|------|------|
| F1: 订阅入口 | 在运势页面提供订阅入口,引导用户订阅每日推送 |
| F2: 微信订阅消息授权 | 调用 `wx.requestSubscribeMessage` 获取用户授权 |
| F3: 生辰信息上传 | 将用户生辰信息上传至云数据库,用于云端生成运势 |
| F4: 每日定时推送 | 云函数定时触发器每日 07:00 执行推送 |
| F5: 推送内容生成 | 云函数调用共享算法包生成当日运势 |
| F6: 推送时间配置 | 用户可自定义推送时间(默认 07:00) |
| F7: 取消订阅 | 用户可随时取消推送,清理云数据库订阅记录 |
| F8: 共享算法包抽取 | 将运势算法纯函数层抽取为独立 npm 包 |
### 2.2 范围外(后续迭代)
| 功能 | 说明 |
|------|------|
| 黄历每日推送 | 未来可扩展为推送当日宜忌 |
| 多模板推送 | 支持不同模板(运势、黄历、提醒等) |
| 多平台推送 | H5 浏览器推送、App 原生推送 |
| 推送统计 | 推送到达率、点击率分析 |
## 3. 用户故事
### US-01: 订阅推送
> 作为已设置生辰信息的用户,我希望在运势页面看到订阅入口,一键订阅每日运势推送,从而每天自动收到我的运势信息。
**验收标准**
- [ ] 用户进入运势页面时,显示订阅入口(仅未订阅时)
- [ ] 点击订阅后,弹出微信订阅消息授权弹窗
- [ ] 用户授权后,生辰信息上传至云数据库
- [ ] 订阅成功后显示"已订阅"状态和每日推送时间
- [ ] 未输入生辰信息的用户提示先设置生辰信息
### US-02: 每日推送接收
> 作为已订阅用户,我希望每天在固定时间收到服务通知,查看当日的综合运势、各维度运势和幸运信息。
**验收标准**
- [ ] 每日在用户配置的时间(默认 07:00)收到服务通知
- [ ] 推送内容包含:日期、综合运势评分+等级、各维度运势、幸运色+数字
- [ ] 推送内容与小程序内当日运势一致
- [ ] 同一用户每日不会收到重复推送
### US-03: 推送时间配置
> 作为已订阅用户,我希望在订阅管理页面修改推送时间,从而适配我的作息习惯。
**验收标准**
- [ ] 订阅管理页面显示当前推送时间
- [ ] 用户可修改推送时间(步长 30 分钟)
- [ ] 修改后云端同步更新
- [ ] 修改后下一次推送按新时间执行
### US-04: 取消订阅
> 作为已订阅用户,我希望在订阅管理页面一键取消订阅,从而不再收到每日推送。
**验收标准**
- [ ] 订阅管理页面提供"取消订阅"按钮
- [ ] 取消后删除云端订阅记录
- [ ] 取消后不再收到推送
- [ ] 取消后订阅入口重新显示
## 4. 架构与数据流
### 4.1 系统架构
```
┌──────────────────────────────────────────────────────┐
│ 微信小程序 │
│ ┌──────────────┐ ┌──────────────┐ ┌───────────┐ │
│ │ 运势页面 │ │ 订阅管理页面 │ │ 共享算法包 │ │
│ │ (订阅入口) │ │ (时间/取消) │ │ (本地使用) │ │
│ └──────┬───────┘ └──────┬───────┘ └───────────┘ │
│ │ │ │
│ └────────┬────────┘ │
│ │ │
│ wx.cloud.callFunction │
└──────────────────┼─────────────────────────────────────┘
┌──────────────────────────────────────────────────────┐
│ 微信云开发 (CloudBase) │
│ ┌────────────────────┐ ┌────────────────────────┐ │
│ │ 云函数: subscribe │ │ 云函数: dailyPush │ │
│ │ - 存储订阅关系 │ │ - 定时触发器 07:00 │ │
│ │ - 存储生辰信息 │ │ - 调用共享算法包 │ │
│ │ - 更新推送时间 │ │ - 生成运势内容 │ │
│ │ - 取消订阅 │ │ - 调用 subscribe.send │ │
│ └────────────────────┘ └────────────────────────┘ │
│ ┌────────────────────────┐ │
│ │ 云函数: unsubscribe │ │
│ │ - 删除订阅记录 │ │
│ └────────────────────────┘ │
│ ┌────────────────────────────────────────────────┐ │
│ │ 云数据库: subscriptions 集合 │ │
│ │ { openid, templateId, birthInfo, pushTime, │ │
│ │ pushEnabled, subscribedAt, lastPushDate } │ │
│ └────────────────────────────────────────────────┘ │
│ ┌────────────────────────────────────────────────┐ │
│ │ 共享算法包 @everything-suitable/algorithm │ │
│ │ (云函数依赖,纯 TypeScript 计算) │ │
│ └────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────┘
```
### 4.2 数据流
**订阅流程**
```
1. 用户点击"订阅每日推送"
2. 小程序检查用户是否已输入生辰信息
3. 调用 wx.requestSubscribeMessage 请求授权
4. 用户授权 → 小程序调用云函数 subscribe
5. 云函数将 { openid, birthInfo, templateId, pushTime } 写入云数据库
6. 返回成功 → 小程序 UI 更新为"已订阅"
```
**每日推送流程**
```
1. 云函数定时触发器 (dailyPush) 在每日 07:00 触发
2. 查询云数据库 subscriptions 中 pushEnabled=true 且 lastPushDate != today 的记录
3. 对每条记录:
a. 使用 birthInfo 计算 ZiweiChart(本地算法)
b. 使用 chart + today 调用 generateDailyFortune
c. 格式化推送内容(模板字段绑定)
d. 调用 wx.subscribeMessage.send 发送
e. 更新 lastPushDate = today
```
## 5. 共享算法包定义
### 5.1 包结构
```
packages/algorithm/
├── package.json
├── tsconfig.json
├── src/
│ ├── index.ts # 导出入口
│ ├── fortuneStrategy.ts # 运势生成策略
│ ├── fortune.ts # 综合运势生成
│ ├── ziweiAlgorithm.ts # 紫微算法基础
│ ├── types.ts # 类型定义
│ ├── enums.ts # 枚举定义
│ └── __tests__/ # 算法测试
│ └── fortuneStrategy.test.ts
└── README.md
```
### 5.2 导出接口
```typescript
// 核心导出
export { generateDailyFortune } from './fortuneStrategy'
export { generateComprehensiveFortune } from './fortune'
export { calculateLuckyColor, calculateLuckyNumber, calculateLuckyDirection } from './ziweiAlgorithm'
export { determineLuckLevel, calculatePalaceScore } from './ziweiAlgorithm'
export type { DailyFortune, ZiweiChart, PalaceFortune } from './types'
```
## 6. 微信订阅消息模板
### 6.1 模板申请
在微信小程序管理后台 → 功能 → 订阅消息 → 公共模板库,搜索并选用合适的模板。
### 6.2 推荐模板字段映射
| 模板参数 | 值 | 说明 |
|---------|-----|------|
| `date1` | `{{data.date1}}` | 日期,格式:2026年8月14日 |
| `thing2` | `{{data.thing2}}` | 综合运势,格式:综合评分85分,等级:吉 |
| `thing3` | `{{data.thing3}}` | 各维度运势摘要 |
| `thing4` | `{{data.thing4}}` | 幸运信息,格式:幸运色红色 幸运数字7 |
### 6.3 推送内容示例
```
📅 2026年8月14日
🌟 综合运势:85分(吉)
📊 事业:今日事业运势吉显,适合处理重要工作事务
财运:财运亨通,可进行投资理财
感情:感情运势良好,适合表达爱意
健康:身体状况良好,精力充沛
🍀 幸运色:红色 幸运数字:7
```
## 7. 阶段与里程碑
| 阶段 | 内容 | 预估工时 | 依赖 |
|------|------|---------|------|
| **M1: 共享算法包** | 抽取算法为独立包,确保云函数可调用 | 2d | 无 |
| **M2: 云开发环境** | 开通微信云开发,创建数据库、云函数、定时触发器 | 1d | M1 |
| **M3: 订阅功能** | 小程序端订阅入口 + 订阅管理页面 + 云函数 | 2d | M2 |
| **M4: 每日推送** | 云函数 dailyPush 实现 + 定时触发器配置 | 1.5d | M2+M3 |
| **M5: 测试与验收** | 集成测试 + 推送验证 + 异常处理 | 1.5d | M4 |
## 8. 验收标准
### 8.1 功能验收
| # | 验收项 | 预期结果 |
|---|--------|---------|
| 1 | 未输入生辰信息时订阅 | 提示用户先设置生辰信息 |
| 2 | 首次订阅流程 | 微信授权弹窗 → 生辰信息上传 → 订阅成功 |
| 3 | 每日推送触发 | 用户在配置时间收到服务通知 |
| 4 | 推送内容正确性 | 推送内容与小程序内当日运势一致 |
| 5 | 推送时间修改 | 修改后下次推送按新时间执行 |
| 6 | 取消订阅 | 删除云端记录,不再收到推送 |
| 7 | 重复推送防护 | 同一用户每日仅收到一次推送 |
| 8 | 订阅消息过期 | 用户重新订阅后恢复正常推送 |
### 8.2 非功能验收
| # | 验收项 | 预期结果 |
|---|--------|---------|
| 1 | 云函数执行时间 | < 3s/用户(含算法计算) |
| 2 | 订阅消息到达率 | 微信官方保障,不做额外要求 |
| 3 | 用户数据安全 | 生辰信息仅用于推送计算,不另作他用 |
## 9. 术语表
| 术语 | 定义 |
|------|------|
| 微信订阅消息 | 微信小程序提供的消息推送能力,用户订阅后可在"服务通知"中收到消息 |
| 微信云开发 | 微信生态内的 Serverless 云服务,提供云函数、云数据库、存储等 |
| 云函数 | 运行在微信云端的 Node.js 函数 |
| 定时触发器 | 云函数的 cron 触发机制 |
| 共享算法包 | 从应用中抽取的纯算法模块 |
| 服务通知 | 微信内用户接收订阅消息的入口 |