325 Commits

Author SHA1 Message Date
浅念 74593d9953 fix(embed): scroll freeze root cause — drag-set 'manual' pause reason never cleared
setReason('manual', true) fired on >8px drag had no clear path anywhere (wheel/keyboard have 500ms timers; pointer path didn't) — one drag left the reason permanently, stopping auto-scroll until refresh. Now cleared on pointerup, watchdog, and window blur.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-23 17:09:17 +08:00
浅念 b414b3666e fix(embed): pointer pause watchdog — capture does not cross iframe boundary, outside-release now auto-resumes in 2s
The earlier capture+window-listener fix is insufficient: releasing outside the 195x280 window dispatches pointerup in the host document, which no in-iframe listener can observe. Deterministic fallback: 2s watchdog on pointerdown force-clears the pause reason (in-frame releases still cancel it immediately).

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-23 17:04:46 +08:00
浅念 2332d24591 docs(g4): clipboard HTTP-context fix record
Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-23 17:04:45 +08:00
浅念 aaea76b0e3 fix(admin): copy buttons dead on HTTP origin — execCommand fallback
navigator.clipboard 仅安全上下文(HTTPS/localhost)可用,测试服务器经
http://IP:32005 访问时为 undefined,四处复制按钮(公开令牌/分享链接/
嵌入代码/重置密码)点击即抛 TypeError 且无提示。统一 utils/clipboard
copyText:API 优先、失败降级隐藏 textarea + execCommand。

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-23 17:01:54 +08:00
浅念 cd8a3696e2 fix(embed): scroll freeze — pointer pause leaked when release happened outside window
Root cause: pointerup/pointercancel bound only on the viewport element; press on a photo then release outside the 195x280 window (or gesture interruption) never cleared the 'pointer' pause reason -> auto-scroll stopped permanently until page refresh.
- pointerdown now setPointerCapture (release guaranteed to return)
- window-level pointerup/pointercancel + blur fallbacks clear the reason
- rAF frame wrapped in try/catch so a single bad frame can no longer break the animation chain

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-23 16:57:04 +08:00
浅念 ae17776be6 feat(app): session restore on startup — no forced re-login after app restart
用户反馈:关闭 App 重开每次都要登录。根因:会话已持久化(安全存储,
服务端 TTL 30 天),但启动固定落在登录页——无人消费已存会话。

- _StartupGate(home):watch sessionAccount——在场直进 HomePage,离场
  LoginPage;状态驱动(401/登出清会话后 gate 自动重建,不依赖导航时序)
- onUnauthorized 保留 push 兜底(home 路由被显式导航替换后的 401 场景)
- 测试适配(boot 401 两项重写通过;397/397 全绿)

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-23 16:48:27 +08:00
浅念 b6daa6fa0e docs(embed): live title+modal verification — '2026届-广交会' overlay, coordinate click opens in-host detail modal with deep link, closes via button
Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-23 16:47:27 +08:00
浅念 a5dcfffd37 docs(embed): refreshed evidence artifacts (modal screenshot, screenshots/recordings regenerated)
Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-23 16:37:17 +08:00
浅念 da6f1b282e feat(embed): in-host photo detail modal + title overlay — e2e adapted (no popup, close button, some() heart attribution with ambient bubbles)
Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-23 16:36:51 +08:00
浅念 985829fee8 fix(app): poster title truly left-aligned — Column crossAxisAlignment start (QR re-centered)
Text 的 textAlign 被 Column 默认 center 吞掉(文本行收缩包裹时对齐不生效);
文字区 Column 改 CrossAxisAlignment.start,二维码+扫码说明显式 Center 回居中。

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-23 16:30:14 +08:00
浅念 a16fa738f6 fix(app): poster — date-only text, left-aligned title/time/venue (QR stays centered)
用户反馈:海报日期仍带时间(表单已日期粒度,海报 formatAlbumDateTime 同步改
posterDate 只显 y/M/d);宣传图下标题/时间/地址居左;二维码保持居中。

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-23 16:26:32 +08:00
浅念 8834b1bbb9 feat(embed): album title overlay + in-host photo detail modal (replaces new-tab open)
- viewer: EmbedStream shows album title overlay top-left (ellipsis, avoids collapse zone); photo click posts open-photo {url} to host instead of window.open (direct-open still new tab)
- loader v2: open-photo message (origin+source whitelisted, URL must match widget origin) opens host overlay modal with embedded viewer deep-link iframe, close button/Esc/scrim dismiss, single instance, cleaned on destroy
- tests: click case asserts modal iframe deep link + no popup + close button dismiss; viewer 244 + loader 36 green

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-23 16:20:10 +08:00
浅念 5a207b395e feat(app,viewer): WeChat card share + 'Share to...' label + site og tags
- 按钮文字「分享到微信/其他应用」→「分享到...」(用户需求)
- 微信卡片分享(fluwx 6):WECHAT_APPID 经 --dart-define 注入;已配置且
  装微信 → WXWebpage 卡片(标题=相册名、描述=日期·地点、缩略图=封面压缩
  240px PNG ≤32KB、点击进观众链接);未配置/未装 → 回退系统分享面板
- viewer index.html 加站点级 og 标签(微信/QQ 抓取链接预览用;每相册动态
  og 需服务端注入,登记后续增强)
- 397/397 全绿、analyze 0

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-23 16:05:53 +08:00
浅念 77b1519209 docs(viewer): like-hidden live verification — feed badges/sort tabs gone, lightbox bar is share+download only
Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-23 14:31:21 +08:00
浅念 2babd364ba feat(viewer): hide like feature — action bar like slot, photo like badges, hot sort tab, others' like bubbles (user request 2026-09-23)
- PhotoFeed: cell like badge not rendered
- AlbumHeader: sort tabs row removed (hot depends on likes; latest-only has no toggle value)
- PhotoActionBar: like slot v-if=false (share/download remain, auto re-center)
- ActivityPage: LikeBubbles hidden
- specs updated to hidden assertions; 244 green

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-23 14:29:22 +08:00
浅念 e44b35db28 feat(albums): date-only pickers for start/end (create & edit, admin + app)
- 管理后台:DatePicker type=datetime → date;提交归一(开始=当天 00:00、
  结束=当天 23:59 整天活动语义;契约仍 datetime 仅交互粒度)
- App:去掉时间选择步骤(选日期即定;同上归一);表单显示只显 yyyy/M/d
- e2e 日期填入改 '2026-10-01'(date 格式);widget 断言日期粒度
- admin 87/87 + build、app 397/397 全绿

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-23 14:13:58 +08:00
浅念 f984535c2a fix(deploy): absolute_redirect off — root redirect keeps host:port through reverse proxy
nginx 默认 absolute_redirect on:return 302 被绝对化为 scheme://Host/(经
OpenResty 反代 Host 无端口 → 32005/ 跳到无端口的 /admin/ 打不开)。
off 后发相对 Location,浏览器按当前 host:port 补全。

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-23 13:55:46 +08:00
浅念 7ef27797ff fix(deploy): root path redirect to admin (cn) — persisted in template+compose
用户约定:32005 根路径打开即管理后台。之前是直接改在服务器容器配置上的,
历次镜像重建被冲掉——本次固化进仓库:nginx 模板 location = / → 302
${ROOT_REDIRECT};Dockerfile 默认 /admin/;compose 按栈注入(cn=/admin/,
ov=/index.html 观众端安全自指,不影响 /a/<token> 与嵌入路径)。

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-23 13:52:29 +08:00
浅念 d7ac9420be docs(viewer): lightbox close button restored on server (transparent bg, white X, 44px circle)
Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-23 13:51:59 +08:00
浅念 85146be7ef fix(viewer): restore lightbox close button styles orphaned by menu removal (transparent bg, white X icon, hover/focus)
Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-23 13:48:03 +08:00
浅念 f2cd26e523 docs: register embed-slot soft-delete acceptance
Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-23 13:41:27 +08:00
浅念 bdad433dae fix(viewer): remove lightbox top-bar settings menu (user request) — close button + counter only; Esc closes directly
Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-23 13:39:53 +08:00
浅念 903962a46b feat(embed-slots): soft-delete slots — admin entry, ov shutdown via enabled=false snapshot
- 契约 deleteEmbedSlot(DELETE /admin/embed-slots/{id} → 204 幂等;admin 专属)
- cn schema:embed_slots.deletedAt(迁移 20260923120000,本地已应用)
- softDelete:乐观锁 claim + outbox slot.updated(payload enabled 强制 false
  ——ov 副本无墓碑,enabled=false 快照即公开端 404 下线;priority=high)+ audit
- 列表/加载/更新过滤 deletedAt → 同码 404
- Admin 列表操作「删除」(确认:已接入网站将停止展示、不可恢复)
- API 56/56、admin 87/87 + build 全绿

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-23 13:37:39 +08:00
浅念 aa366c4268 docs(embed): ambient hearts restored on server (7 on screen) after parallel-session image rollback
Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-23 13:35:23 +08:00
浅念 20321f1b93 fix(app): account-switch data residue + empty-albums pull-to-refresh
- 换账号数据残留(用户报告):albumListProvider 非 autoDispose 且首页
  IndexedStack 常驻——登出与登录成功两处显式 invalidate(任务库本就按账号
  隔离键隔离,不受影响)
- 空相册无法下拉刷新(用户报告):空态原本直接 return EmptyState 无
  RefreshIndicator——被拉进相册后无法手动刷新;空态改入可滚动容器承载
  下拉刷新(保留新建入口)
- 397/397 全绿、analyze 0

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-23 12:05:25 +08:00
浅念 c1869d7314 feat(admin): photo upload in album photos tab (same staging pipeline as app)
- 照片页签工具栏加「上传照片」(多选 jpeg/png/heic)→ /v1/uploads
  init → PUT staging → complete(clientTaskId 幂等;categoryId 随当前分类筛选)
- 逐张结果:部分成功语义(成功 N 张 toast + 失败明细前 3 条);完成后 reload
- 类型 UploadInitPayload/UploadSession/UploadCompleteResponse + api/uploads.ts
- 问题1 修复说明:详情页 404 系并行部署把 2618ad3 server 覆盖回 8e674a9,
  已重滚双栈至 ui06-2618ad3(assets 端点恢复 200,详情页零失败请求)

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-23 11:54:26 +08:00
浅念 7adc1b0858 docs(embed): denser/lower ambient hearts verification (6 on screen, origin band 140-244px)
Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-23 11:41:11 +08:00
浅念 f667842e9c style(embed): ambient hearts denser and lower (user feedback — spawn 160-320ms, band 140-244px)
Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-23 11:38:55 +08:00
浅念 c8a9727993 docs(embed): ambient hearts live verification — bubbles float with zero likes (steady ~3 on screen)
Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-23 11:33:25 +08:00
浅念 4d31eaf184 fix(app): poster sheet close button — header row with explicit close (drag-down not obvious on long sheet)
Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-23 11:32:02 +08:00
浅念 d11ca16d1d feat(embed): ambient heart bubbles — always floating in the right band (user request 2026-09-23)
- ReactionLayer ambient prop: self-scheduled spawn every 400-800ms (jitter), band 56-232px avoiding the 44px action zone, stops on hidden page/unmount, shares MAX_ACTIVE=8 with real bursts
- EmbedStream mounts layer with ambient = reactions && !reducedMotion — persistent decoration independent of real likes (no burst frames, no count inflation; §5.2 anti-fake semantics unaffected)
- viewer 244 green

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-23 11:30:53 +08:00
浅念 df0c318599 feat(app): share redesign — card share (system), QR poster (banner+title+time+venue+QR, downloadable), copy link
- 三方式(用户需求):①卡片模式默认=系统分享面板(share_plus SharePlus.
  instance,微信/其他应用,文本=标题+链接)②生成二维码=海报弹层——顶部
  宣传图(banner→cover→品牌占位回退)+ 活动标题 + 时间 + 地址 + 二维码,
  「下载海报图」RepaintBoundary 3x 渲染 PNG → gal 存相册 ③复制链接
- 依赖 share_plus + gal;分享/保存均 Provider 注入(测试替身)
- 测试适配三方式结构 + 海报弹层断言(397/397 全绿、analyze 0)

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-23 11:27:32 +08:00
浅念 8768a04a75 docs(embed): collapsed handle right-dock verification on server (right=16px, x=1324 @ 1440 viewport)
Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-23 11:26:56 +08:00
浅念 9761eea591 fix(embed): collapsed handle positioned correctly on first creation (v2 parity with v1 applyWrapperBox call)
Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-23 11:24:47 +08:00
浅念 257643934a docs(viewer): share sheet live verification — album header & photo lightbox entries, QR 188px, on-button copy feedback, Esc close
Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-23 11:15:55 +08:00
浅念 c2143e1f94 feat(app): album banner picker in edit form — show current banner, pick & upload on save
- api_client:uploadAlbumAssetFromFile 泛化(cover 为薄壳)+ fetchAlbumAssetUrl
  (GET /albums/{id}/assets → 指定 kind 全局行 URL)
- 编辑页 Details:封面下方新增「宣传图」3:1 选择器——编辑模式异步加载现有
  banner 预览(失败静默);保存成功后上传(同封面:失败不阻塞表单结果)
- 未保存变更判断纳入 banner;l10n zh/en
- 测试适配:编辑用例 pumpForm 后清空 banner 现状预检请求(397/397 全绿)

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-23 11:07:54 +08:00
浅念 3d45350711 feat(viewer): share sheet with QR code + link + copy (replaces inline toast, App-style)
- ShareSheet.vue: bottom sheet (mobile) / centered card (desktop) — QR canvas (qrcode dep), selectable deep link, copy with on-button feedback (2.5s), optional navigator.share button, Esc/scrim/close dismiss, focus on open
- AlbumHeader + PhotoLightbox: share buttons open the sheet (album URL / photo deep link); page-level copied strips removed
- tests rewritten for sheet behavior — viewer 244 green

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-23 11:04:11 +08:00
浅念 e3f40c696d docs(ui06): dedupe task table rows
Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-23 10:56:33 +08:00
浅念 63b3e539fd docs: register asset status acceptance — admin branding tab shows current banner/cover/logo
Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-23 10:56:14 +08:00
浅念 2618ad3163 feat(assets): album asset status — show current banner/cover/logo in admin branding tab
- 契约 listAlbumAssetStatus(GET /albums/{albumId}/assets):每 (kind,locale)
  最新 effective 行 + 现签 URL;权限同详情(可见即读);deleted → 404
- 服务端 AssetsService.status(createdAt,id DESC 组内取首;presignGet 现签)
- Admin 品牌资产页签改造:进入即加载现状——三种 kind 卡片(预览图/未设置
  空态/设置时间),banner 分全局/zh/en 槽位;上传成功自动刷新(替换语义)
- API 56/56、admin 87/87 + build 全绿

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-23 10:51:53 +08:00
浅念 d678c8d38d style(viewer): banner-wrap drops fixed aspect-ratio and placeholder bg (user edit)
Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-23 10:42:03 +08:00
浅念 3cd9dafd1b docs(viewer): server verification — topbar locale-only (settings menu removed)
Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-23 10:40:28 +08:00
浅念 fd35c712a5 fix(viewer): remove topbar settings menu, keep locale switcher only (user request)
Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-23 10:38:23 +08:00
浅念 2409beb7c2 docs: register album soft-delete acceptance — full-chain verified on test server
Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-23 10:20:57 +08:00
浅念 2b2ae7a083 docs: banner/cover fallback live verification — cover-only album renders banner atop viewer (server 8e674a9 images, migration applied)
Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-23 10:19:36 +08:00
浅念 8e674a902e feat(albums): soft-delete albums (admin+owner, hidden & irreversible, both app entries)
契约 deleteAlbum(DELETE /albums/{albumId} → 204 幂等)+ status enum 'deleted':
- 服务端:softDelete(canView 404→canManage 403 防枚举;乐观锁 claim +
  outbox album.updated priority=high + audit album.delete);列表/详情/更新/
  成员/资产/分类/水印/照片/展示位绑定全部 deleted→404;公开端 cn
  (status!=='active')与 ov(isAlbumVisibleOv)天然屏蔽;ov 副本经
  album.updated 载荷 status 直投自动下线
- Admin:列表表格操作「删除」+ 详情页头「删除相册」(确认含不可恢复说明)
- App:操作面板「删除相册」(红字、二次确认、成功退回列表并刷新)
- 验证:API 56/56、App 397/397(analyze 0)、admin typecheck/lint/test/build 绿

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-23 10:13:08 +08:00
浅念 9cb960c27a docs(viewer): banner live verification — uploaded via admin asset API, renders atop album page
Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-23 09:41:51 +08:00
浅念 c481aeeeb7 docs(viewer): server verification screenshot — tap-more hint removed on live lightbox
Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-23 09:35:25 +08:00
浅念 aa78855657 fix(viewer): remove tap-more like hint from photo action bar (user request)
Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-23 09:31:26 +08:00
浅念 452cdf496c style(ui06): full-width pages — hand padding back to Art/ElMain container (user adjustment)
用户将全局 .ui06-page 的 30px 边距/1660 限宽注释(内容铺满,边距交还
ElMain 默认 20px);manage 页 scoped 同名类同步、清理媒体查询死引用。

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-23 09:26:16 +08:00