visual-novel-web/src/app/(main)/character/[id]/(detail)/components/BasicInfo.tsx

154 lines
4.7 KiB
TypeScript
Raw Normal View History

2025-11-03 10:03:34 +00:00
import { Rate } from '@/components';
2025-10-28 07:59:26 +00:00
import Image from 'next/image';
import { RightArrowIcon } from '@/assets/chatacter';
2025-11-03 10:03:34 +00:00
import IconFont from '@/components/ui/iconFont';
import ChatButton from './ChatButton';
import Tags from '@/components/ui/Tags';
type CharacterBasicInfoProps = {
characterId: string;
characterDetail?: any;
};
export default function CharacterBasicInfo({
characterId,
characterDetail,
}: CharacterBasicInfoProps) {
if (!characterDetail) {
return null;
}
const from = characterDetail?.from || "The CEO's Contract Wife";
const avatar = characterDetail?.avatar || '/test.png';
const fromImage = characterDetail?.fromImage || '/images/character/from.png';
const characterName = characterDetail?.name || '未知角色';
2025-10-28 07:59:26 +00:00
return (
2025-11-03 10:03:34 +00:00
<article className="flex w-full gap-7.5">
{/* 角色头像 - 使用 figure 语义化标签 */}
<figure>
<Image
src={avatar}
alt={`${characterName} - 角色头像`}
width={338}
height={600}
priority
/>
</figure>
2025-10-28 07:59:26 +00:00
<div className="w-full pt-5">
2025-11-03 10:03:34 +00:00
{/* 角色名称 - 使用 header 和 h1 */}
<header className="flex items-center justify-between">
<h1 className="text-text-color text-4xl font-bold">
{characterName}
</h1>
2025-10-28 07:59:26 +00:00
<div>
2025-11-03 10:03:34 +00:00
<IconFont type="icon-jubao" size={20} />
2025-10-28 07:59:26 +00:00
</div>
2025-11-03 10:03:34 +00:00
</header>
{/* 角色基本信息 - 使用定义列表 */}
<dl className="text-text-color/60 mt-4 flex items-center gap-2">
<div className="flex items-center gap-2">
<dt
style={{ backgroundColor: 'rgba(255, 102, 0, 1)' }}
className="text-text-color inline-flex h-4 w-4 justify-center rounded-md text-xs"
aria-label="角色ID"
>
ID
</dt>
<dd>{characterDetail.id}</dd>
2025-10-28 07:59:26 +00:00
</div>
<div
style={{ background: 'rgba(255, 255, 255, 0.2)' }}
className="h-2 w-0.25"
2025-11-03 10:03:34 +00:00
aria-hidden="true"
2025-10-28 07:59:26 +00:00
></div>
2025-11-03 10:03:34 +00:00
<div className="flex items-center gap-2">
<dt className="sr-only"></dt>
<dd>{characterDetail.age ?? '18'}</dd>
</div>
2025-10-28 07:59:26 +00:00
<div
style={{ background: 'rgba(255, 255, 255, 0.2)' }}
className="h-2 w-0.25"
2025-11-03 10:03:34 +00:00
aria-hidden="true"
2025-10-28 07:59:26 +00:00
></div>
2025-11-03 10:03:34 +00:00
<div className="flex items-center gap-2">
<dt className="sr-only"></dt>
<dd>{characterDetail.role}</dd>
</div>
</dl>
2025-10-28 07:59:26 +00:00
{/* 角色评分 */}
2025-11-03 10:03:34 +00:00
<div className="mt-8">
<Rate value={characterDetail.rate ?? 7} readonly />
</div>
2025-10-28 07:59:26 +00:00
2025-11-03 10:03:34 +00:00
{/* 角色TAG */}
{characterDetail.tags && characterDetail.tags.length > 0 && (
<div className="mt-10">
<Tags
options={characterDetail.tags.map((tag: any) => ({
label: tag,
value: tag,
}))}
2025-10-28 07:59:26 +00:00
/>
</div>
2025-11-03 10:03:34 +00:00
)}
2025-10-28 07:59:26 +00:00
2025-11-03 10:03:34 +00:00
{/* divider */}
<div
className="bg-text-color/10 mt-10 h-0.25 w-full"
aria-hidden="true"
></div>
{/* description - 使用 section 和语义化标签 */}
{characterDetail.description && (
<section className="mt-10.5">
<h2 className="flex items-center">
2025-10-28 07:59:26 +00:00
<Image
2025-11-03 10:03:34 +00:00
src={'/character/desc.svg'}
alt=""
aria-hidden="true"
className="mr-1"
width={18}
height={20}
2025-10-28 07:59:26 +00:00
/>
2025-11-03 10:03:34 +00:00
Description:
</h2>
<p className="text-text-color/60 mt-5 text-sm">
{characterDetail.description}
</p>
</section>
)}
{/* from and chat */}
<div className="flex items-center justify-between gap-10 pt-5">
{/* FROM - 使用语义化标签 */}
{from && (
<div className="bg-text-color/5 flex h-15 items-center justify-between rounded-lg pr-5">
<div className="flex items-center">
<Image
src={fromImage}
alt={`${from} - 来源作品封面`}
className="rounded-lg"
width={45}
height={60}
/>
<div className="text-text-color/80 max-w-110 pr-2 text-sm">
<span style={{ color: 'rgb(0, 102, 255)' }}>Form:</span>
{` ${from}`}
</div>
2025-10-28 07:59:26 +00:00
</div>
2025-11-03 10:03:34 +00:00
<RightArrowIcon />
2025-10-28 07:59:26 +00:00
</div>
2025-11-03 10:03:34 +00:00
)}
2025-10-28 07:59:26 +00:00
2025-11-03 10:03:34 +00:00
{/* Chat Button - 客户端组件 */}
<ChatButton characterId={characterId} />
2025-10-28 07:59:26 +00:00
</div>
</div>
2025-11-03 10:03:34 +00:00
</article>
2025-10-28 07:59:26 +00:00
);
}