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 首页内联打卡流程(已确定):

  1. 在首页任务列表点击 [Check in]
  2. 当前任务行展开内联打卡面板(不跳转页面):
    • 展示当前颜色色块 + 颜色名称
    • 文案:“你完成这次 Color Walk 了吗?”
    • 操作:[Complete check-in] / [Cancel]
  3. 点击 [Complete check-in] 后,面板先收起,再执行任务行反馈动画
  4. 提交成功后移除该任务,并在首页显示反馈条

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 walksCollected 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 PaletteMy Photos(不展示 Account
  • 右栏内容区按二级菜单切换:
    • My Palette:展示色板与统计
    • My Photos:展示个人照片墙(按 walk 分组)
  • Stats 不做独立菜单,合并进 My Palette 页面顶部
  • My Palette 页内包含:
    • 顶部统计:Total walksCollected N/72Joined {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_definitionsid, code, name, type, rule_json, is_active, created_at
  • user_challenge_progressid, user_id, challenge_id, progress_value, status, completed_at(可空), updated_at
  • challenge_progress_eventsid, 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 默认 0has_photophoto_count 一致
  • emotion_tag 枚举:calm | excited | healed | grateful | lazy | melancholy(可空)

照片表(V1 新增)

  • checkin_photos 建议字段:
    • id, checkin_id, user_id, object_key, url, sort_order
    • mime_type, size_bytes, width(可空), height(可空)
    • created_at, updated_at, deleted_at(可空)
  • 说明:
    • 图片二进制不入库,统一存储在 R2
    • 支持单图删除(按 id/object_key
    • 支持按 checkin_id 前缀批量清理
    • 单图/整次 walk 删除后需同步回写 photo_counthas_photo(删到 0 时 has_photo=false

匿名到登录合并规则

  • 未登录行为使用 session_id 记录;登录后不追溯改写历史事件,只从登录时点起按 user_id 统计挑战
  • MVP 游客态不保存任务列表,因此不存在登录后任务并集合并逻辑

版本开关

  • 挑战累计开关:V2 开启;MVP/V1/V1.5 不累计、不回填
  • 位置采集开关:V3 开启;MVP/V1/V1.5/V2 不采集

质量门槛(上线前自测)

  • 事件丢失率 < 1%(客户端触发数与服务端入库数差异)
  • 关键事件去重:complete_checkincheckin_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, sessionId
    • emotionTag(可空,枚举: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/heifjpeg,压缩参数 JPEG quality=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 小时执行一次