169 lines
7.6 KiB
Markdown
169 lines
7.6 KiB
Markdown
# Card UI(任务清单)
|
||
|
||
> 说明:本清单根据 `plan.md` 拆解,要求“可执行、可验收、可标记”。
|
||
> 标记规则:执行完成后将对应项从 `- [ ]` 改为 `- [x]`,并把“状态”改为 **已完成**;进行中改为 **进行中**;阻塞写明原因与解除条件。
|
||
|
||
## 0. UI 参考(本次实现对齐)
|
||
|
||
- **参考截图**:你提供的卡片页 + 主题弹窗 + 我的弹窗
|
||
- **弹窗内容区背景色**:`#FAF3EC`
|
||
- **右上角按钮资源**:`client/assets/images/home/theme.svg`、`client/assets/images/home/my.svg`
|
||
- **底部反应按钮资源**:`client/assets/images/home/like.svg`、`client/assets/images/home/hate.svg`
|
||
- **交互约束**:
|
||
- 弹窗为**底部上拉(Sheet)**
|
||
- 关闭方式:**点 X 关闭**(不要求点遮罩关闭)
|
||
- 顶部按钮使用**系统导航栏**(`headerRight`)
|
||
- 主题切换最少影响:**页面背景**
|
||
- 个人主页弹窗中的列表项:本期允许 **仅做占位**
|
||
- 喜欢动效为**强反馈:心形填满**(按压回弹 + 填充变化)
|
||
|
||
## 1. 依赖与基础设施(SVG 可 import)
|
||
|
||
- [x] **安装 `react-native-svg-transformer` 并新增 `client/metro.config.js`**
|
||
- **状态**:已完成
|
||
- **原因**:让 `assets/images/home/*.svg` 支持 `import XxxIcon from '...svg'` 作为组件使用
|
||
- **命令**:
|
||
|
||
```bash
|
||
cd client
|
||
pnpm add react-native-svg-transformer
|
||
```
|
||
|
||
- **实现点**:
|
||
- 新增 `client/metro.config.js`,基于 `expo/metro-config` 配置 `svg` transformer
|
||
- **验收**:
|
||
- 任一页面可成功渲染 `theme.svg`/`like.svg`(真机/模拟器均可)
|
||
- `pnpm start` 正常启动,无 Metro 报错
|
||
|
||
## 2. 本地存储:主题模式持久化
|
||
|
||
- [x] **在 `src/storage/appStorage.ts` 新增主题 mode key 与读写方法**
|
||
- **状态**:已完成
|
||
- **Key**:`ui.theme.mode`
|
||
- **类型**:`'scenery' | 'color'`(默认 `scenery`)
|
||
- **新增 API(建议)**:
|
||
- `getThemeMode(): Promise<'scenery' | 'color'>`
|
||
- `setThemeMode(mode: 'scenery' | 'color'): Promise<void>`
|
||
- **验收**:
|
||
- 代码中不散落硬编码 key
|
||
- 切换主题后重启 App 仍保持上次选择
|
||
|
||
## 3. 通用组件:底部上拉弹窗(Sheet)框架
|
||
|
||
- [x] **新增通用 `SheetModal` 组件(底部上拉 + 背景色 #FAF3EC + X 关闭)**
|
||
- **状态**:已完成
|
||
- **建议路径**:`client/components/ui/SheetModal.tsx`
|
||
- **要求**:
|
||
- 遮罩存在(可拦截背景交互),但本期**不要求点遮罩关闭**
|
||
- 内容区背景色固定为 `#FAF3EC`
|
||
- 顶部提供右上/左上 **X 按钮**关闭(以设计稿为准)
|
||
- 基础动效:上滑进入、下滑退出(或淡入淡出 + translateY)
|
||
- **验收**:
|
||
- 任意页面可打开/关闭该弹窗,不闪烁、不穿透点击
|
||
- iOS 安全区适配正常(底部不被 Home Indicator 遮挡)
|
||
|
||
## 4. 主题弹窗:风景 / 颜色
|
||
|
||
- [x] **实现 `ThemeModal`(复用 `SheetModal`)**
|
||
- **状态**:已完成
|
||
- **建议路径**:`client/components/home/ThemeModal.tsx`
|
||
- **内容**:
|
||
- 标题:主题
|
||
- 选项:风景 / 颜色(含预览卡片)
|
||
- 选中态:明显高亮(描边/阴影/勾选均可)
|
||
- **交互**:
|
||
- 点击选项:`setThemeMode(...)` 并立即生效(可关闭弹窗或保持打开,按设计稿)
|
||
- 点 X:关闭
|
||
- **验收**:
|
||
- 两种主题可切换
|
||
- 切换后 Home 页面背景立刻变化
|
||
|
||
## 5. 个人主页弹窗:占位入口
|
||
|
||
- [x] **实现 `ProfileModal`(复用 `SheetModal`)**
|
||
- **状态**:已完成
|
||
- **建议路径**:`client/components/home/ProfileModal.tsx`
|
||
- **内容(按设计最小闭环)**:
|
||
- 顶部:插画/头像 + 昵称(来自 `getUserProfile().name`,无则占位)
|
||
- 快捷卡片:我的喜欢 / 小组件(小组件可占位)
|
||
- 通用列表:每日提醒 / 隐私政策 / 使用条款 / 语言(本期均允许占位)
|
||
- **交互**:
|
||
- 点 X:关闭
|
||
- 列表项点击:占位反馈(例如 `Alert` 或轻提示),不崩溃即可
|
||
- **验收**:
|
||
- 弹窗 UI 与 ThemeModal 同一套视觉(背景色/圆角/间距一致)
|
||
- 点击各入口有明确反馈
|
||
|
||
## 6. 卡片页头部:系统导航栏右上角两个 icon 按钮
|
||
|
||
- [x] **改造 `client/app/(app)/_layout.tsx`:`home` 的 `headerRight` 使用两个圆形 icon 按钮**
|
||
- **状态**:已完成
|
||
- **要求**:
|
||
- 两按钮水平排列、圆形浅色底、`hitSlop>=10`
|
||
- 左:主题(`theme.svg`),右:我的(`my.svg`)
|
||
- **事件传递方案(需要落地)**:
|
||
- 实际落地:在 `home.tsx` 内通过 `navigation.setOptions()` 设置 `headerRight`,直接使用页面 state 打开 Theme/Profile 弹窗(避免跨层事件传递)
|
||
- **验收**:
|
||
- 右上角两个按钮展示正确
|
||
- 点击分别能打开对应弹窗
|
||
|
||
## 7. 卡片页内容:喜欢/讨厌改为 icon + 强反馈动效
|
||
|
||
- [x] **改造 `client/app/(app)/home.tsx`:底部按钮从文字改为 icon**
|
||
- **状态**:已完成
|
||
- **要求**:
|
||
- 喜欢按钮使用 `like.svg`
|
||
- 讨厌按钮使用 `hate.svg`(逻辑仍写入 reaction=`dislike`)
|
||
- **验收**:两按钮 icon 显示清晰,点击逻辑仍正常推进下一张卡片
|
||
|
||
- [x] **实现“强反馈:心形填满”点击动效**
|
||
- **状态**:已完成
|
||
- **范围**:至少作用于“喜欢”按钮
|
||
- **建议实现**:
|
||
- `pressIn/pressOut`:按钮缩放回弹
|
||
- `onPress`:短促强调动效(scale 1 → 1.12 → 1)
|
||
- “填满”效果:点击后切换到“填充版心形”(若当前资源仅描边,需要:
|
||
- 新增一份 `like_filled.svg`(或在现有 SVG 上修改 fill/stroke),并保持风格一致
|
||
- 或用 `react-native-svg` 动态改 `fill`(可行但实现复杂)
|
||
- **验收**:
|
||
- 点击喜欢按钮能看到明显的“变填充 + 弹一下”反馈
|
||
- 动效结束后再推进下一张卡片(避免动画被切页吞掉)
|
||
|
||
## 8. 主题对 Home 背景的影响
|
||
|
||
- [x] **让主题 mode 影响 Home 页面背景**
|
||
- **状态**:已完成
|
||
- **规则**:
|
||
- `scenery`:使用风景主题背景(可先用现有米色/图片占位)
|
||
- `color`:使用颜色主题背景(可先用淡粉色/纯色占位)
|
||
- **验收**:切换主题后背景立即变化;返回/重进页面仍正确
|
||
|
||
## 9. i18n(用于标题/无障碍/占位文案)
|
||
|
||
- [x] **补齐本需求相关 i18n key(至少 zh-CN/en)**
|
||
- **状态**:已完成
|
||
- **建议 key**:
|
||
- `theme.title`、`theme.scenery`、`theme.color`
|
||
- `profile.title`、`profile.favorites`、`profile.widget`
|
||
- `profile.dailyReminder`、`profile.privacy`、`profile.terms`、`profile.language`
|
||
- `home.theme`、`home.profile`(用于 `accessibilityLabel`)
|
||
- **验收**:弹窗标题/选项/占位提示无硬编码长文案;切换语言可生效
|
||
|
||
## 10. 自测与验收
|
||
|
||
- [ ] **主题弹窗流程自测**
|
||
- **状态**:未开始
|
||
- **路径**:Home 右上角主题按钮 → 主题弹窗 → 切换风景/颜色 → 背景变化 → 重启后仍保持
|
||
- **验收**:符合 `spec.md` / `plan.md` / 本清单验收点
|
||
|
||
- [ ] **我的弹窗流程自测**
|
||
- **状态**:未开始
|
||
- **路径**:Home 右上角我的按钮 → 个人主页弹窗 → 点 X 关闭 → 列表项点击占位反馈
|
||
- **验收**:弹窗不穿透、关闭稳定、占位反馈明确
|
||
|
||
- [ ] **喜欢/讨厌动效与逻辑自测**
|
||
- **状态**:未开始
|
||
- **路径**:连续点击喜欢/讨厌 → 按钮动效可见 → 卡片索引推进 → 收藏/反应写入正常
|
||
- **验收**:无报错、不卡顿、动效不被切换吞掉
|
||
|