6 Commits

Author SHA1 Message Date
iye
10878ddb3f feat(vote): 重构投票模型为终身 12 票 + 每艺人 1 票
Some checks failed
Build and Deploy / build-and-deploy (push) Has been cancelled
前端:
- store 改为 votedArtists[] + zustand persist
- VoteModal 删除 1/3/5/ALL 选择器,改三态(待投/已投/满额)
- 卡片/排行/详情页加 hasVoted 状态 + ✓ 角标
- Hero 右上角 Countdown 替换为 HeroVoteProgress(12 格点亮进度)
- /me 改为终身额度叙事(QuotaCard / StatsGrid / MyFanSupport)

后端:
- votes 表加 @@unique([userId, artistId])(已 apply 到生产 RDS)
- /api/vote 重写:12 票上限 + P2002 ALREADY_VOTED + P2003 NOT_FOUND 兜底
- /api/me 新增 votedArtists[] + voteQuota,移除 dailyQuota
- 新增 ERR.ALREADY_VOTED 错误码

测试:
- DB 层 5/5 + E2E 18/18 通过(scripts/e2e-vote-flow.sh)
- 修复 P2003 FK 违反未识别的 bug

详情见 docs/todo/voting-refactor-完成报告.md 与 voting-refactor-backend-完成报告.md

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-15 20:14:57 +08:00
iye
a9f4799f71 feat(db): wire real persistence for votes / users / quota / supports
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 3m26s
数据正式落库, 不再仅靠浏览器内存:

prisma/schema.prisma:
- Artist 模型对齐当前前端数据形态:
  * 旧字段 slogan / birthday / cv / themeColor 改为可选 (前端早不用, 但保留兼容历史 seed)
  * 新增 age / gender / motto / personality / catchphrase / skills / track (来自人物小传)
- 注释从 "001 ~ 035" 改 "001 ~ 036"

prisma/seed.ts:
- 整体重写: 从 src/lib/artist-bios.ts 的 ARTIST_SEEDS 灌真实 36 人
- 不再写假数据 (AURORA / LUMI / NEBULA...)
- portrait / videoUrl 不入库 (前端 NEXT_PUBLIC_TOS_DOMAIN 拼接, 换桶不用 reseed)
- ActivityConfig 默认 dailyQuota=10, perArtistLimit=0, voteEnabled=true, 活动期 30 天

src/lib/date-utils.ts (新增):
- startOfUtcDay(): 修复"今日"在 MySQL @db.Date 列与 JS Date 之间的 TZ 漂移
- isSameUtcDay(): 共享给签到判断

修复 P2025 bug (vote / me / signin):
- 用 startOfUtcDay 替代 startOfDay (后者用 setHours 取本地午夜,
  对 @db.Date 列会因 TZ 漂移导致 upsert 后再用 userId_date 复合键查找失败)
- /api/vote 的扣额度从 userId_date 改用 dq.id 主键 update, 双保险
- 三个路由的 startOfDay 重复实现合并到 lib/date-utils

E2E 验证 (curl):
  登录 → 投 5 给 002 → 余 5 ✓
  投 3 给 003 → 余 2 / totalVotes 8 ✓
  /api/me supports 反映 002+003 真实 voteTotal ✓
  超额 (5 票 余 2) → 409 QUOTA_EXHAUSTED ✓
  /api/ranking 票数实时反映 DB ✓

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 17:32:38 +08:00
zyc
7506372abd fix(ci): hoisted node_modules + alpine binary target for Prisma in Docker
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 5m45s
Root cause (from build log):
1. Prisma 6 generates client into @prisma/client package dir (not .prisma/client)
2. pnpm default isolated linker puts everything in .pnpm/ store with symlinks
   at top-level — Docker COPY of @prisma followed broken/incomplete symlinks
3. node:22-alpine needs linux-musl-openssl-3.0.x engine binary

Fixes:
- .npmrc: node-linker=hoisted → flat node_modules, COPY behaves like npm
- schema.prisma: add linux-musl-openssl-3.0.x to binaryTargets
- Dockerfile: drop dead .prisma/client checks, copy only @prisma (where
  Prisma 6 actually writes the client) plus standalone output

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 14:13:37 +08:00
iye
d5ed43acbd feat(ui): design overhaul, global login modal, design spec
- nav: center links (首页/排行榜/我的), right-side AuthMenu + RemainingVotesBadge; image logo with responsive sizing
- auth: replace /login route with global LoginModal triggered anywhere; "我的" intercepts unauth users with post-login redirect
- home: full-screen Hero, redesigned Top12 (12 pill cards, top-3 glow), scroll-snap mandatory between Hero/Top12/candidates
- home: candidates section with sticky filter that gains frosted-glass bg when stuck (matches nav)
- filter: simplified tags (全部/舞蹈/声乐/rap/全能型); ArtistCard uniform purple vote button
- ranking/me: remove Top12Bar; me header stacks 编辑资料/退出登录 vertically
- typography: font-logo set to Orbitron; ✦ glyph in CYBER ✦ STAR preserved
- layout: max-w-[1500px] unified across pages
- docs: add design-spec.md + design-spec.html with full visual spec (lucide SVG, zero emoji policy)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-12 18:59:30 +08:00
iye
175276a085 feat(api): add REST API routes (artists/ranking/me/vote/signin) + Redis rate limiting + Zod validation 2026-05-12 09:59:38 +08:00
iye
91a0dd0f05 feat(db): Prisma 6 + MySQL schema with all models, seed script and env example 2026-05-12 09:51:17 +08:00