Color Walk PRD
Color Walk PRD
1. 产品概述
Color Walk 是一个正念色彩记录工具。用户转动色轮获得颜色任务,完成 color walk 后打卡记录,积累个人色板。产品定位为工具优先,社区为辅。
核心循环: 转色轮 → 出门发现 → 打卡记录 → 色板增长
产品定位:
- 主要价值:个人色彩记录工具(色板、挑战系统、情感报告)
- 次要价值:轻量社区(可选上传分享,看别人的发现)
- 用户可以在 Instagram/TikTok 发布内容,回到网站仅需打卡即可
2. 目标用户
- 对正念/减压感兴趣的人
- 喜欢摄影和记录生活的人
- 追随 TikTok 健康生活趋势的年轻用户(18-35岁)
3. 版本规划(已合并 VERSION_PLAN)
3.1 版本划分原则
每个版本只验证一个核心假设,逐步构建产品价值。
3.2 MVP — 核心工具闭环(预计 4-6 周)
目标 验证“用户会不会为了积累色板而回来打卡”。
功能范围
- 色轮 + 任务列表:随时转色轮、最多 10 个任务、重复提示、删除功能;颜色池为 72 种
- 打卡(仅打卡):在首页任务列表内完成,不包含照片上传,仅记录完成
- 个人色板:色块网格展示,支持重复颜色标记(×N)
- 打卡反馈展示:首页任务行色块俏皮下落并消失 + 累计 walk 次数
- 个人主页:色板 + 基础统计(累计次数、加入时间)
- 账号系统:使用模板能力
- 数据预埋:完成核心事件埋点与字段预留;挑战进度不在 MVP/V1/V1.5 累计
明确不包含
- 社区广场
- 照片上传
- 点赞/评论
- 挑战与徽章
- 情感报告
- 色彩热力图
验收指标
- 注册用户中,7 日内完成 ≥ 3 次打卡的比例 ≥ 20%
- 色板查看率:打卡后点击“查看我的色板” ≥ 60%
3.3 V1 — 打卡增强(预计 4-6 周)
目标 验证“更丰富的打卡记录(照片+情绪)能否提升完成率与回访意愿”。
功能范围
- 打卡 + 上传照片:打卡流程中加入可选上传(最多 9 张)
- 上传方式:支持文件选择与网页端拖拽上传;不支持移动端直接拍照
- 情绪标签:打卡时可选情绪(平静、兴奋、治愈、感恩、慵懒、Melancholy)
- 个人照片墙:个人主页新增照片墙
- 个人照片墙排序:按时间倒序
- 历史图片管理:可在个人照片墙对某次 walk 执行补传、删图、换图
验收指标
- 有照片的打卡占总打卡比例 ≥ 30%
- 有情绪标签的打卡占比 ≥ 40%
- 个人照片墙周访问率 ≥ 35%(活跃用户)
3.4 V1.5 — 轻社区开放(预计 4-6 周)
目标 验证“社区内容能否进一步提升留存与互动”。
功能范围
- 社区广场(瀑布流):展示所有有照片的打卡记录
- 按颜色浏览:
/community/:color筛选特定颜色 - 点赞:需登录,每张照片只能点赞一次
- 匿名浏览:未登录可浏览社区,不能点赞/上传
验收指标
- D7 留存较 V1 提升 ≥ 15%
- 社区广场周访问率 ≥ 40%(活跃用户)
运营策略(V1.5)
- UGC 治理先采用人工巡检,不在 V1.5 开发举报/审核系统
3.5 V2 — 游戏化 + 互动深化(预计 6-8 周)
目标 验证“游戏化机制能否加深参与度”。
功能范围
- 评论系统:需登录,最多 150 字,发布者可删除
- 基础挑战与徽章:收集类(10/30 种颜色、彩虹七色)+ 数量类(10/50 张照片)
- 情感色谱报告(基础版):月度颜色分布,累计 10 次打卡后解锁
- 挑战数据累计:从 V2 开始累计与计算挑战进度(不追溯 MVP/V1/V1.5)
验收指标
- 解锁至少一枚徽章的用户占活跃用户 ≥ 30%
- 评论渗透率:有评论的帖子占比 ≥ 20%
3.6 V3 — 差异化与传播(预计 8-10 周)
目标 验证“差异化功能能否带来自然增长”。
功能范围
- 色彩热力图:世界地图 + 颜色热力分布
/map - 地理位置标记:每次打卡时单次选择是否标记城市级位置
- 地理位置数据采集:从 V3 开始采集
- 情感色谱报告(完整版):年度报告、颜色-情绪交叉分析
- 完整挑战体系:挑战规则重设计后上线(不包含按天连续打卡类挑战)
- 色板分享功能:生成色板图片,可分享到 Instagram/TikTok
验收指标
- 地图功能使用率:周活用户中访问
/map≥ 15% - 年度报告查看率:满足门槛用户中查看 ≥ 40%
- 色板分享率:生成分享图片的用户 ≥ 10%
3.7 关键规则(跨版本一致)
- 任务列表上限:10 个
- 重复颜色处理:提示“已在列表中”
- 色板逻辑:同一颜色可多次打卡,显示次数标记
- 删除交互:✕ 图标
- 账号系统:使用模板能力,不单独开发
4. 功能清单(最终形态)
注:以下为完整功能设计,具体上线节奏以第 3 节版本规划为准。
4.1 色轮与任务系统
描述: 用户可以随时转动色轮获得颜色任务,管理自己的待完成任务列表。
规则:
- 用户可以随时转色轮,不限次数
- 每次转出的颜色会加入“我的颜色任务列表”
- 任务列表最多保留 10 个待完成颜色
- 达到上限后,转色轮会提示“任务列表已满,请先完成或删除一些颜色”
- 如果转出已在列表中的颜色,提示“这个颜色已在你的任务列表中”
- 颜色从预设的色库中随机抽取(固定为 72 种颜色)
- 游客态不保存任务列表;仅登录用户可创建和持久化任务
- 登录用户再次打开网页时,需恢复其未完成任务列表
交互:
- 转盘动画:先快后慢,自然减速停止
- 停止后展示颜色名称 + 色块,自动加入任务列表
- 任务列表展示所有待完成的颜色
- 每个颜色任务显示:色块、颜色名称、[Check in] 按钮、✕ 删除图标
- 点击 ✕ 可删除该颜色任务
4.2 打卡
描述: 用户完成 walk 后,对任务列表中的颜色进行打卡记录。
规则:
- 需要登录才能打卡
- 打卡时选择任务列表中的某个颜色
- 打卡完成后该颜色从任务列表移除,加入个人色板
- 同一颜色可以多次打卡(每次都是独立记录)
- MVP 不包含照片上传与情绪标签(V1 再加入)
MVP 首页内联打卡流程(已确定):
- 在首页任务列表点击 [Check in]
- 当前任务行展开内联打卡面板(不跳转页面):
- 展示当前颜色色块 + 颜色名称
- 文案:“你完成这次 Color Walk 了吗?”
- 操作:[Complete check-in] / [Cancel]
- 点击 [Complete check-in] 后,面板先收起,再执行任务行反馈动画
- 提交成功后移除该任务,并在首页显示反馈条
MVP 反馈动画(已确定):
- 不生成新色块元素,直接使用任务行左侧原色块做动画
- 动画节奏:轻微上弹 → 向下坠落 → 小弹跳 → 缩小淡出消失
- 同时任务行淡出后移除,避免列表抖动
- 成功反馈文案:
{颜色名} 已加入你的色板+累计 walk 次数 - 反馈操作:[查看我的色板](主) / [继续转色轮](次)
- 成功反馈层自动消失(建议 2.5-3 秒)
- 动效无障碍降级:检测
prefers-reduced-motion: reduce时禁用位移/弹跳,仅保留短时淡出
异常与边界状态:
- 未登录点击 [Check in]:拉起登录弹窗,登录成功后回到首页并恢复对应任务的打卡状态
- 提交失败:保留当前内联面板,提示“打卡失败,请重试”
- 同时仅允许 1 个任务处于“打卡展开/提交/动画”状态
4.2.1 首页 UI 布局(MVP)
桌面端(已确定):
- 采用左右分区布局(方案 C)
- 左侧:色轮 + 结果展示 + Spin 操作
- 右侧:任务列表 + 打卡内联展开区 + 反馈条
移动端(已确定):
- 采用上下结构(方案 A)
- 上半区:色轮 + 结果展示 + Spin 操作
- 下半区:任务列表(任务行内联展开打卡)
统一约束:
- 打卡动作在首页内完成,不新增
/checkin路由页面 - 反馈动画以“下落消失”表达收纳结果,不依赖首页展示色板容器
- 首页顶部 Hero 区提供 CTA;点击后平滑滚动至色轮区域
- 任务列表空状态仅展示标题 + 引导文案(不显示按钮):
- 标题:
No tasks yet - 引导:
Spin the wheel to get your first color task.
- 标题:
- 任务上限与重复提示使用 Toast,位置为顶部居中(top-center)
- 首页展示核心统计:
Total walks、Collected N/72 - MVP UI 文案使用英文
4.2.2 首页交互体验优化(已实现,2026-03-19)
本次落地目标: 降低右侧任务操作体感卡顿,提升暗黑模式一致性与操作反馈清晰度。
已完成项:
- 组件命名收敛:首页色轮核心组件统一为
ColorWalkSpin(文件color-walk-spin.tsx),移除mvp-home命名。 - 暗黑模式视觉修复:
- Spin 按钮外圈改为跟随主题背景色(不再固定亮色白环)。
- 色轮中心环与外圈高光增加 dark 适配,避免暗色场景下发白突兀。
- To-do 内联确认面板(check-in 面板)补齐 dark 背景与边框样式。
- 任务操作性能优化(右侧区域):
Add to To-do/Delete/Check in/Complete check-in改为乐观更新(Optimistic UI),优先更新界面再异步提交。- 接口失败时执行回滚,并显式 Toast 提示(例如
Changes were undone/Item was restored),避免用户感知“莫名跳变”。
- 动画体验优化:
Add to To-do增加任务行进入动画(淡入 + 上移回弹 + 轻微高亮),并兼容prefers-reduced-motion。- 点击删除图标增加任务行离场动画(淡出后移除),动画期间禁用该行按钮防止重复触发。
埋点状态(实现说明):
- 为降低当前链路时延,本轮已临时移除以下接口内的
recordColorWalkEvent调用:/api/colorwalk/spin/api/colorwalk/task/delete/api/colorwalk/checkin/start/api/colorwalk/checkin/complete
- 后续恢复建议:采用异步事件队列或非阻塞上报,避免再次影响主交互链路时延。
4.2.3 V1 内联打卡面板增强(照片 + 情绪)
位置与结构(已确定):
- 触发位置:用户在首页任务行点击 [Check in] 后展开的内联面板
- 面板顺序:颜色信息区 → 照片上传区 → 情绪标签区 → 操作区([Complete check-in] / [Cancel])
照片上传规则(已确定):
- 每次打卡最多 9 张图片
- 单张大小限制:5MB
- 总大小限制:45MB
- 支持格式:
jpg/jpeg/png/webp/heic/heif(不支持gif/svg) - 上传方式:
- 支持文件选择
- 支持网页端拖拽上传(拖入区域高亮)
- 不支持移动端直接拍照
- 拖拽边界:
- 拖入数量超过上限时,整批拒绝并提示(不做“截取前 N 张”)
- 拖入文件夹时忽略并提示“仅支持图片文件”
- 上传流程:
- 上传中禁用 [Complete check-in]
- 若存在上传失败图片,允许用户删除失败项后继续提交
- 失败后保留其余已成功图片与已选情绪
- 图片处理:
- 客户端自动压缩(建议长边约 2048)
- 压缩参数建议固定:JPEG
quality=0.82 heic/heif统一转jpeg- 去除 EXIF 元数据,降低隐私暴露风险
- 保留用户上传顺序用于展示与存储
- 页面关闭提醒:当存在“上传中/未提交变更”时,提示离开将丢失未保存内容
- 临时文件清理:仅清理“未绑定到任一 checkin 的临时对象”
情绪标签规则(已确定):
- 情绪为可选项,不选择也可提交
- 交互为单选,可取消(点击已选项再次取消)
- 展示形态:
emoji + 英文短标签,并显示 hover/selected 文本提示 - 情绪枚举值(写入库):
calm | excited | healed | grateful | lazy | melancholy - UI 展示文案(英文):
- 😌 Calm
- 🤩 Excited
- 🫶 Healed
- 🙏 Grateful
- 😴 Lazy
- 😔 Melancholy
提交与异常(已确定):
- 提交前置条件:无图片处于上传中
- 提交失败:不收起面板,保留用户当前输入状态并提示重试
- 无障碍降级:
prefers-reduced-motion: reduce下仅使用低动效反馈
4.3 社区广场
描述: 展示所有用户上传的 walk 照片,支持两种浏览模式。社区为可选功能,用户可以选择不上传照片,仅使用工具记录。
模式一:瀑布流广场
- 默认视图,展示全站最新上传
- 瀑布流布局(两列或三列)
- 每张卡片显示:照片、对应颜色色块、用户昵称、点赞数
- 支持无限滚动加载
模式二:按颜色浏览
- 顶部展示颜色色块列表(横向滚动)
- 点击某个颜色,筛选出所有人拍摄该颜色的照片
- 同样使用瀑布流布局
4.4 点赞与评论
点赞:
- 需要登录才能点赞
- 每个用户每张照片只能点赞一次
- 点赞数实时显示
评论:
- 需要登录才能评论
- 评论最多 150 字
- 发布者可删除自己的评论
4.5 账号系统
注册/登录方式:
- 邮箱 + 密码
- Google 一键登录(可选,二期)
匿名访问权限:
- 可以浏览社区广场
- 可以查看照片详情和评论
- 不能点赞、不能上传、不能评论
登录后权限:
- 以上所有 + 点赞 + 上传照片 + 发表评论
4.6 个人主页
色板
- MVP 采用网格 + 次数标记(×N)
- 完整形态为固定容器宽度流式排列:
- 全部 31 种预设颜色都显示在容器内
- 未打卡的颜色:有灰色调的半透明小色块
- 已打卡的颜色:实心色块,宽度随打卡次数动态增长
- 打卡次数越多,色块越宽,其他颜色自动换行重新排列
- 顶部显示收集进度:已收集 N/31 种颜色、累计 N 次 walk
照片墙
- 展示单位为“单次 walk 图组”,不是单张图片平铺
- 默认按时间倒序排列(最新 walk 在前)
- 支持按颜色筛选图组
- 每个图组卡片包含:
- 头部信息:颜色色块、颜色名、打卡时间
- 内容区:该次 walk 的多图拼贴预览(1-9 张)
- 辅助信息:
N photos、情绪标签(如有)
- 点击图组内任一图片后,使用弹窗(Lightbox)展开查看
- 可对历史 walk 图片执行补传、单图删除、替换(换图)
- 历史操作仍受同一约束:最多 9 张、总大小 45MB、格式限制一致
- 允许删除到 0 张图片(保留该 walk 打卡记录)
- 删除整个 walk 需二次确认,并明确提示会删除该 walk 关联的全部图片
- V1 不提供批量删图,仅支持单图删除与整次 walk 删除
4.6.2 照片墙查看交互(V1)
- 弹窗打开定位到用户点击的那一张图(同组内)
- 支持组内逐张查看(上一张/下一张)
- 弹窗显示当前序号(例如
2/6) - 弹窗展示当前 walk 元信息:颜色、时间、情绪(可空)
- 支持
Esc关闭弹窗,左右方向键切图
统计数据
- 累计 walk 次数
- 加入时间
4.6.1 MVP UI 信息架构(已确定)
- 入口:导航栏头像下拉菜单进入个人主页
- 页面上层提供一级切换:
My Color Walk/Setting - 个人主页主体沿用双栏布局:
- 左栏二级菜单(V1):
My Palette、My Photos(不展示Account) - 右栏内容区按二级菜单切换:
My Palette:展示色板与统计My Photos:展示个人照片墙(按 walk 分组)
Stats不做独立菜单,合并进My Palette页面顶部My Palette页内包含:- 顶部统计:
Total walks、Collected N/72、Joined {date} - 72 色网格:已收集为实色并显示
×N,未收集为灰色半透明
- 顶部统计:
MVP 个人主页 ASCII(桌面端)
┌──────────────────────────────────────────────────────────────────────────────┐
│ Nav (avatar ▼) │
├──────────────────────────────────────────────────────────────────────────────┤
│ [ My Color Walk ] [ Setting ] │
├──────────────────────────────────────────────────────────────────────────────┤
│ My Color Walk
┌──────────────────────┐ ┌────────────────────────────────────────────────┐ │
│ │ My Palette │ │ │ │
│ │ │ │ Total walks: 12 Collected: 8/72 Joined: ...│ │
│ │ │ ├────────────────────────────────────────────────┤ │
│ │ │ │ [■][■][□][□][■x2][□][□][■] ... │ │
│ │ │ │ [□][□][■][□][□][□][■x3][□] ... │ │
│ │ │ │ [□][■][□][□][□][■][□][□] ... │ │
│ │ │ │ ... (72 cells) │ │
│ └──────────────────────┘ └────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────────────────┘MVP 个人主页 ASCII(移动端)
┌──────────────────────────────┐
│ Nav (avatar) │
├──────────────────────────────┤
│ [My Color Walk] [Setting] │
├──────────────────────────────┤
│ 三 My Color Walk
│ Total walks: 12 │
│ Collected: 8/72 │
│ Joined: ... │
├──────────────────────────────┤
│ [■][■][□][□][■x2][□] ... │
│ [□][■][□][□][□][■] ... │
│ ... (72 cells) │
└──────────────────────────────┘情感色谱报告
- 按月/年维度,将用户拍摄的颜色与情绪标签聚合,生成可视化色谱图
- 展示用户个人的色彩-情绪关联规律(需累积足够数据后解锁,建议至少 10 次 walk)
- 报告维度:最常出现的颜色、最常选择的情绪、颜色与情绪的交叉分布
4.7 阶段性挑战与荣誉系统
挑战类型
- 收集类挑战:10 种不同颜色、30 种不同颜色、集齐彩虹七色
- 数量类挑战:累计上传 10 张照片、50 张照片、200 张照片
- 情绪类挑战:使用全部 6 种情绪标签各至少一次、同一颜色记录 3 种不同情绪
约束
- 不设计按天连续打卡类挑战
- 挑战体系后续按“低压力、非强制日更”原则重设计
荣誉徽章
- 每个挑战对应一枚徽章,完成后永久解锁
- 徽章展示在个人主页,按解锁时间排列
规则
- 挑战进度自动追踪,无需手动参与
- 个人主页展示已解锁徽章 + 进行中挑战进度
- 不设积分、排行榜
4.8 色彩热力图
功能
- 世界地图视图,展示所有标记了地理位置的 walk
- 热力图按颜色分层,可切换查看特定颜色的地理分布
- 点击地图上的热点区域,查看该区域用户上传的照片
- 支持按时间筛选(本周、本月、全部)
隐私
- 地理位置为可选项,每次打卡可单次选择是否标记
- 位置精度为城市级别,不显示精确坐标
- 不使用全局位置开关
展示位置
- 独立页面
/map - 社区广场顶部导航可进入
5. 不做的功能(Out of Scope)
| 功能 | 原因 |
|---|---|
| 颜色验证 | 破坏正念氛围,用户自觉即可 |
| 关注 / 粉丝系统 | 增加社交压力,保持轻量 |
| 积分排行榜 | 容易产生竞争压力,与产品调性不符 |
| 私信 | 不需要 |
6. 页面结构
/ 首页(色轮 + 任务列表 + 打卡反馈内嵌展示)
/community 社区广场(瀑布流)
/community/:color 按颜色筛选
/map 色彩热力图
/profile/:userId 个人主页
/login 登录/注册7. 非功能需求
- 响应式设计,优先移动端体验
- 图片加载使用懒加载 + CDN
- 首屏加载时间 < 2s
7.1 指标口径(统一定义)
- 统计时区:UTC+8(Asia/Shanghai)
- 注册用户:完成账号创建且首次登录成功的用户
- 活跃用户(WAU):自然周内至少触发 1 次核心事件(
spin_wheel/complete_checkin/view_community_feed/view_profile_palette) - D7 留存:注册后第 7 天(按注册日 + 7)的回访用户占注册用户比例
- 7 日内完成 ≥3 次打卡比例:注册后 7 天窗口内
complete_checkin事件次数 ≥ 3 的注册用户 / 同期注册用户 - 色板查看率:完成打卡后 10 分钟内触发
view_profile_palette的用户数 / 触发complete_checkin的用户数 - 有照片打卡占比:含至少 1 张照片的
complete_checkin/ 全部complete_checkin - 社区广场周访问率:自然周内触发
view_community_feed的活跃用户 / 全部活跃用户 - 评论渗透率:自然周内有至少 1 条评论的帖子数 / 自然周内有曝光的帖子数
- 地图功能使用率:自然周内触发
view_map的活跃用户 / 全部活跃用户 - 年度报告查看率:满足解锁门槛用户中触发
view_emotion_report_yearly的用户比例 - 色板分享率:触发
share_palette_image的用户 / 活跃用户
7.2 数据预埋规范(跨版本)
目标
- MVP 不上线挑战功能,并预留后续扩展结构;挑战进度从 V2 才开始累计。
事件清单(MVP 最小充分集)
| 事件名 | 触发时机 | 必填字段 |
|---|---|---|
spin_wheel | 每次转色轮完成 | user_id(可空), session_id, color_id, trigger_source, created_at |
task_added | 颜色加入任务列表 | user_id(可空), session_id, color_id, task_count_after, created_at |
task_deleted | 删除任务列表颜色 | user_id(可空), session_id, color_id, task_count_after, created_at |
checkin_started | 首页任务行点击 [Check in] 并展开内联打卡面板 | user_id, checkin_id, color_id, entry_surface(home_task_inline), created_at |
complete_checkin | 提交打卡成功 | user_id, checkin_id, color_id, has_photo, photo_count, emotion_tag(可空), created_at |
view_home_feedback | 首页反馈层展示 | user_id, checkin_id, color_id, created_at |
view_profile_palette | 访问个人色板 | user_id, profile_user_id, entry_source, created_at |
数据表预留(MVP 先建表)
challenge_definitions:id,code,name,type,rule_json,is_active,created_atuser_challenge_progress:id,user_id,challenge_id,progress_value,status,completed_at(可空),updated_atchallenge_progress_events:id,user_id,challenge_id,source_event,delta,created_at
业务原子字段(写入打卡主表)
checkins必须包含:id,user_id,color_id,created_at,has_photo,photo_count,emotion_tag(可空),visibility(private|public)- V3 预留字段:
location_shared,city_code(可空)(V3 才采集) - 约束:
photo_count默认0;has_photo与photo_count一致 emotion_tag枚举:calm | excited | healed | grateful | lazy | melancholy(可空)
照片表(V1 新增)
checkin_photos建议字段:id,checkin_id,user_id,object_key,url,sort_ordermime_type,size_bytes,width(可空),height(可空)created_at,updated_at,deleted_at(可空)
- 说明:
- 图片二进制不入库,统一存储在 R2
- 支持单图删除(按
id/object_key) - 支持按
checkin_id前缀批量清理 - 单图/整次 walk 删除后需同步回写
photo_count与has_photo(删到 0 时has_photo=false)
匿名到登录合并规则
- 未登录行为使用
session_id记录;登录后不追溯改写历史事件,只从登录时点起按user_id统计挑战 - MVP 游客态不保存任务列表,因此不存在登录后任务并集合并逻辑
版本开关
- 挑战累计开关:V2 开启;MVP/V1/V1.5 不累计、不回填
- 位置采集开关:V3 开启;MVP/V1/V1.5/V2 不采集
质量门槛(上线前自测)
- 事件丢失率 < 1%(客户端触发数与服务端入库数差异)
- 关键事件去重:
complete_checkin按checkin_id幂等 - 事件与业务表可对账:
complete_checkin数量与checkins新增记录数日维度一致 - 埋点版本字段
schema_version必填,默认1
7.3 媒体存储与可见性策略(V1 已确定)
存储方案
- 使用 Cloudflare R2 存储打卡图片
- 复用现有存储桶(不新建 bucket),通过路径前缀隔离业务
- 图片采用单对象复用策略:同一张图片只存一份,不因 private/public 切换而复制
对象路径规范
- 头像等通用资源与 Color Walk 资源分离
- 建议路径:
avatars/...(头像)colorwalk/checkins/{userId}/{checkinId}/{photoId}.{ext}(打卡图片)
可见性策略
- 可见性由业务字段控制(
checkins.visibility),而非复制对象控制 - V1 默认
private - V1.5 社区阶段开启
public后,仅查询并展示visibility=public的记录 - V1 后端强制写入
visibility=private,前端不提供可见性切换入口 - 用户可见性说明:
- 用户始终可查看自己的 private 图片
- private 图片通过后端签发 Signed URL 访问
- Signed URL 过期时间:10 分钟(TTL=10m)
- Signed URL 过期后由前端静默重签,用户无感知
接口命名与职责
- 新增 Color Walk 专用上传接口:
/api/colorwalk/photos/upload - 不复用通用
/api/storage/upload-image作为业务入口 - 资源操作接口建议:
- 绑定图片到打卡:
POST /api/colorwalk/checkins/:checkinId/photos - 删除单图:
DELETE /api/colorwalk/checkins/:checkinId/photos/:photoId - 历史换图:通过“上传新图 + 删除旧图”完成
- 删除整次 walk:二次确认后执行级联删除(checkin + checkin_photos + R2 对象)
- 绑定图片到打卡:
- 权限边界:补传/换图/删图/删 walk 仅允许该 checkin 所属用户操作,服务端按
user_id + checkin_id严格校验
去重策略(V1 已确定)
- Color Walk 专用上传接口不做去重(不做跨用户、跨 checkin、同 checkin 去重)
- 每次上传生成独立对象 key,确保图片删除与权限控制相互独立
上传中断与回收策略(V1 已确定)
- 用户在上传/编辑过程中关闭页面时,未提交内容视为未保存
- 页面需提示“离开会丢失未保存内容”
- 对未绑定临时对象执行延迟清理(建议 24 小时后)
- 清理任务执行频率:建议每 6 小时运行一次
7.4 V1 API Contract(已确定)
目标
- 为 V1 提供最小充分的接口边界,覆盖“上传、提交打卡、历史改图”三类核心场景。
接口清单与职责
POST /api/colorwalk/photos/upload- 职责:上传图片到 R2,返回临时资源标识;不直接绑定 checkin。
POST /api/colorwalk/checkin/complete- 职责:完成打卡并绑定已上传图片;写入情绪标签与图片计数。
GET /api/colorwalk/checkins/:checkinId/photos- 职责:获取该 walk 的图片列表(private 资源返回 Signed URL)。
POST /api/colorwalk/checkins/:checkinId/photos- 职责:为历史 walk 追加图片(补传绑定)。
DELETE /api/colorwalk/checkins/:checkinId/photos/:photoId- 职责:删除单张图片并回写统计字段。
DELETE /api/colorwalk/checkins/:checkinId- 职责:删除整次 walk(需前端二次确认后调用,服务端级联删除关联图片与对象)。
核心请求字段(摘要)
- 上传接口:
files[](multipart/form-data)
- 完成打卡接口:
checkinId,colorId,sessionIdemotionTag(可空,枚举:calm|excited|healed|grateful|lazy|melancholy)tempPhotoIds[](可空)
- 历史补传接口:
tempPhotoIds[]
核心响应字段(摘要)
- 上传接口:
tempPhotos[]:tempId,objectKey,mimeType,sizeBytes,width,height
- 完成打卡接口:
stats,paletteCounts,photoCount,emotionTag
- 图片查询接口:
photos[]:photoId,signedUrl,objectKey,sortOrder,mimeType,sizeBytes
关键约束(服务端口径)
- 上传限制:最多 9 张,单张 5MB,总计 45MB,格式
jpg/jpeg/png/webp/heic/heif。 - 媒体处理:
heic/heif转jpeg,压缩参数 JPEGquality=0.82,去 EXIF。 - 可见性:V1 服务端强制
visibility=private,前端不提供切换开关。 - 私有访问:Signed URL,TTL=10 分钟,前端过期后静默重签。
- 权限:补传/换图/删图/删 walk 仅允许 checkin 所属用户操作(
user_id + checkin_id严格校验)。 - 去重:Color Walk 不做图片去重,每次上传生成独立对象 key。
8. 待讨论事项
8.1 Streak 判定细则
- 已移除 Streak 机制(当前版本不设计连续打卡挑战)
8.2 地理位置交互
- 已确定:每次打卡单次选择是否标记城市级位置
8.3 个人色板最终形态上线时机
- 已确定:动态宽度流式布局在 V2 上线
8.4 页面信息架构
- 已确定:首页承载核心流程与打卡反馈展示,不单独建设打卡反馈页面
- 已确定:MVP 打卡动作在首页任务列表内联完成,不新增独立打卡页
8.5 挑战累计起始版本
- 已确定:挑战进度从 V2 开始累计,不追溯 MVP/V1/V1.5
8.6 位置采集起始版本
- 已确定:地理位置从 V3 开始采集
8.7 挑战规则设计时点
- 已确定:MVP 先不细化,待上线后观察 2-4 周数据再定
8.8 MVP 首页交互与动画方案
- 已确定:桌面端首页采用左右分区(方案 C),移动端采用上下结构(方案 A)
- 已确定:点击 [Check in] 后任务行内联展开确认面板,点击 [Complete check-in] 后先收起面板再播动画
- 已确定:反馈动画使用任务行原色块执行“上弹-下落-小弹跳-淡出消失”,不生成新色块
- 已确定:检测到
prefers-reduced-motion: reduce时使用低动效版本(仅淡出) - 已确定:任务上限/重复颜色提示使用 top-center Toast;成功反馈自动消失
- 已确定:首页空状态仅保留
No tasks yet+ 引导文案,不放额外按钮
8.9 V1 图片上传交互细则
- 已确定:支持网页端拖拽与文件选择,不支持移动端直接拍照
- 已确定:支持格式为
jpg/jpeg/png/webp/heic/heif,不支持gif/svg - 已确定:单张 5MB、总计 45MB(最多 9 张)
- 已确定:拖入超过 9 张整批拒绝并提示;拖入文件夹忽略并提示
- 已确定:有图片上传中时禁用提交;有失败项时允许删除失败项后继续提交
- 已确定:客户端自动压缩并去除 EXIF;
heic/heif统一转jpeg - 已确定:压缩参数固定为 JPEG
quality=0.82 - 已确定:上传中/未提交变更时,关闭页面需提示未保存内容会丢失
- 已确定:V1 不提供批量删图,仅支持单图删除与整次 walk 删除
8.10 V1 情绪标签交互细则
- 已确定:情绪可不提交
- 已确定:情绪为单选且可取消
- 已确定:UI 采用 emoji + 英文短标签,并提供 hover/selected 文本提示
- 已确定:
emotion_tag使用固定枚举:calm | excited | healed | grateful | lazy | melancholy
8.11 打卡图片存储与公开策略
- 已确定:使用 Cloudflare R2,复用现有 bucket,不新增 bucket
- 已确定:Color Walk 使用独立路径前缀,避免与头像上传混用
- 已确定:采用单对象复用,不因 private/public 切换复制对象
- 已确定:V1 默认 private;V1.5 起按
visibility=public进入社区可见范围 - 已确定:private 图片通过 Signed URL 访问,TTL 为 10 分钟;用户始终可见自己的 private 图片
- 已确定:Signed URL 过期后由前端静默重签,用户无感知
- 已确定:V1 由后端强制写入
visibility=private,前端不展示可见性开关 - 已确定:Color Walk 上传不做去重(跨用户/跨 checkin/同 checkin 均不去重)
- 已确定:删除整个 walk 需二次确认,并级联删除关联图片对象
- 已确定:补传/换图/删图/删 walk 仅允许 checkin 所属用户操作(服务端校验)
- 已确定:未绑定临时对象清理策略为“24 小时后清理”,任务每 6 小时执行一次