"use client";
import Link from "next/link";
import {
ChevronLeft,
Heart,
Check,
Quote as QuoteIcon,
Sparkles,
Compass,
MessageCircle,
User,
Ruler,
Calendar,
BookOpen,
} from "lucide-react";
import type { Artist } from "@/types/artist";
import { TAG_LABEL } from "@/types/artist";
import ArtistPortrait from "@/components/cards/ArtistPortrait";
import VoteModal from "@/components/VoteModal";
import Button from "@/components/ui/Button";
import RankCard from "./RankCard";
import PerformanceVideo from "./PerformanceVideo";
import PerformanceGallery from "./PerformanceGallery";
import FloatingVoteButton from "@/components/FloatingVoteButton";
import FloatingBackButton from "@/components/FloatingBackButton";
import { useVoteStore, selectArtist, selectHasVoted } from "@/lib/store";
import { useVoteAction } from "@/hooks/useVoteAction";
import { cn } from "@/lib/cn";
interface ArtistDetailContentProps {
artist: Artist;
allArtists: Artist[];
}
/** 把 "、 / , ," 分隔的串切成 chip 数组 */
function parseChips(text?: string): string[] {
if (!text) return [];
return text
.split(/[、,,/]/)
.map((s) => s.trim())
.filter(Boolean);
}
export default function ArtistDetailContent({
artist: initialArtist,
allArtists: initialAll,
}: ArtistDetailContentProps) {
// 用 store 数据覆盖(投票后票数能马上变)
const storeArtist = useVoteStore(selectArtist(initialArtist.id));
const storeAll = useVoteStore((s) => s.artists);
const hasVoted = useVoteStore(selectHasVoted(initialArtist.id));
const artist = storeArtist ?? initialArtist;
const allArtists = storeAll.length ? storeAll : initialAll;
const { target, remaining, totalQuota, openVote, closeVote, confirmVote } =
useVoteAction();
return (
<>
{/* 面包屑 */}
{/* HERO · 立绘 + 身份信息 */}
openVote(artist)}
hasVoted={hasVoted}
/>
{/* 性格 · 口头禅 */}
{(artist.personality || artist.catchphrase) && (
{artist.personality &&
}
{artist.catchphrase &&
}
)}
{/* 核心技能 · 核心赛道 */}
{(artist.skills || artist.track) && (
{artist.skills && (
}
chips={parseChips(artist.skills)}
/>
)}
{artist.track && (
}
chips={parseChips(artist.track)}
/>
)}
)}
{/* 人物小传 · 长简介 */}
{artist.bio && (
)}
{/* 表演视频 · 与版心同宽,首帧自动作为封面,整个视频区域可点击播放/暂停 */}
{artist.videoUrl && (
)}
{/* 表演图片 · 三张氛围图,左对齐,竖向 3:4 */}
{artist.gallery && artist.gallery.filter(Boolean).length > 0 && (
)}
openVote(artist)} hasVoted={hasVoted} />
>
);
}
/* ============================================================
* 子组件 · 统一品牌紫色,无 per-artist themeColor
* ============================================================ */
interface HeroPanelProps {
artist: Artist;
allArtists: Artist[];
onVote: () => void;
hasVoted: boolean;
}
function HeroPanel({ artist, allArtists, onVote, hasVoted }: HeroPanelProps) {
return (
{/* 装饰光晕 */}
{/* 立绘 */}
{/* 身份信息 */}
{/* 编号 */}
No.{artist.no}
{/* 中文名 / 英文名 */}
{artist.name}
{artist.enName}
{/* 实力标签 */}
{artist.tags.map((t) => (
{TAG_LABEL[t]}
))}
{/* 年龄 / 身高 / 性别 */}
}
label="年龄"
value={artist.age != null ? `${artist.age} 岁` : "未公开"}
/>
}
label="身高"
value={`${artist.height} cm`}
/>
}
label="性别"
value={
artist.gender === "M"
? "男生"
: artist.gender === "F"
? "女生"
: "未公开"
}
/>
{/* 座右铭 · 品牌紫引文,保持与全站视觉一致 */}
{artist.motto && (
{artist.motto}
Motto · 座右铭
)}
{/* 排名卡片 */}
{/* 操作按钮 · 仅投票 */}
) : (
)
}
onClick={onVote}
>
{hasVoted ? "已投票" : "投票"}
);
}
function MetaCell({
icon,
label,
value,
}: {
icon: React.ReactNode;
label: string;
value: string;
}) {
return (
);
}
/**
* 性格 / 口头禅 双卡使用完全相同的容器规范:
* - 圆角 2xl + 玻璃化 surface 背景 + 同样的 border / padding
* - 左上角同样的紫色装饰条
* - 同款 SectionHeading
* 唯一差异:内容呈现 —— 性格是段落正文,口头禅是大字引号。
*/
function ProfileInfoCard({
title,
subtitle,
children,
}: {
title: string;
subtitle: string;
children: React.ReactNode;
}) {
return (
);
}
function PersonalityCard({ text }: { text: string }) {
return (
{text}
);
}
function CatchphraseCard({ text }: { text: string }) {
return (
);
}
function ChipCard({
label,
subtitle,
icon,
chips,
}: {
label: string;
subtitle: string;
icon: React.ReactNode;
chips: string[];
}) {
return (
{icon}
{chips.length > 0 ? (
{chips.map((c, i) => (
{c}
))}
) : (
未公开
)}
);
}
function BiographyCard({ bio }: { bio: string }) {
return (
);
}
function SectionHeading({
title,
subtitle,
}: {
title: string;
subtitle: string;
}) {
return (
{title}
{subtitle}
);
}