PersonalWebApplication/docs/photo-wall.md
cc d240c128dc feat(photo-wall): client-only photo wall behind #photo login entry
已部署到线上(frontend-only)。本提交把工作区里已上线但未提交的实现固化为分支基线。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 20:55:03 +08:00

66 lines
3.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 照片墙 Photo Wall`#photo` 入口)
模拟软木板/墙面的互动照片展示页:上传本地照片,以宝丽来风格散落摆放,用胶带、
图钉、便签、贴纸、印章、手绘箭头自由装扮,可导出为一张 PNG。**纯前端**(无后端改动),
状态存浏览器 `localStorage`
设计来源:`photo-wall-design.docx`(产品设计文档 v1.0)。本页是其 React 重写版。
## 入口与鉴权流
地址栏 `#photo` 是一个**写死的公开入口**,与开发者入口门(`dev_gate`**无关**
```
浏览器 #photo
└─ 直接显示登录页(复用 LoginPage但去掉顶部服务器负载栏 ← 不查后端 gate
登录页提交用户名 + 密码
└─ POST /api/web/login → 校验同一套 ccuser 账号 → 成功后进入照片墙
```
- `#photo` **不走** `POST /api/web/gate`(藏门口令),但照片墙本身仍被登录挡住——
用的是同一套 `ccuser` 后端账号(见 [auth-login-gate.md](auth-login-gate.md))。
- **已登录**用户访问 `#photo` 会跳过登录页,直接进墙。
- 墙内右上角「退出」= 清登录态 + 抹掉地址栏 `#photo`,回到导航页(`StartPage`)。
## 涉及文件(全部前端)
- `Client/src/App.tsx` — 监听 `hashchange``#photo` 短路 gate`wantsPhoto`
已登录 + `wantsPhoto` → 渲染 `PhotoWallPage`,否则博客页。
- `Client/src/components/LoginPage.tsx` — 新增 `hideStats` 开关,隐藏顶部
`AnnouncementBar`(系统负载栏);把轮询的 `useSystemStats` 拆进只在显示时挂载的
`StatsBar` 子组件,隐藏时不发请求。
- `Client/src/components/PhotoWallPage.tsx` — 照片墙组件本体。
- `Client/src/index.css` — 末尾 `.pw-` 命名空间的全部照片墙美术样式(软木板/宝丽来/
便签折角/胶带/图钉等,无法用 Tailwind 表达的部分)。
> 后端零改动:登录走既有 `/api/web/login`,照片墙数据只存浏览器,不落服务器。
## 功能
- **照片**:宝丽来白边(底部加大留白)、随机旋转 ±15°、立体投影三种随机固定方式
(胶带 / 彩色图钉 / 双角胶带)。
- **交互**:拖拽移动、双击编辑标注、右键菜单(旋转 ±5°、放大/缩小、移到最前/最后、
删除;便签额外可改色)。触摸端长按 = 右键。
- **装饰**便签5 色 + 折角、胶带条、12 预设贴纸 + 自定义文字、SVG 印章、手绘箭头
(选中后在画布拖动绘制)。
- **背景**:软木板 / 黑板 / 白墙 / 牛皮纸,工具栏循环切换。
- **上传**:按钮选择 / 拖入画布 / 剪贴板粘贴(`FileReader` 读 Base64
- **历史**:撤销/重做 Ctrl+Z / Ctrl+Y最多 30 步。
- **持久化**:操作后防抖 1s 自动写 `localStorage`key `photo-wall-state`
`{ bgIndex, els }`);工具栏显示「保存中…/已保存」。
- **导出**`html2canvas`CDN 懒加载)截图画布为 `photo-wall-<时间戳>.png`
## 实现注记
- **拖拽性能**:拖拽过程中只直接改 DOM 的 `transform`GPU 合成),**不触发 React
重渲染**;松手后才一次性 commit 进状态并记一步历史。故拖拽中不得 `setState`
- 元素统一 Pointer Events 处理鼠标 + 触摸;`touch-action: none` 防止滚动抢手势。
- 「保存中…」由各改动入口mutate / undo / redo / 拖拽 commit / 换背景)打标,
防抖 effect 仅负责落盘并置「已保存」——避免在 effect 内同步 `setState` 引发级联渲染。
## 线上访问
部署后:`http://8.130.143.54:8548/#photo`(纯前端改动,按
[部署计划](superpowers/plans/2026-06-18-deploy.md)的 frontend-only redeploy 路径上线,
后端无需重启)。