UI-UX/CHANGELOG.md
iye 5c009f38cd
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 4m48s
fix(vote): 投票后立即 refresh ranking,不等 30s 轮询
- useVoteAction 加 onVoteSuccess 回调,服务端 200 立即触发
- page.tsx + ranking/page.tsx 传 live.refresh
- 顺手把 fire-and-forget 改成 await + 失败回滚 + /api/me 跨设备对齐
- store 新增 rollbackVote + hydrateFromServer 两个 action

体感:本地 30s → 700ms,生产 30s → 150ms

bump to v0.3.3

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-18 14:25:40 +08:00

207 lines
9.5 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.

# CHANGELOG
CYBER STAR(虚拟明星 Top 12 出道选拔)更新日志。新条目写在最上面,旧条目往下沉。
## 版本号规则(SemVer · 0.x 开发期)
- `0.X.0` → 重要功能、破坏性变更(如投票模型重构)
- `0.x.Y` → 修补、内容更新、UI 打磨
- `1.0.0` → 正式上线 / 第一次面向公众活动
每次发版必须三件套同步:
1. `package.json` 里的 `version` 字段
2. 本文件加新条目(顶部)
3. `git tag v<x.y.z>`(可选 push 到远程,触发 CI release 流程)
每个版本下方都写两块 commit 信息:
- **Tag**: tag 实际打在哪条 commit(可点击直达 Gitea)
- **核心 commit**: 该版本最重要的功能/改动 commit hash
- **完整 diff**: 与上一个版本的 compare 链接
---
## v0.3.3 · 2026-05-15 · 修复:投票后票数 +1 和 Top12 排位要等 30s
**Commit 信息**
- 完整 diff: [v0.3.2...v0.3.3](https://gitea.airlabs.art/zyc/UI-UX/compare/v0.3.2...v0.3.3)
**改了什么**
- 投票成功后,首页 Top12 + 排行榜立即拉新数据,不必等下次 30s 轮询
- 服务端拒绝投票时(如其他设备已投过),本地立即回滚乐观更新 + 用 /api/me 重新对齐
- 网络异常时回滚 + 报错,避免本地状态与服务端不一致
**根因(诊断详见 v0.3.2 后的对话)**
- `useRanking` 30s 轮询拉服务端票数,merge 时取 max(serverVotes, storeVotes)
- 用户投票后,storeVotes 立即 +1,但 serverVotes 还是 30s 前的旧值,且更大
- max 永远取 server → 本地 +1 被压住 → 票数和排位最多延迟 30s 才更新
**技术修复**
- `useVoteAction``onVoteSuccess` 回调,服务端 200 后立即触发
- `page.tsx` + `ranking/page.tsx``live.refresh` 传进去
- 顺手把 fire-and-forget 改成 await 服务端,失败时 `rollbackVote` + `refetchMe(/api/me)` 跨设备对齐
- store 新增 `rollbackVote(id)` + `hydrateFromServer(ids[])` 两个 action
**体感对比**
| 场景 | 本地 dev(打公网 RDS) | 生产(同区 K3s + RDS) |
|------|---------------------|---------------------|
| 改前 | 0~30 秒后才看到票数 +1 | 同上 |
| 改后 | ~700-1000 ms(vote API 写完 + ranking refresh) | ~150 ms |
**风险 / 已知问题**
- ArtistDetailContent 显示的 artist.votes 仍从 store 来,store 里这个字段是"本地用户投过几次"不是服务端真实票。详情页票数显示问题留下次单独修。
---
## v0.3.2 · 2026-05-15 · 修复:首页 Top12 出道位空着,排行榜却有数据
**Commit 信息**
- 完整 diff: [v0.3.1...v0.3.2](https://gitea.airlabs.art/zyc/UI-UX/compare/v0.3.1...v0.3.2)
**改了什么**
- 首页 Top12 出道位现在能显示真实票数(此前一直显示"Awaiting Votes")
**根因**
- 首页 Top12Bar 之前只读前端 zustand store 的 `artists`,store 初始来自 mock-data(36 人全部 0 票),只有**当前浏览器用户自己投票时**才会更新
- 排行榜 `/ranking``/api/ranking` 直接读 DB,所以有真实票数
- 未登录访客访问首页 → store 全 0 票 → `top12 = filter(votes > 0)` 空 → 显示"Awaiting Votes"
**技术修复**
- `src/app/page.tsx``useRanking({ pollInterval: 30_000 })`,30 秒轮询 `/api/ranking`
-`useMemo` 合并 `storeArtists`(本地乐观投票)+ API 票数(取 max),重新排序赋 rank
-`/ranking` 页面用同样的 merge 策略,保证两处票数视图一致
**风险 / 已知问题**
- 首页和排行榜各自跑一个 `useRanking` 实例,会产生两个独立轮询请求。后续可以提到 layout 层共享,但当前 36 行查询很轻,先这样
---
## v0.3.1 · 2026-05-15 · 13 号(虞浓)氛围图 2 替换
**Commit 信息**
- Tag 打在: 本次 release commit(`git log -1` 看)
- 完整 diff: [v0.3.0...v0.3.1](https://gitea.airlabs.art/zyc/UI-UX/compare/v0.3.0...v0.3.1)
**改了什么**
- 13 号虞浓的氛围图 2 换成新版本(`portraits/013-2.webp`,1440×2560,153KB)
**技术点**
- TOS cache version `7``8`(`src/lib/tos.ts`),浏览器 + CDN 立即拿到新图,不必等 TTL
- 转换脚本 `_tmp_webp_convert/round3.mjs`,sharp quality 82
---
## v0.3.0 · 2026-05-15 · 投票模型大改:每日额度 → 终身 12 票
**Commit 信息**
- Tag 打在: [`93c3abe`](https://gitea.airlabs.art/zyc/UI-UX/commit/93c3abe) `chore(release): v0.3.0 + 建立 CHANGELOG + 追溯版本号`
- 核心 commit: [`10878dd`](https://gitea.airlabs.art/zyc/UI-UX/commit/10878dd) `feat(vote): 重构投票模型为终身 12 票 + 每艺人 1 票`
- 完整 diff: [v0.2.2...v0.3.0](https://gitea.airlabs.art/zyc/UI-UX/compare/v0.2.2...v0.3.0)
**改了什么**
- 每个用户改为终身 12 票,每位艺人最多 1 票,投出不可撤销
- 取消活动时间窗(不再限定结束日期)
- Hero 右上角倒计时换成 "应援进度" 12 格点亮式条
- 已投艺人卡片显示 ✓ 角标 + "已投票" 灰色按钮
- /me 页改为终身额度叙事(QuotaCard / StatsGrid / MyFanSupport)
- VoteModal 去掉 1/3/5/ALL 选择器,改"投出我的一票"单一确认
**技术点**
- `votes` 表加 `@@unique([userId, artistId])` 硬约束(已 apply 到生产 RDS)
- `/api/vote` 重写:12 票上限校验 + P2002 转 ALREADY_VOTED + P2003 转 NOT_FOUND
- `/api/me` 新增 `votedArtists[]` + `voteQuota`,替换旧 `dailyQuota`
- 前端 store 改为 zustand `persist` + `votedArtists[]`,localStorage key `cyber-star-vote`
- 新增 `scripts/`:DB 探查 / SQL 迁移 apply / E2E 回归测试(走完整 OTP 登录)
- 提交后 DB 测试数据清空,从 0/12 重新开始
**风险 / 已知问题**
- 前端 hydrate 仍只用 localStorage,不消费后端 `/api/me.votedArtists`。用户清缓存或换设备会看到"我能再投",但 DB unique 兜底,重投会被服务端拒绝(toast 提示已投过)
-`daily_quota` 表数据保留未清,新逻辑不再读取
**报告**: [docs/todo/voting-refactor-完成报告.md](docs/todo/voting-refactor-完成报告.md)、[docs/todo/voting-refactor-backend-完成报告.md](docs/todo/voting-refactor-backend-完成报告.md)
---
## v0.2.2 · 2026-05-15 · 内容批次 v2 修正 + 单人视频
**Commit 信息**
- Tag 打在: [`8d8451b`](https://gitea.airlabs.art/zyc/UI-UX/commit/8d8451b) `chore(tos): bump cache version 6 → 7 for 014-2 recrop`
- 完整 diff: [v0.2.1...v0.2.2](https://gitea.airlabs.art/zyc/UI-UX/compare/v0.2.1...v0.2.2)
**改了什么**
- 多位艺人立绘 / 头像 / 氛围图替换(003 / 006 / 007 / 010 / 014 / 017 / 019 / 027 / 033 等)
- 单人表演视频更新(5 个艺人)
- Hero PV 视频压缩 4K 1.19GB → 1080p 47MB
- Nav logo 去除 + Hero 视频默认静音
**技术点**
- TOS bucket `?v=` 缓存版本号 4→7 多次升级
- `sharp` + `ffmpeg-static` 资源压缩管线(`scripts/` 多个工具)
---
## v0.2.1 · 2026-05-14 · UI 视觉打磨
**Commit 信息**
- Tag 打在: [`7168e50`](https://gitea.airlabs.art/zyc/UI-UX/commit/7168e50) `fix: prod login + env-file driven config + scroll-snap bounce`
- 完整 diff: [v0.2.0...v0.2.1](https://gitea.airlabs.art/zyc/UI-UX/compare/v0.2.0...v0.2.1)
**改了什么**
- 导航栏滚动到 Hero 下方时自动从透明变毛玻璃
- 加浮动返回按钮 + 滚动位置 per-tab 记忆
- 筛选条吸顶时与 nav 合并为单一 backdrop-filter 带,消除接缝
**技术点**
- `useUIStore` 跨组件感知 filter 吸顶状态
- 修复生产登录失败 + .env 驱动配置
---
## v0.2.0 · 2026-05-13 · 真实持久化 + CI/CD 打通
**Commit 信息**
- Tag 打在: [`1073262`](https://gitea.airlabs.art/zyc/UI-UX/commit/1073262) `ci(secret): inject Aliyun SMS credentials into cyberstar-env`
- 核心 commit: [`a9f4799`](https://gitea.airlabs.art/zyc/UI-UX/commit/a9f4799) `feat(db): wire real persistence for votes / users / quota / supports`
- 完整 diff: [v0.1.0...v0.2.0](https://gitea.airlabs.art/zyc/UI-UX/compare/v0.1.0...v0.2.0)
**改了什么**
- 投票 / 用户 / 应援 / 额度全部走真实数据库(火山引擎 RDS),不再 mock
- 阿里云短信 OTP 登录上线(国内手机号)
- 静态资源全部迁移到火山引擎 TOS 桶
- 排行榜真实动态计算(基于 DB 聚合)
**技术点**
- CI/CD 流水线接通 Gitea Actions → Docker build → K3s 部署
- `cyberstar-env` Secret 注入 DATABASE_URL + SMS 凭据
- Prisma alpine binary target + hoisted node_modules 适配 docker
- next/image 对 TOS 资源关掉优化(否则会代理拉破带宽)
---
## v0.1.0 · 2026-05-12 · 项目骨架与全部页面初版
**Commit 信息**
- Tag 打在: [`d5ed43a`](https://gitea.airlabs.art/zyc/UI-UX/commit/d5ed43a) `feat(ui): design overhaul, global login modal, design spec`
- 核心 commit: [`8a83815`](https://gitea.airlabs.art/zyc/UI-UX/commit/8a83815) `chore: bootstrap Next.js 16 + Tailwind v4 + TypeScript baseline`
- 范围: 项目第一个 commit 到 d5ed43a(共 16 个 commit)
**改了什么**
- Next.js 16 + Tailwind v4 + TypeScript 项目搭建
- 紫色品牌设计系统(Megrim / Audiowide / Cinzel / Inter 字体)
- 首页(Hero + Top12 + 36 艺人候选区)
- 排行榜(Top3 podium + Top4-12 列表 + 出道线 + 候补区)
- 艺人详情页(Hero + 15s 视频 + Gallery + 人物小传)
- /me 用户中心(配额卡 / 签到日历 / 统计 / 应援)
- 通用组件(Button / Countdown / ArtistCard / Top12Bar / VoteModal)
- Auth.js v5 手机号 OTP 登录(全局登录 modal)
- REST API(artists / ranking / me / vote / signin)+ Redis 限流 + Zod 校验
- Prisma 6 + MySQL schema(Vote / DailyQuota / FanSupport / Invitation / RiskLog 等)
- 实时排名 polling + LiveBadge
**技术点**
- 首版投票规则:**无限制**(无日额度、无单艺人上限)—— 后续逐步加严
- API 不可达时前端降级到 mock 数据
---
_格式参考 [Keep a Changelog](https://keepachangelog.com/),宽松版_