# CYBER ✦ STAR

虚拟偶像 Top12 出道企划 · 投票网页

## 技术栈

| 层 | 选型 |
|---|---|
| 框架 | Next.js 16（App Router）· React 19 · TypeScript |
| 样式 | Tailwind CSS v4（CSS-first `@theme`）· Framer Motion |
| 字体 | Megrim / Audiowide / Cinzel / Inter（全部 SIL OFL 商用免费）|
| 数据库 | MySQL 8 · Prisma 6 ORM |
| 缓存 / 限流 | Redis（`ioredis`，未配置时降级内存）|
| 身份 | Auth.js v5（手机号 OTP · 可扩展微信 / QQ）|
| 校验 | Zod |
| 部署 | 火山引擎 ECS · 火山引擎 TOS（对象存储）|

## 本地启动

```bash
pnpm install            # 安装依赖（自动 prisma generate）
cp .env.example .env    # 配置环境变量（首次）
pnpm dev                # http://localhost:3000
```

未配置数据库时，前端页面会回退到 `src/lib/mock-data.ts` 的 35 位艺人 mock 数据，UI 完全可用。

## 数据库初始化（部署时）

```bash
# 1. 创建 MySQL 库 + 在 .env 设置 DATABASE_URL
# 2. 推送 schema 到数据库
pnpm db:push

# 3. 灌入 35 位艺人 + 活动配置
pnpm db:seed

# 可视化管理（可选）
pnpm db:studio
```

## 关键脚本

| 命令 | 说明 |
|---|---|
| `pnpm dev` | 开发服务器（Turbopack）|
| `pnpm build` | 生产构建（先 prisma generate）|
| `pnpm start` | 生产服务器 |
| `pnpm lint` | ESLint |
| `pnpm db:push` | 把 schema 推到数据库 |
| `pnpm db:migrate` | 生成迁移脚本 |
| `pnpm db:seed` | 灌入种子数据 |
| `pnpm db:studio` | Prisma Studio（GUI）|

## 项目结构

```
prisma/
  schema.prisma         # 数据库 schema（10 个模型）
  seed.ts               # 初始化 35 位艺人

src/
  app/
    layout.tsx          # 根布局（含氛围装饰层）
    page.tsx            # 首页（Hero PV + Top12 + 35 卡片）
    artist/[id]/        # 艺人详情页
    ranking/            # 排行榜（Top3 podium + 出道线 + 候补区）
    me/                 # 个人中心
    login/              # 登录页（手机号 OTP）
    api/
      artists/          # GET 艺人列表 / 单个详情
      ranking/          # GET 实时排名
      vote/             # POST 投票（含风控限流 + 事务）
      me/               # GET 当前用户 / POST 签到
      auth/             # NextAuth handlers + send-otp
  components/
    Logo / Navigation / Footer / NavLinks
    HeroBanner / Top12Bar / ArtistFilters
    VoteModal / FloatingVoteButton / LiveBadge
    ui/                 # Button / Countdown
    cards/              # ArtistCard / ArtistPortrait
    artist/             # 详情页组件（视频 / 画廊 / 排名卡等）
    ranking/            # 排行榜组件
    me/                 # 个人中心组件
  hooks/
    useRanking.ts       # 实时排名轮询 hook
  lib/
    prisma / redis / rate-limit
    auth / current-user / api-response
    cn / mock-data / mock-user
  types/
    artist.ts
```

## 设计资料

- 交互原型：`../交互原型线框图.html`
- 视觉规范：`../视觉规范.html` · v1.1 紫调主导
- 需求文档：`../需求分析文档.md`
- 参考视觉：`../参考图.png`

## 团队需配置的外部服务

| 服务 | 用途 | 环境变量 |
|---|---|---|
| **MySQL（火山 RDS）** | 主数据库 | `DATABASE_URL` |
| **Redis（火山实例）** | 限流 / OTP 缓存 / 实时聚合 | `REDIS_URL` |
| **TOS（火山对象存储）** | 立绘 / 视频 / 头像 | `TOS_*` |
| **短信网关** | 手机号 OTP | `SMS_*` |
| **微信开放平台** | 微信扫码登录 | `WECHAT_APP_ID` `WECHAT_APP_SECRET` |
| **hCaptcha** | 反作弊验证码 | `HCAPTCHA_*` |

详见 `.env.example`。所有这些都用 TODO 注释标记在代码中，**可灰度配置 —— 没配置时功能自动降级**。

## 开发态便利

- **登录** ：`/login` 页面下，开发环境接受万能验证码 `123456`
- **mock 用户** ：API 调用前自动落到 `cs_user_id` cookie，可在开发面板设置
- **mock 数据** ：未配 DB 时前端自动使用 `mock-data.ts` 的 35 位艺人
- **实时排名** ：API 不可用时静默回退到 mock 数据

## 设计原则

参考 `../视觉规范.html` 的 16 个章节，核心：

- 紫罗兰为主调色（不是蓝），承担 CTA / 激活态 / 描边
- 装饰星标 ✦ 用于 Logo 中间，体现品牌签
- TOP12 头像方形圆角（不是圆形）— "明星卡片"质感
- VOTE NOW 紫色侧栏面板（不是普通按钮）— 视觉锚点
- 背景始终在深紫黑系，星点 + 紫雾装饰层
- 投票交互必须有动画仪式感
