Files
2026-02-03 17:43:58 +08:00

145 lines
5.5 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.
# Daily Widget Reco任务清单
> 对应计划:`spec_kit/Daily Widget Reco/plan.md`
>
> 标记规则:
>
> - 执行完成后将对应项从 `- [ ]` 改为 `- [x]`,并把“状态”改为 **已完成**
> - 进行中改为 **进行中**
> - 阻塞写明原因与解除条件
---
## 0. 清单状态说明
- **状态**:未开始 / 进行中 / 已完成 / 阻塞
- **阻塞**:必须写明阻塞点与解除条件
---
## 1. 客户端:补齐 Widget 场景 APIRN
- [ ] **新增 `fetchRecoWidget``POST /v1/reco/widget`**
- **状态**:未开始
- **文件**`client/src/services/recoApi.ts`
- **要求**
- Header `Accept-Language` 逻辑沿用 `fetchRecoFeed`
- body 结构沿用 `RecoRequest`
- timeout 建议 12s
- **验收**:在 App 内调用可拿到 `items[0].text`(允许为空但不报错)
---
## 2. iOS 原生能力App Group 共享读写suiteName 已确认)
> suiteName`group.com.damer.mindfulness`
- [ ] **新增 App Group 共享存储原生模块RN Bridge**
- **状态**:未开始
- **目标**RN 可写/读共享 `UserDefaults(suiteName:)`
- **要求**
- 支持 `setString(key, value)` / `getString(key)`(最小闭环)
- 以 JSON 字符串形式存储(上层 JS 自行 `JSON.stringify/parse`
- **验收**
- RN 写入后Widget 侧能读到同一 key
- 解析失败不 crash返回 `null`/空字符串均可,按上层回退)
- [ ] **新增触发 Widget 刷新的原生方法(可选但建议)**
- **状态**:未开始
- **目标**App 写入缓存后触发 `WidgetCenter.reloadAllTimelines()`
- **验收**App 调用后Widget 在合理时间内刷新显示新内容(允许系统延迟)
---
## 3. 客户端:写入共享配置/画像/每日缓存App ↔ Widget 共通)
- [ ] **写入共享配置 `widget.config.v1`(包含 `apiBaseUrl`**
- **状态**:未开始
- **要求**
- App 启动后(或 baseURL 计算完成后)写入
- JSON 字段最少包含:`schema_version``apiBaseUrl``saved_at`
- **验收**Widget 侧可读到正确 baseURLdev/pro 随 App 切换)
- [ ] **写入共享画像 `widget.userProfile.v1_2`Onboarding 完成后)**
- **状态**:未开始
- **依赖**:客户端已能获取/持久化用户画像(本地存储已有 `user.profileScoring`
- **要求**
- 结构以现有 `UserProfileV1_2` 输出为准
- JSON 字段建议包含:`schema_version``saved_at``user_profile`
- **验收**Widget 侧可读到 `user_profile`,且可用于请求后端
- [ ] **实现 App 前台“可选主动拉取”并写入 `widget.dailyReco.v1`**
- **状态**:未开始
- **要求**
- 判断 `day_key`(用户时区 `YYYY-MM-DD`)不是今天时才拉取
- 调用 `fetchRecoWidget(k=1)`,成功写入缓存
- 失败不影响 UI不阻塞主流程
- **验收**App 打开后能把今日推荐写入共享缓存Widget reload 后展示一致
---
## 4. iOS Widget读取共享缓存并展示先不接网络也能跑通
- [ ] **Widget 读取 `widget.dailyReco.v1` 并展示**
- **状态**:未开始
- **要求**
- JSON 解析失败容错:视为无缓存
- 展示优先级:今日缓存 → 最近缓存 → 兜底文案
- **验收**手动写入共享缓存后Widget 立即能展示对应文案(或在下一次 reload 展示)
---
## 5. iOS Widget网络拉取每日推荐 + Timeline 每日刷新(核心)
- [ ] **Widget 在缓存过期时请求 `POST /v1/reco/widget` 并写回缓存**
- **状态**:未开始
- **依赖**:可读到 `widget.config.v1`apiBaseUrl`widget.userProfile.v1_2`user_profile
- **要求**
- 无鉴权
- 超时建议 812s
- `Accept-Language` 与 App 保持一致(`en/tc`
- `items=[]` 视为失败,走回退
- **验收**清空今日缓存后Widget 能在一次 timeline 请求内拉取并展示今日推荐(允许先兜底再更新)
- [ ] **实现每日刷新调度TimelinePolicy**
- **状态**:未开始
- **要求**
- `nextRefreshDate` 设置为“下一天本地时间 00:1001:00 随机”之一
- 不追求严格准点,但确保每日范围内能更新
- **验收**:通过修改系统日期/模拟 day_key 变化,可观察到会进入“过期→重新拉取”逻辑
---
## 6. 联调与验收验证(必须)
- [ ] **联调:添加小组件后,未打开 App 也能每日更新(尽力而为)**
- **状态**:未开始
- **步骤**
- 安装带 Widget 的开发包
- 在桌面添加 Widget
- 清空今日缓存并等待 Widget 刷新(或手动触发 reload
- **验收**Widget 能从后端拉取并展示;隔天能更新到新内容(允许系统延迟)
- [ ] **回退验证:断网/后端不可用/返回异常**
- **状态**:未开始
- **验收**
- Widget 不崩溃
- 展示最近缓存或兜底文案
- [ ] **一致性验证App 与 Widget 当天展示一致**
- **状态**:未开始
- **验收**App 主动拉取并写入缓存后Widget reload 后展示同一条 `content_id/text`
---
## 7. 文档与总览更新
- [ ] **补充实现说明(可放入客户端 README 或本需求 overflow**
- **状态**:未开始
- **要求**:记录 suiteName、共享 key、如何本地验证
- [ ] **更新 `spec_kit/overview.md`**
- **状态**:未开始
- **要求**在“Spec Kit Overview”中新增本需求摘要目标/产物/已完成编码变更)