docs(plan): UI-02 viewer redesign implementation plan
Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,216 @@
|
||||
# UI-02 观众页视觉重构 实施计划
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** 按 [UI02 方案](2026-09-21-UI02-观众页效果图落地实施方案.md)和[设计概念](../designs/viewer-mobile-concept-2026-09-21.png)完成观众页视觉重构:蓝白活动首页(品牌栏+宣传图+信息+筛选+瀑布流)+ 深色沉浸式大图查看器(缩略图导航+点赞粒子+分享下载)——不改变任何业务逻辑。
|
||||
|
||||
**Architecture:** 纯 viewer 前端改造(apps/viewer)。不新增 API/契约变更(UI-02 §9.3 明确:如果实现发现必须扩展,先记录再兼容变更)。不修改 App/admin/embed。样式作用域隔离(.viewer-shell / .album-page / .photo-viewer),不影响 EmbedPage。
|
||||
|
||||
**Tech Stack:** Vue 3 + TypeScript + CSS(新 CSS 变量文件),零新框架依赖。
|
||||
|
||||
**对应验收:** V-A01 至 V-A15(方案 §9.2)。
|
||||
|
||||
**依赖基线:** 当前 HEAD(含 UI-01 tag ui01)。
|
||||
|
||||
---
|
||||
|
||||
## 方案分析
|
||||
|
||||
| 维度 | 评估 |
|
||||
|---|---|
|
||||
| 复杂度 | 高——PhotoLightbox 完全重构(缩略图条+底部操作栏+粒子动效),PhotoFeed 重排(响应式列数+点赞角标+新图提示) |
|
||||
| 风险点 | ① EmbedPage 共用 viewer 工程——样式必须作用域隔离 ② 缩略图条与 usePhotoSequence 的集成 ③ 粒子动效的 DOM 数量控制 ④ 位置计数的真实回退逻辑(不伪造总数) |
|
||||
| 与 UI-01 的关系 | UI-01 已改 embed 组件样式——UI-02 只改普通相册路由的样式,通过 CSS 作用域隔离 |
|
||||
| 不变项 | usePhotoSequence 单一数据源、useLikes 业务逻辑、useAlbumRealtime WS/轮询、useDownload 权限、路由语义、浏览去重上报 |
|
||||
|
||||
---
|
||||
|
||||
## Task 1: V00 基线与代码核对
|
||||
|
||||
- [ ] Git 状态核对(UI-01 已提交,工作树应清洁);记录当前 HEAD
|
||||
- [ ] 启动 viewer dev server + 后端;截图当前首页(zh/en)+ 大图(zh/en)作为基线
|
||||
- [ ] 阅读 ActivityPage.vue / PhotoFeed.vue / PhotoLightbox.vue / usePhotoSequence / useLikes / useAlbumRealtime / useDownload / zoom.ts——记录每个文件的职责和现有数据流
|
||||
- [ ] 确认 EmbedPage 的样式不受影响(检查 App.vue 中的布局条件)
|
||||
- [ ] 创建 `docs/plans/progress/UI02-验收记录.md` 骨架
|
||||
- [ ] Commit `docs(ui02): baseline screenshots and acceptance skeleton`
|
||||
|
||||
---
|
||||
|
||||
## Task 2: V01+V02 视觉基础 + 首页信息区
|
||||
|
||||
**Files:**
|
||||
- Create: `apps/viewer/src/styles/viewer-tokens.css`(全部 CSS 变量)
|
||||
- Modify: `apps/viewer/src/App.vue`(普通布局顶栏+容器)
|
||||
- Modify: `apps/viewer/src/components/LocaleSwitcher.vue`(紧凑化)
|
||||
- Create: `apps/viewer/src/components/album/AlbumHeader.vue`(宣传图+信息区)
|
||||
- Modify: `apps/viewer/src/pages/ActivityPage.vue`(使用新组件)
|
||||
|
||||
- [ ] **CSS 变量**(方案 §3.1 精确值):
|
||||
```css
|
||||
.viewer-shell {
|
||||
--viewer-primary: #1A73E8;
|
||||
--viewer-surface: #FFFFFF;
|
||||
--viewer-page-bg: #F3F6FA;
|
||||
--viewer-text: #172033;
|
||||
--viewer-text-secondary: #647084;
|
||||
--viewer-divider: #E5EAF1;
|
||||
--viewer-dark-bg: #0E1218;
|
||||
--viewer-like-accent: #FF667D;
|
||||
--viewer-radius-img: 4px;
|
||||
--viewer-radius-pill: 20px;
|
||||
--viewer-padding-info: 16px;
|
||||
--viewer-padding-photo: 4px;
|
||||
}
|
||||
```
|
||||
- [ ] **App.vue 顶栏**:品牌名(左)+ 语言切换(右),高 48-52px,白色背景,底部细线。减少动画入口放语言旁的轻量菜单(可发现但不占整行)。普通路由有顶栏;embed 路由无顶栏无外边距(验证不被破坏)
|
||||
- [ ] **LocaleSwitcher**:紧凑 "EN ▾" 形态(非全宽下拉)
|
||||
- [ ] **AlbumHeader.vue**(新组件):
|
||||
- 宣传图全宽(约 2.4:1 手机,桌面限高 320px,contain 优先不裁切海报文字;无图收起)
|
||||
- 标题(≤2 行 + 展开查看)+ 分享按钮(右侧,不压缩标题)
|
||||
- 说明(≤3 行 + 展开/收起,保留换行)
|
||||
- 元信息行:浏览次数(真实 viewCount, Intl.NumberFormat,未知显示 "—")+ 日期(相册时区)+ 地点;窄屏可换行
|
||||
- 缺字段自然省略(null/undefined 不显示)
|
||||
- [ ] **排序/分类工具栏**:
|
||||
- Latest / Popular tab(高 44px,选中蓝字+底部 2px 线)
|
||||
- 分类胶囊(选中蓝底白字;横向滚动+溢出提示;键盘可访问)
|
||||
- 无分类省略分类条;All = 不传分类筛选
|
||||
- [ ] vitest:token 值断言、AlbumHeader 各字段渲染/缺失省略/展开收起、工具栏 tab 切换回调
|
||||
- [ ] Commit `feat(viewer): UI-02 visual foundation, top bar and album info`
|
||||
|
||||
---
|
||||
|
||||
## Task 3: V03 瀑布流重排
|
||||
|
||||
**Files:**
|
||||
- Modify: `apps/viewer/src/components/PhotoFeed.vue`
|
||||
- Modify: `apps/viewer/src/feed/layout.ts`
|
||||
|
||||
- [ ] **响应式列数**:
|
||||
- <600px: 2 列, gap 4px
|
||||
- 600-959px: 3 列, gap 6px
|
||||
- ≥960px: 4 列, gap 8px(主内容 max-width 1120px)
|
||||
- 窗口 resize 重新布局(现有 ResizeObserver 或 LayoutBuilder)
|
||||
- [ ] **图片卡片重设计**:
|
||||
- 无白色厚卡片、无常驻文件名、无额外标题
|
||||
- 圆角 4-6px
|
||||
- 右下角:心形图标 + 真实点赞数(半透明暗色底确保可读)
|
||||
- 点赞控件独立交互(阻止冒泡,不嵌套 button)
|
||||
- 图片点击 → 打开大图(现有行为保留)
|
||||
- [ ] **新照片提示**:
|
||||
- 白色 pill "有新照片 ↑",点击加载合并(现有行为)
|
||||
- 只有确切数量时才显示数字("8 new photos"),否则只写"有新照片"
|
||||
- 不在用户浏览时强制跳到顶部
|
||||
- [ ] **骨架与加载**:
|
||||
- 首屏骨架按真实瀑布流比例占位(不是均匀网格)
|
||||
- 翻页加载失败底部重试(不清空已有图片)
|
||||
- "已到底" 文案
|
||||
- [ ] **宽高安全**:缺失/异常宽高用安全占位比例(避免 NaN/无限高度)
|
||||
- [ ] vitest:列数计算(320/600/960 断点)、点赞角标渲染+冒泡阻止、新图提示显隐、骨架占位比例
|
||||
- [ ] Commit `feat(viewer): UI-02 responsive waterfall with like badges`
|
||||
|
||||
---
|
||||
|
||||
## Task 4: V04 深色大图查看器
|
||||
|
||||
**Files:**
|
||||
- Rewrite: `apps/viewer/src/components/PhotoLightbox.vue`
|
||||
- Create: `apps/viewer/src/components/viewer/ThumbnailStrip.vue`(新)
|
||||
- Create: `apps/viewer/src/components/viewer/PhotoActionBar.vue`(新)
|
||||
|
||||
- [ ] **布局层级**(方案 §5.1 ASCII 图):
|
||||
```
|
||||
顶栏(52-56px,深色半透明): × 位置 ⋯菜单
|
||||
图片舞台(flex:1): 完整大图 contain + ‹ › 切换
|
||||
粒子层: pointer-events:none
|
||||
缩略图条(~56px): [thumb][current][thumb]...
|
||||
底部操作栏(88-104px+安全区): ♥ Like Share Download
|
||||
```
|
||||
- [ ] **顶栏**:
|
||||
- 关闭 ×(左,有效区≥44px)
|
||||
- 位置计数(中)——真实回退:有 total 显示 "12 / 248";无 total 显示 "已加载 24 张";深链未定位显示 "照片预览";全部加载完成显示当前筛选序列 i/n(方案 §5.2 精确规则)
|
||||
- 更多菜单 ⋯(右)——至少包含"减少动画"开关;无真实动作则不渲染
|
||||
- [ ] **图片舞台**:
|
||||
- contain 完整显示,不裁切
|
||||
- browse 变体 URL(不默认加载原图)
|
||||
- 左右按钮靠近舞台边界
|
||||
- 双指缩放 + 单指平移(复用 zoom.ts;放大时平移不误触切图)
|
||||
- 键盘:← → 切换,Escape 关闭
|
||||
- [ ] **缩略图条**(新组件):
|
||||
- 显示当前附近最多 7 项(手机可见 5)
|
||||
- 当前项蓝色 2px 描边
|
||||
- 宽 56-64px,高 44-52px
|
||||
- 点击切换到该 photoId(不新增浏览器历史)
|
||||
- 切换后选中项滚动到可见范围
|
||||
- 使用 thumb 变体
|
||||
- [ ] **底部操作栏**(新组件):
|
||||
- Like: coral (#FF667D) 心形 + 累计数 + "Like/点赞" + 下方提示 "连续点击,为照片点赞"
|
||||
- Share: 白色分享图标 + "Share/分享"
|
||||
- Download: 白色下载图标 + "Download/下载"(权限关闭时移除)
|
||||
- 三个均匀分布,有效触控≥44px
|
||||
- 原图下载:Download 长按或二级菜单(仅 originalDownloadEnabled 时)
|
||||
- [ ] **深色主题**:#0E1218 背景,白色/半透明文字
|
||||
- [ ] **安全区**:dvh + safe-area-inset 处理
|
||||
- [ ] **焦点管理**:打开后焦点进入对话框,Escape 关闭,关闭后回到触发图片
|
||||
- [ ] **背景滚动锁定**:打开时锁住 body 滚动
|
||||
- [ ] vitest (~15):位置回退三种模式、缩略图渲染+点击切换、操作栏权限显隐、焦点管理、键盘导航、安全区
|
||||
- [ ] Commit `feat(viewer): UI-02 dark immersive photo viewer with thumbnail strip`
|
||||
|
||||
---
|
||||
|
||||
## Task 5: V05 分享下载与互动粒子
|
||||
|
||||
**Files:**
|
||||
- Modify: `apps/viewer/src/components/PhotoLightbox.vue`(集成粒子)
|
||||
- Create: `apps/viewer/src/components/viewer/HeartParticles.vue`(新)
|
||||
- Create: `apps/viewer/src/components/viewer/InteractionNotice.vue`(新)
|
||||
- Modify: `apps/viewer/src/likes/useLikes.ts`(暴露本地点击动效事件)
|
||||
|
||||
- [ ] **心形粒子**(HeartParticles.vue):
|
||||
- 触发:当前照片本地点击 或 该照片收到他人点赞 WS 事件
|
||||
- 视觉:18-30px coral 心形,2-3 条漂移轨迹,持续 1.2-1.8s
|
||||
- 大图内靠右侧上浮;首页在照片区右侧
|
||||
- pointer-events: none, aria-hidden: true
|
||||
- 同时最多 12 个装饰粒子(超出丢弃最旧)
|
||||
- 页面隐藏/关闭上下文时清理
|
||||
- 减少动画时不漂浮(计数正常更新)
|
||||
- [ ] **跨照片互动提示**(InteractionNotice.vue):
|
||||
- 保留现有缩略图+心形+delta 可识别提示及点击定位
|
||||
- 大图内放底部操作栏上方安全区
|
||||
- 同时最多 3 条
|
||||
- 不把其他照片计数加到当前照片
|
||||
- [ ] **分享**:
|
||||
- navigator.share 优先;不支持时复制链接
|
||||
- 相册分享:相册路由;照片分享:当前 photoId 深链+语言参数
|
||||
- 复制失败展示可选中文本
|
||||
- 用户取消原生分享不显示错误
|
||||
- [ ] **下载**(复用 useDownload):
|
||||
- 权限关闭时移除下载按钮(不留可绕过直链)
|
||||
- 原图仅在 originalDownloadEnabled 时提供二级选项
|
||||
- 下载中防重复;异步错误归属正确 photoId
|
||||
- 微信等环境提示保留
|
||||
- [ ] **自身回声去重**:同一批次 WS 回传不重复累计、不再制造"他人点赞"粒子
|
||||
- [ ] vitest (~12):粒子生成/清理/上限、减少动画禁用、自身回声过滤、分享复制回退、下载权限组合、异步错误归属
|
||||
- [ ] Commit `feat(viewer): UI-02 heart particles, interaction notices, share and download`
|
||||
|
||||
---
|
||||
|
||||
## Task 6: V06+V07 状态国际化与验收
|
||||
|
||||
- [ ] **全部新文案 zh-CN + en**(方案 §3-§7 所有 UI 文字)
|
||||
- [ ] **状态矩阵**(方案 §7 表格逐项验证):加载中骨架/不可公开/空相册/网络失败/加载更多失败/URL 过期/隐藏删除/深链不存在/WS 断线/分享下载失败
|
||||
- [ ] **无障碍**:aria 标签、焦点可见、模态焦点不穿透、tabular-nums 数字宽度
|
||||
- [ ] **EmbedPage 回归**:确认全局样式不影响嵌入组件(截图+Playwright)
|
||||
- [ ] **全量测试**:`pnpm --filter @photo/viewer lint && typecheck && test && build && test:e2e`
|
||||
- [ ] **截图矩阵**(方案 §9.1):390×844 / 320×568 / 430×932 / 844×390 / 1440×900 × zh/en × 首页/大图
|
||||
- [ ] **V-A01 至 V-A15 逐项验证** + 验收记录完成
|
||||
- [ ] 总纲 UI-02 注记;tag `ui02`;Commit `docs: UI-02 acceptance record`
|
||||
|
||||
---
|
||||
|
||||
## 执行注意
|
||||
|
||||
- **样式隔离红线**:所有新 CSS 在 `.viewer-shell` / `.album-page` / `.photo-viewer` 作用域内;不用全局 `button`/`img` 选择器;验证 EmbedPage 不受影响
|
||||
- **业务零变更**:usePhotoSequence/useLikes/useAlbumRealtime/useDownload 的数据流不改(仅 UI 层消费方式变化)
|
||||
- **数据诚实**:不伪造总数/在线人数/准确位置——按方案 §5.2 的回退规则
|
||||
- **性能红线**:粒子 DOM 有上限、缩略图不加载整相册、不预加载全部 browse 图
|
||||
- 每任务 TDD + 提交带 Co-Authored-By trailer
|
||||
@@ -0,0 +1,396 @@
|
||||
# UI-02:观众页视觉与交互调整实施方案
|
||||
|
||||
版本:1.0
|
||||
日期:2026-09-21
|
||||
状态:待实施;本文是执行规范,不是已完成报告。
|
||||
执行对象:Claude 或其他接手本仓库的开发者。
|
||||
|
||||
## 1. 目标与设计依据
|
||||
|
||||
将现有 Vue 观众页调整为下图的效果:蓝白活动相册首页 + 深色沉浸式照片查看器。必须交付真实可运行页面,不能用整张效果图替代界面,也不能只返回另一份方案。
|
||||
|
||||

|
||||
|
||||
- 设计原图:`docs/designs/viewer-mobile-concept-2026-09-21.png`
|
||||
- 设计说明:`docs/designs/viewer-mobile-concept-2026-09-21.md`
|
||||
- 实施总纲:`docs/plans/2026-09-17-实施总纲.md`
|
||||
- 关联方案:`docs/plans/2026-09-21-UI01-App与悬浮组件体验优化实施方案.md`
|
||||
|
||||
本方案只处理普通观众相册和大图页,不修改 App、不重做管理后台、不改变 JS 嵌入组件。与 UI-01 共用 viewer 工程时,注意样式与文件冲突。
|
||||
|
||||
**优先级:业务需求与权限 > 本文交互/数据规范 > 效果图视觉参考。** 效果图中的摄影内容、标题、日期、人数、点赞数、照片数量均是示例,不写入生产页面。截图两侧布局是两个浏览状态,不是实际页面中同时显示两台手机。
|
||||
|
||||
### 1.1 完成后应具备的体验
|
||||
|
||||
1. 扫码或链接打开,无需登录。
|
||||
2. 顶部品牌与语言切换,宣传图、活动介绍、浏览次数、时间地点。
|
||||
3. 最新/热门及分类筛选,真正的双列瀑布流,新照片提示。
|
||||
4. 点击照片打开全屏深色大图,左右切换、双指缩放、缩略图导航。
|
||||
5. 每张照片均可匿名连续点赞,计数累计;所有在线观众接收相册内其他人的点赞反馈。
|
||||
6. 分享相册或单图,按服务端开关下载;关闭大图返回原浏览位置。
|
||||
7. 中英文完整可用,手机优先,并适配桌面。
|
||||
|
||||
### 1.2 必须遵守的实现边界
|
||||
|
||||
- 不新增登录、评论、关注、上传、管理入口或底部 App 导航。
|
||||
- 不改变海外 API 数据来源、浏览去重、点赞批次幂等、实时重连与轮询降级语义。
|
||||
- 不将连续点赞改成收藏开关,不提供“取消点赞”。
|
||||
- 不把浏览次数显示成在线人数。
|
||||
- 不把已加载照片数量当相册总数,不把热门快照顺序当永久排名。
|
||||
- 不把示例宣传文字叠在所有活动海报上;宣传图可能自带文字。
|
||||
- 不为了视觉效果撤掉减少动画、错误反馈、下载限制、权限撤回处理。
|
||||
- 不生成新品牌,不修改包名或路由体系。现有英文品牌优先,若仓库已有正式 Logo 则复用。
|
||||
- 不覆盖工作树已有改动;实施前重新检查,尤其是 UI-01 同时进行的 App/组件工作。
|
||||
- 不自动部署、推送、执行生产数据初始化或操作云资源。
|
||||
- 常规样式实现按本文默认执行,无需反复询问用户;真实资源缺失时登记并继续不依赖它的任务。
|
||||
|
||||
## 2. 当前代码与改动地图
|
||||
|
||||
当前页面已经实现关键业务编排,应以重排模板、提取展示组件和样式调整为主。
|
||||
|
||||
| 文件 | 当前职责 | 本轮改动 |
|
||||
|---|---|---|
|
||||
| apps/viewer/src/App.vue | 顶栏、语言、减少动画、embed 独立外壳 | 普通相册顶栏与页面容器;保证 embed 不受影响 |
|
||||
| src/pages/ActivityPage.vue | 活动读取、统计、筛选、序列、大图深链、实时互动 | 组织信息区与工具栏,分享编排,明确气泡展示上下文 |
|
||||
| src/components/LocaleSwitcher.vue | 语言切换 | 紧凑 EN/中文控件与可用菜单 |
|
||||
| src/components/PhotoFeed.vue | 瀑布流、懒加载、加载更多、新图提示 | 图片主导布局、点赞角标、骨架与按钮层级 |
|
||||
| src/feed/layout.ts | 图片位置计算 | 移动双列、桌面列数和统一间距(兼容原调用) |
|
||||
| src/feed/sequence.ts | 共享照片序列 | 原则上保持;只扩展必要展示信息,不另建序列 |
|
||||
| src/components/PhotoLightbox.vue | 大图、翻页、缩放、下载等 | 深色布局、底部操作、缩略图条、焦点与安全区 |
|
||||
| src/components/LikeBubbles.vue | 他人点赞反馈 | 心形粒子与可识别的其他照片通知分层 |
|
||||
| src/likes/useLikes.ts | 点赞计数、批次发送 | 保留业务;必要时暴露本地点击动效事件 |
|
||||
| src/realtime/useAlbumRealtime.ts | 实时气泡、数据校准、降级 | 保留去重和限量策略,不复制第二套订阅 |
|
||||
| src/download/useDownload.ts | 下载权限、错误与浏览器引导 | 复用控制器,保持原图/浏览图权限 |
|
||||
| src/ui/prefs.ts | 减少动画偏好 | 保持用户和系统偏好 |
|
||||
| src/i18n/locales/zh-CN.ts、en.ts | 语言资源 | 新文案及可访问性标签 |
|
||||
| src/__tests__/、apps/viewer/e2e/ | 单测和浏览器回归 | 新增重点视觉与交互验证 |
|
||||
|
||||
上表 src 均相对 apps/viewer。可新增 `src/styles/viewer-tokens.css`、`AlbumHeader.vue`、`PhotoThumbnailStrip.vue`、`PhotoActionBar.vue` 等,按实际复用拆分。不要为了文件数量拆分所有小元素。
|
||||
|
||||
## 3. 页面结构与视觉参数
|
||||
|
||||
### 3.1 统一视觉
|
||||
|
||||
| 参数 | 默认值 |
|
||||
|---|---|
|
||||
| 主色 | #1A73E8 |
|
||||
| 页面表面 | #FFFFFF |
|
||||
| 桌面外背景 | #F3F6FA |
|
||||
| 主文字 | #172033 |
|
||||
| 次文字 | #647084 |
|
||||
| 分隔线 | #E5EAF1 |
|
||||
| 深色查看器 | #0E1218 |
|
||||
| 点赞强调 | #FF667D |
|
||||
| 正文字体 | system-ui, -apple-system, Segoe UI, PingFang SC, sans-serif |
|
||||
| 页面左右留白 | 信息区 16px;照片区 4–6px |
|
||||
| 普通图标 | 20–24px,线条风格一致 |
|
||||
| 按钮有效触控区 | 至少 44×44px |
|
||||
| 图片圆角 | 4–6px |
|
||||
| 轻提示圆角 | 20px |
|
||||
| 焦点 | 清晰可见的主色描边,不能取消 outline 后不补替代 |
|
||||
|
||||
标题 22px/28px、正文 14–16px、信息行 12–13px。不能以缩小字体解决英文溢出。使用 tabular-nums 稳定数字宽度。
|
||||
|
||||
效果图外部灰底、左右编号、圆角手机边框、投影只用于展示板,不加入手机实际页面。手机 Web 正常铺满视口,桌面可以有居中内容表面。
|
||||
|
||||
### 3.2 首页层级
|
||||
|
||||
```text
|
||||
品牌 EN ▾
|
||||
宣传图(全宽)
|
||||
活动标题 分享
|
||||
活动说明
|
||||
浏览次数 活动日期 地点
|
||||
Latest Popular
|
||||
All Exhibition People Highlights
|
||||
[新照片提示]
|
||||
双列瀑布流 + 图片右下点赞
|
||||
底部加载更多 / 加载失败重试 / 已到底
|
||||
```
|
||||
|
||||
- 顶栏高约 48–52px,不与活动标题重复。
|
||||
- 减少动画入口放语言旁的轻量菜单或可访问的偏好菜单,不挤占整行标题;功能必须可发现,不能彻底隐藏。
|
||||
- 普通内容页改为无全局 16px 包围的布局,让宣传图和照片充分占宽;内边距分别由信息区和照片区负责。
|
||||
- 首页不固定底部操作栏,不增加账户入口。
|
||||
|
||||
### 3.3 响应式
|
||||
|
||||
| 视口 | 内容与列数 |
|
||||
|---|---|
|
||||
| 320–599px | 全宽,两列瀑布流,间距 4px |
|
||||
| 600–959px | 居中,三列,间距 6px |
|
||||
| 960px 及以上 | 主内容最大宽 1120px,四列,间距 8px |
|
||||
|
||||
宣传图手机建议约 2.4:1,最大宽桌面限制视觉高度约 320px。优先保持宣传图完整内容:默认按原始比例展示并限制过高时使用 contain,不把海报文字强行裁掉。仅在已有素材明确适合裁切时使用 cover。无宣传图直接收起该区域,不显示假广交会海报。
|
||||
|
||||
## 4. 首页组件细则
|
||||
|
||||
### 4.1 宣传图与活动信息
|
||||
|
||||
- 使用实际 album 资产 URL,处理过期与失败;若无法刷新则收起图片,活动信息仍可用。
|
||||
- 标题最多默认两行,超长标题允许展开查看;不要仅靠 title 属性。
|
||||
- 说明默认三行,超出使用展开/收起;保留换行,不按 HTML 注入未信任内容。
|
||||
- 分享按钮位于标题右侧,占位不压缩标题至不可读。
|
||||
- 浏览数采用真实 viewCount;未知显示“—”而非 0。数字格式使用 Intl.NumberFormat,读屏可读完整数字。
|
||||
- 日期按相册时区格式化;首页可紧凑显示,详情可查看完整起止与时区。不要将时区转换悄悄改为设备时间。
|
||||
- 地点、结束日期、说明缺失时自然省略,不显示 null/undefined。
|
||||
- 窄屏元信息可换行,不能硬把三个字段挤在同一行。
|
||||
|
||||
### 4.2 排序和分类
|
||||
|
||||
- Latest/最新默认选中,Popular/热门沿用服务端热门快照。
|
||||
- 标签高约 44px;选中蓝字与底部 2px 线,非选中次文字。
|
||||
- 分类为轻量胶囊,选中蓝底白字。分类来自接口,不硬编码效果图中的分类。
|
||||
- 分类多时横向滚动且有可见溢出提示;键盘能访问所有项。
|
||||
- 没有分类时可省略分类条;All 对应不传分类筛选。
|
||||
- 更换排序/分类沿用原序列重置机制;大图打开期间不允许后台换序造成正在看的照片跳走。
|
||||
- 语言改变只改变显示和内容请求,不随意丢失当前分类 ID。
|
||||
|
||||
### 4.3 瀑布流与新图提示
|
||||
|
||||
- 保留宽高计算和懒加载,不用等高网格取代瀑布流。原图不同高度应实际反映在布局中。
|
||||
- 缺失或异常宽高使用安全占位比例,避免 NaN/无限高度。
|
||||
- 图片无白色厚卡片、无常驻文件名、无额外大标题。右下为心形与真实点赞数。
|
||||
- 图片点击打开大图;点赞控件是独立交互,阻止冒泡,不使用嵌套 button。
|
||||
- 角标文字配轻微暗色渐变/半透明底,明亮照片上也可读。
|
||||
- 有新照片时显示白色小提示,点击后加载/合并;不在用户浏览时强制跳到顶部。
|
||||
- 原接口只有 hasNew 时写“有新照片 / New photos”,不能照抄“8 new photos”。只有确切待展示新增数量时才显示数字。
|
||||
- 首屏骨架按真实瀑布流比例占位;翻页加载失败只在底部重试,不能清空已有图片。
|
||||
- 保留按 photoId 稳定键,不用数组索引作为图片身份。
|
||||
|
||||
## 5. 大图查看器规格
|
||||
|
||||
### 5.1 布局
|
||||
|
||||
全屏深色覆盖层,使用固定定位及 dvh/安全区处理。锁住背景滚动,打开后焦点进入对话框,关闭后回到触发图片。
|
||||
|
||||
```text
|
||||
× 当前位置 ⋯
|
||||
完整大图(contain)
|
||||
‹ ›
|
||||
点赞气泡
|
||||
[缩略图] [当前] [缩略图] [缩略图]
|
||||
Tap to send more love
|
||||
♥ 分享 下载
|
||||
1,286 Share Download
|
||||
```
|
||||
|
||||
- 顶栏约 52–56px,关闭有效区 44px。
|
||||
- 图片舞台占剩余主要空间,纵横比保留,不能照抄示例图片固定高度。
|
||||
- 底部栏约 88–104px 加安全区;短屏可收紧缩略图间距,不能遮挡主要按钮。
|
||||
- 大图选用 browse 变体,缩略图用 thumb,不默认加载原图。
|
||||
- 桌面仍全屏深色查看器,图片居中,左右按钮靠近舞台边界;不要把图片放进带手机外壳的窄卡片。
|
||||
- 更多菜单必须有实际功能,例如减少动画;没有真实动作则不渲染装饰性的三个点。
|
||||
|
||||
### 5.2 位置计数:必须修正示意图的假精确问题
|
||||
|
||||
当前 PhotoLightbox 的 total 来源是已加载 photos.length,深链还可能存在 solo 条目。不得把它当相册总数。
|
||||
|
||||
- 仅当接口提供当前筛选范围的准确 total 且当前位置可确定时,显示“12 / 248”。
|
||||
- 当前序列未到末页但没有 total 时,显示“当前已加载 24 张 / 24 loaded”;可把当前序列位置写成“已加载第 3 张”,但不暗示全相册排名。
|
||||
- 全部加载完成且不是未知定位的 solo 时,可显示当前筛选序列的 i / n。
|
||||
- 深链目标尚未定位时显示“照片预览 / Photo preview”,不伪造位置。
|
||||
- 本轮默认不为装饰计数新增昂贵 COUNT 查询;采用上述真实回退即可。
|
||||
|
||||
### 5.3 切换、缩放与缩略图条
|
||||
|
||||
- 保留现有 usePhotoSequence 单一数据源,大图与瀑布流不能分别拉取两份顺序。
|
||||
- 手势/按钮/键盘左右切换共享一个入口;页尾沿用 loadMore 和错误重试。
|
||||
- 双指缩放和单指平移复用 viewer/zoom.ts;放大状态下平移不能误触切图。
|
||||
- 不同时绑定 touch/click 导致同一操作执行两次。
|
||||
- 缩略图条为本轮新增:显示当前附近最多 7 项,手机约可见 5 项;当前项蓝色 2px 描边,缩略图宽约 56–64px、高约 44–52px。
|
||||
- 点缩略图切换当前 photoId,不新增浏览器历史;不为了填满条带加载整个相册。
|
||||
- 切换后让选中缩略图进入可见范围,遵守减少动画。
|
||||
- Escape 关闭,左右键在表单/菜单等焦点内不抢占;模态焦点限制、aria-modal 和背景不可交互均需实现。
|
||||
- 保留现有 push/replace/back 语义与关闭恢复 scrollY;直接深链进入关闭后返回相册,而不是跳到未知外站历史。
|
||||
|
||||
### 5.4 分享与下载
|
||||
|
||||
- 相册分享使用相册路由;照片分享使用当前 photoId 的深链,附正确语言参数,不分享 OSS URL。
|
||||
- 优先 navigator.share;不支持时复制链接;复制失败展示可选中文本。用户取消原生分享不显示错误。
|
||||
- 底部 Share 必须真实工作,不能借 Download 按钮冒充分享。
|
||||
- 下载复用 useDownload 权限与失败文案;下载关闭时移除动作并合理分配剩余栏宽,不能保留可绕过的直链。
|
||||
- 原图仅在 canDownloadOriginal 允许时提供二级选项,默认浏览图;保留微信等环境提示。
|
||||
- 下载中防重复请求,但不影响点赞/切图。异步回调绑定触发时的 photoId,切图后不显示错误归属错乱。
|
||||
- 分享/下载反馈用轻提示,不每次弹阻塞式对话框。
|
||||
|
||||
## 6. 点赞和气泡:外观升级,不改变真实统计
|
||||
|
||||
### 6.1 点赞按钮
|
||||
|
||||
- 首页每张照片和大图均可连续点击;按钮颜色不表达“已经赞过不能再赞”。
|
||||
- 大图显示 coral 心形、累计数、Like/点赞;提示“Tap to send more love / 连续点击,为照片点赞”。
|
||||
- 每次有效点击立即有本地轻量视觉反馈;统计发送、批次合并、失败校准沿用 useLikes。
|
||||
- 不因为动画节流丢弃业务点赞;反之也不因动画补帧额外发送点赞。
|
||||
- 同一批次被 WebSocket 回传时不重复累计、不再次制造“他人点赞”气泡。
|
||||
- 服务端限速和网络错误使用现有错误语义,不能永远显示虚假成功值。
|
||||
|
||||
### 6.2 两类反馈分开
|
||||
|
||||
1. **装饰心形粒子**:当前照片本地点赞或该照片其他观众点赞时,在舞台右侧上浮;pointer-events:none、aria-hidden=true。
|
||||
2. **相册内其他照片互动提示**:保留现有可识别照片缩略图、心形、+delta 的紧凑提示及点击定位能力。不能把别的照片点赞数加到当前照片。
|
||||
|
||||
首页可在照片区右侧显示装饰粒子,其他照片提示位于不遮挡筛选/按钮的位置。大图打开时使用独立定位容器:当前照片心形靠右,其他照片提示放底部操作栏上方的安全区域。避免页面级气泡被模态框盖住或遮住下载。
|
||||
|
||||
### 6.3 动效与负载
|
||||
|
||||
- 粒子约 18–30px,2–3 条轻微漂移轨迹,持续约 1.2–1.8s。
|
||||
- 每个界面同时最多 12 个装饰粒子、最多 3 条互动提示;广播批次可合并呈现,不一赞一个 DOM 无限增长。
|
||||
- 数值依然按真实 delta 更新,视觉采样不改变统计。
|
||||
- 页面隐藏、离开相册、关闭上下文时清理计时器和过期粒子;恢复后不回放大量历史动画。
|
||||
- 减少动画开启时不漂浮、不心跳;计数正常更新,必要时保留静态汇总提示。
|
||||
- 取消逐个气泡 aria-live 播报;交互通知使用节流汇总,避免读屏被持续打断。
|
||||
- 不新增第二个 WebSocket 连接,不把所有点赞气泡绑定到当前图片 ID。
|
||||
|
||||
## 7. 数据状态、国际化与隔离
|
||||
|
||||
| 状态 | 页面要求 |
|
||||
|---|---|
|
||||
| 活动加载中 | 基本布局骨架,不显示假标题和数字 |
|
||||
| 活动不可公开/不存在 | 本地化不可访问页,不继续显示缓存内容 |
|
||||
| 图片为空 | Photos coming soon/照片即将上线,不出现上传按钮 |
|
||||
| 初次网络失败 | 清晰重试 |
|
||||
| 加载更多失败 | 保留已有照片,底部重试 |
|
||||
| 图片 URL 失效 | 沿用受控刷新,重试失败显示图片占位 |
|
||||
| 图片隐藏/删除 | 从序列移除;大图回退邻居或关闭,并提示 |
|
||||
| 深链不存在 | 提示并提供返回相册 |
|
||||
| WS 断线 | 沿用轮询降级,不把“无实时连接”说成“没有新照片” |
|
||||
| 分享/下载失败 | 对应操作区域反馈,不清空整个页面 |
|
||||
|
||||
- 英文参考图必须同时落地 zh-CN;保持用户语言选择和服务端内容回退分离。
|
||||
- 不因内容回退为中文就自动把用户 UI 改回中文。
|
||||
- 保留 html lang、文档标题、日期和数字本地化。
|
||||
- 大图切图、缩略图、新照片刷新不能重新计作一次相册浏览。
|
||||
- 普通相册样式放在 .viewer-shell/.album-page/.photo-viewer 等作用域;不要用全局 button/img 样式改变 EmbedPage。
|
||||
- 首页亮色、大图暗色是两个固定场景,不要求本轮新增整站暗色设置。
|
||||
- 没有 SSR/SEO 改造任务,不为了分享按钮扩大到搜索引擎架构重写。
|
||||
|
||||
## 8. 实施任务(按顺序勾选)
|
||||
|
||||
### V00 基线与保护
|
||||
- [ ] 检查 Git 状态,记录已有 UI-01 与其他用户改动,避免覆盖。
|
||||
- [ ] 阅读实际 ActivityPage、PhotoFeed、PhotoLightbox、useLikes、useAlbumRealtime 和原测试。
|
||||
- [ ] 运行本地 viewer,截取当前首页和大图,中英文各一;记录无法运行的具体原因。
|
||||
- [ ] 创建验收记录 docs/plans/progress/UI02-验收记录.md。
|
||||
出口:明确基线和环境,不能拿本效果图当运行截图。
|
||||
|
||||
### V01 视觉基础和顶栏
|
||||
- [ ] 新增有作用域的视觉 token,调整 App.vue 普通布局与 LocaleSwitcher。
|
||||
- [ ] 品牌、语言、减少动画入口符合第 3 节。
|
||||
- [ ] 检查 embed 路由仍是无顶栏/无外边距的独立外壳。
|
||||
出口:手机边到边,桌面居中,嵌入组件不变。
|
||||
|
||||
### V02 活动信息与筛选
|
||||
- [ ] 实现宣传图、信息层级、真实浏览数、分享入口。
|
||||
- [ ] 完成日期地点换行、长文案、缺图缺字段。
|
||||
- [ ] 重排排序、分类,保留原筛选/快照逻辑。
|
||||
出口:真实数据可以呈现参考图的上半屏。
|
||||
|
||||
### V03 瀑布流
|
||||
- [ ] 改布局参数、图片角标、独立点赞按钮、新图提示。
|
||||
- [ ] 验证加载/空/失败/分页和宽高占位。
|
||||
- [ ] 适配 2/3/4 列,维持图片身份、DOM 顺序与键盘访问合理。
|
||||
出口:真实不同宽高图片形成瀑布流,无等高假效果。
|
||||
|
||||
### V04 深色大图
|
||||
- [ ] 重构大图模板层级,保留现有缩放、导航、路由编排。
|
||||
- [ ] 新增缩略图条、底部操作栏、真实位置回退。
|
||||
- [ ] 实现安全区、短屏、横屏、焦点与关闭回位。
|
||||
出口:点击和深链均可进入设计图右侧效果,交互完整。
|
||||
|
||||
### V05 分享、下载与互动
|
||||
- [ ] 完成相册/单图分享和复制回退。
|
||||
- [ ] 接入原下载控制器和原图二级菜单。
|
||||
- [ ] 重做心形动画与跨照片互动提示,校验自身回声去重。
|
||||
- [ ] 减少动画、快速点赞、断网限速和多观众场景可用。
|
||||
出口:按钮有真实行为,数值与气泡不串照片。
|
||||
|
||||
### V06 状态和双语
|
||||
- [ ] 补齐所有新中英文词条及无障碍标签。
|
||||
- [ ] 完成第 7 节状态矩阵,不留开发 ID/内部状态裸露。
|
||||
- [ ] 验证相册切换、语言切换、签名刷新请求竞态。
|
||||
出口:非理想网络和长文案下也可用。
|
||||
|
||||
### V07 测试、截图与交付
|
||||
- [ ] 完成第 9 节验收与回归。
|
||||
- [ ] 保存优化后的真实页面截图及与设计图的差异说明。
|
||||
- [ ] 更新 UI02 验收记录;必要时总纲登记独立 UI-02,不覆盖 UI-01 进度。
|
||||
- [ ] 列出已完成、剩余资源关口、实际命令结果,不自动部署。
|
||||
出口:实现、测试、截图、交接说明完整。
|
||||
|
||||
## 9. 验收标准
|
||||
|
||||
### 9.1 视觉截图清单
|
||||
|
||||
固定本地/测试活动数据:横图、竖图、全景、文字海报、无封面、长英文标题。不得写进生产默认内容。截图关闭随机装饰动画;气泡效果另用可控事件截图验证。
|
||||
|
||||
- 手机 390×844:首页、大图各 zh-CN/en。
|
||||
- 320×568:首页与大图,检查按钮和横向溢出。
|
||||
- 430×932:长文案与分类。
|
||||
- 844×390 横屏:大图缩放与操作栏。
|
||||
- 桌面 1440×900:首页、大图。
|
||||
- 字体放大/浏览器 200%:主要操作可达。
|
||||
- 减少动画、禁用下载、空相册、加载失败各一组代表状态。
|
||||
- EmbedPage 回归截图一张,证明不受全局样式污染。
|
||||
|
||||
截图路径建议 `docs/designs/ui02-implementation/`;仅保存项目测试图片,避免真实私密活动照片进入仓库。
|
||||
|
||||
### 9.2 验收矩阵
|
||||
|
||||
| 编号 | 标准 |
|
||||
|---|---|
|
||||
| V-A01 | 首页层级与设计图一致,没有手机外壳、假活动内容或底部 App 导航 |
|
||||
| V-A02 | 双列真实瀑布流、响应式列数、首屏无明显图片布局跳动 |
|
||||
| V-A03 | 宣传图缺失/失败、长标题、日期地点均可用 |
|
||||
| V-A04 | 浏览数是服务端数据,分页/点赞/切图不重复计访问 |
|
||||
| V-A05 | 分类、最新/热门和新图提示沿用正确数据语义 |
|
||||
| V-A06 | 大图完整显示、左右切换、缩放、分页和缩略图正常 |
|
||||
| V-A07 | 深链直达、浏览器后退、关闭回位和照片移除正确 |
|
||||
| V-A08 | 分享当前相册/单图,语言保留,复制失败有回退 |
|
||||
| V-A09 | 下载开关、原图开关、过期/关闭后的失败反馈正确 |
|
||||
| V-A10 | 连续点赞真实累计,自己回声不重复;多观众可看到互动 |
|
||||
| V-A11 | 其他照片点赞不污染当前数值,气泡不遮挡动作且数量有上限 |
|
||||
| V-A12 | 减少动画生效、键盘焦点可见、模态焦点不穿透 |
|
||||
| V-A13 | 位置与新图数量不伪造,深链 solo 不假称全局排名 |
|
||||
| V-A14 | 中英文、窄屏、横屏、安全区和字体放大通过 |
|
||||
| V-A15 | embed 页面和现有上传/管理业务未被改动或样式破坏 |
|
||||
|
||||
### 9.3 测试重点和执行命令
|
||||
|
||||
先定向执行相关测试,再跑 viewer 全部检查;需要测试服务时使用隔离环境,不对真实数据执行 reset/seed。
|
||||
|
||||
```text
|
||||
pnpm --filter @photo/viewer lint
|
||||
pnpm --filter @photo/viewer typecheck
|
||||
pnpm --filter @photo/viewer test
|
||||
pnpm --filter @photo/viewer build
|
||||
pnpm --filter @photo/viewer test:e2e
|
||||
```
|
||||
|
||||
- 保留/扩展 activity、feed-layout、feed、lightbox、zoom、viewer-route、likes、visit-report、i18n、download 等既有测试。
|
||||
- 新增缩略图导航、位置回退、分享取消/复制失败、隐藏后退邻居、非当前气泡归属测试。
|
||||
- E2E 用两个独立浏览器上下文验证其他观众点赞与自己批次过滤。
|
||||
- 不只断言文案存在;检查关键区域尺寸、无横向溢出、操作可点击与页面截图。
|
||||
- 视觉截图使用稳定 fixture 和受控时间;真实服务冒烟另外运行,不能以 mock 全绿代替业务链路。
|
||||
- API/契约原则上无需变动。如果实现发现必须扩展,先记录缺口,采用兼容变更并补权限/服务端回归,不能伪造前端字段。
|
||||
- 不承诺固定性能提升;记录首屏资源请求、大图预加载数和长列表滚动观察,避免一次预加载所有 browse 图。
|
||||
- 若浏览器/设备不可用,记录未执行原因与影响,不把静态编译成功当视觉验收通过。
|
||||
|
||||
## 10. 验收记录内容
|
||||
|
||||
在 `docs/plans/progress/UI02-验收记录.md` 写入:
|
||||
|
||||
1. 基线 commit、日期、环境、已有工作树变更。
|
||||
2. V00–V07 完成情况与实际修改文件。
|
||||
3. V-A01–V-A15 的通过/失败/待验证与证据。
|
||||
4. 截图索引,与效果图差异及理由。
|
||||
5. 实际测试命令、退出结果和未执行项。
|
||||
6. 数据口径、权限、路由、下载和气泡回归结果。
|
||||
7. 对 UI-01/EmbedPage 的隔离情况及剩余问题。
|
||||
|
||||
允许的视觉差异:真实图片比例、真实文案长度、下载权限隐藏、真实计数回退及响应式布局。不能用这些理由省略缩略图、分享、双语或把现有能力做坏。
|
||||
|
||||
## 11. 可直接复制给 Claude 的执行指令
|
||||
|
||||
> 请执行 `docs/plans/2026-09-21-UI02-观众页效果图落地实施方案.md`,先打开 `docs/designs/viewer-mobile-concept-2026-09-21.png` 查看目标效果,再核对当前 viewer 代码,按 V00–V07 完成真实页面调整。重点交付蓝白活动首页、真实瀑布流、深色大图、缩略图导航、连续点赞气泡、分享和权限下载。沿用既有海外 API、序列、路由、浏览去重、点赞批次和实时机制,不写死样例数字,不把已加载数量冒充总数,不影响 UI-01 的 App 与嵌入组件。保护已有未提交改动,按文档默认样式自主实现,不只返回计划。完成后提交可核查的运行截图、测试结果和 UI02 验收记录;资源不足的项目明确标注待验证。未经另行授权不发布、不推送、不操作真实云资源。
|
||||
|
||||
Reference in New Issue
Block a user