UI-UX/src/types/artist.ts
iye 71a2672ff6 fix(data,ranking,ui): real dynamic ranking + data sync hardening
数据准确性
- 票数初始为 0,不再用 Math.sqrt 公式造假票
- 排序 tiebreaker 统一为 votes desc + no asc,确保稳定
- store.rank() 与 sortArtists() 行为对齐

Top12 / 出道位
- Top12Bar 仅收纳真正有票的人(votes > 0),0 票时显示"出道位尚未产生"空态
- ArtistCard / RankingRow / SearchModal / MyFanSupport / RankCard 的 inTop12 高亮全部加 votes > 0 守卫
- ArtistFilters 新增"实时排名 / 编号顺序"分段切换 + 首页 sortKey 状态

领奖台 (Top3Podium)
- 1 人有票即可显示领奖台(此前要求 >= 3 人才显示)
- 缺位的 #2/#3 用"虚位以待"占位卡片填充,与正式卡片同 3:4 比例对齐
- 全员 0 票时三张全部显示虚位以待
- 卡片间距拉大到 gap-8 sm:gap-12

排行榜页 (/ranking)
- API 票数与本地乐观投票取 max() 合并,避免 API 落后覆盖本地新票
- 合并后重新排序与赋 rank
- 仅 >= 12 人有票才显示出道线分隔与复活位标记
- 复活位 gapToDebut 计算修正

跨日额度
- selectRemaining 按 quotaDate 判断是否跨日,跨日自动回满额(此前会卡在昨日剩余值)

搜索 (SearchModal)
- 改为订阅 store 拿活的票数,投票后立即反映
- 默认"热门 Top12"只在真正有票时显示,否则降级为"推荐艺人 · 编号顺序"
- 票数显示统一走 formatVotes(0 票不再显示 0.0w)

人物详情
- 36 人真实数据接入,移除全部静态数据(slogan/birthday/cv/themeColor)
- 接入人物小传 docx 数据(年龄/身高/性格/口头禅/技能/赛道/座右铭/长简介)
- 视频区与版心同宽 + 首帧自动作为封面 + 整区点击播放/暂停 + 可拖拽进度条
- 表演图片改为三张氛围图竖向 3:4,左对齐
- 移除分享按钮,投票按钮全宽

个人页 (/me)
- 移除等级/邀请好友/签到/编辑资料等静态数据
- 退出登录按钮在移动端 icon-only 显示(此前 sm:hidden 导致移动端无法登出)
- 我的应援 list 基于真实 myVotesByArtist 派生,凯之类的投票真正同步过去

导航
- 余票徽章未登录态显示 0/0,已登录显示 N/10
- 登录/注册按钮样式与登录后头像胶囊保持一致(紫色实心)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 13:56:42 +08:00

72 lines
1.8 KiB
TypeScript
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.

export type ArtistTag =
| "rock"
| "pop"
| "chinese"
| "hiphop"
| "folk"
| "jazz";
export interface Artist {
/** 唯一 ID如 001 ~ 036 */
id: string;
/** 编号字符串(如 "001" */
no: string;
/** 中文名(来自小传) */
name: string;
/** 英文名 / 艺名(来自小传) */
enName: string;
/** 年龄(来自小传) */
age?: number;
/** 性别(来自小传) */
gender?: "M" | "F";
/** 长简介 / 人物小传(来自小传) */
bio: string;
/** 立绘主图 URL */
portrait: string;
/** 圆形头像 URL暂未使用 */
avatar: string;
/** 表演视频 URL来自 solo.mp4缺失则 undefined */
videoUrl?: string;
/** 视频封面图 */
videoPoster?: string;
/** 表演图片轮播(三视图 + 氛围图 2/3 */
gallery: string[];
/** 实力标签(用于筛选) */
tags: ArtistTag[];
/** 身高 cm来自小传 */
height: number;
/** 当前票数 */
votes: number;
/** 当前排名 (1-36) */
rank: number;
/** 座右铭(来自小传) */
motto?: string;
/** 性格描述(来自小传) */
personality?: string;
/** 口头禅(来自小传) */
catchphrase?: string;
/** 核心技能(来自小传) */
skills?: string;
/** 核心赛道(来自小传) */
track?: string;
}
export const TAG_LABEL: Record<ArtistTag, string> = {
rock: "摇滚",
pop: "流行",
chinese: "国风",
hiphop: "嘻哈说唱",
folk: "民谣治愈",
jazz: "爵士",
};
export type RankCategory = "gold" | "silver" | "bronze" | "top12" | "candidate";
export function getRankCategory(rank: number): RankCategory {
if (rank === 1) return "gold";
if (rank === 2) return "silver";
if (rank === 3) return "bronze";
if (rank <= 12) return "top12";
return "candidate";
}