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