@@ -48,8 +48,10 @@ export type PlatformHomeTab = 'home' | 'create' | 'saves' | 'profile';
|
||||
const PANEL_SURFACE_CLASS = 'platform-surface platform-surface--soft';
|
||||
const HERO_SURFACE_CLASS =
|
||||
'platform-surface platform-surface--hero platform-interactive-card';
|
||||
const MOBILE_PAGE_STAGE_CLASS = 'platform-page-stage space-y-4 pb-2';
|
||||
const DESKTOP_PAGE_STAGE_CLASS = 'platform-page-stage space-y-5 pb-4';
|
||||
const MOBILE_PAGE_STAGE_CLASS =
|
||||
'platform-page-stage platform-remap-surface space-y-4 pb-2';
|
||||
const DESKTOP_PAGE_STAGE_CLASS =
|
||||
'platform-page-stage platform-remap-surface space-y-5 pb-4';
|
||||
|
||||
function SectionHeader({ title, detail }: { title: string; detail: string }) {
|
||||
return (
|
||||
@@ -57,14 +59,18 @@ function SectionHeader({ title, detail }: { title: string; detail: string }) {
|
||||
<div className="text-[10px] font-semibold tracking-[0.26em] text-zinc-500">
|
||||
{detail}
|
||||
</div>
|
||||
<div className="mt-1 text-base font-semibold text-white">{title}</div>
|
||||
<div className="mt-1 text-base font-semibold text-[var(--platform-text-strong)]">
|
||||
{title}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function EmptyShelf({ text }: { text: string }) {
|
||||
return (
|
||||
<div className={`${PANEL_SURFACE_CLASS} rounded-[1.35rem] px-4 py-3 text-sm leading-6 text-zinc-300`}>
|
||||
<div
|
||||
className={`${PANEL_SURFACE_CLASS} rounded-[1.35rem] px-4 py-3 text-sm leading-6 text-zinc-300`}
|
||||
>
|
||||
{text}
|
||||
</div>
|
||||
);
|
||||
@@ -82,7 +88,7 @@ function SaveArchivePreview({
|
||||
return (
|
||||
<div
|
||||
aria-hidden="true"
|
||||
className={`relative shrink-0 overflow-hidden rounded-[1.35rem] border border-white/12 bg-black/18 shadow-[0_16px_36px_rgba(15,23,42,0.18)] ${className}`}
|
||||
className={`platform-remap-surface relative shrink-0 overflow-hidden rounded-[1.35rem] border border-white/12 bg-black/18 shadow-[var(--platform-desktop-hover-shadow)] ${className}`}
|
||||
>
|
||||
{entry.coverImageSrc ? (
|
||||
<img
|
||||
@@ -93,7 +99,7 @@ function SaveArchivePreview({
|
||||
) : (
|
||||
<div className="absolute inset-0 bg-[radial-gradient(circle_at_top_left,rgba(255,255,255,0.18),transparent_34%),linear-gradient(145deg,rgba(255,94,125,0.92),rgba(255,150,116,0.88))]" />
|
||||
)}
|
||||
<div className="absolute inset-0 bg-[linear-gradient(180deg,rgba(8,10,14,0.06),rgba(8,10,14,0.74))]" />
|
||||
<div className="absolute inset-0 bg-[var(--platform-card-overlay-soft)]" />
|
||||
<div className="absolute inset-x-0 bottom-0 px-2.5 py-2">
|
||||
<span className="inline-flex max-w-full items-center rounded-full border border-white/15 bg-black/24 px-2.5 py-1 text-[9px] font-semibold tracking-[0.14em] text-white/88">
|
||||
{label}
|
||||
@@ -147,12 +153,10 @@ function WorldCard({
|
||||
className="absolute bottom-2 right-2 h-24 w-24 object-contain opacity-25"
|
||||
/>
|
||||
) : null}
|
||||
<div className="absolute inset-0 bg-[linear-gradient(180deg,rgba(8,10,14,0.14),rgba(8,10,14,0.9))]" />
|
||||
<div className="absolute inset-0 bg-[var(--platform-card-overlay-strong)]" />
|
||||
<div className="relative z-10 flex h-full flex-col">
|
||||
<div className="flex items-start justify-between gap-3">
|
||||
<span className="platform-pill platform-pill--warm">
|
||||
{badge}
|
||||
</span>
|
||||
<span className="platform-pill platform-pill--warm">{badge}</span>
|
||||
<span className="platform-pill platform-pill--neutral px-2.5">
|
||||
{metaLabel}
|
||||
</span>
|
||||
@@ -233,7 +237,7 @@ function CreationLibraryCard({
|
||||
className="absolute bottom-1.5 right-1.5 h-16 w-16 object-contain opacity-24 sm:h-20 sm:w-20"
|
||||
/>
|
||||
) : null}
|
||||
<div className="absolute inset-0 bg-[linear-gradient(180deg,rgba(8,10,14,0.1),rgba(8,10,14,0.92))]" />
|
||||
<div className="absolute inset-0 bg-[var(--platform-card-overlay-strong)]" />
|
||||
<div className="relative z-10 flex h-full min-w-0 flex-col">
|
||||
<div className="flex min-w-0 flex-wrap items-center gap-1.5">
|
||||
<span
|
||||
@@ -267,7 +271,9 @@ function CreationLibraryCard({
|
||||
<span className="truncate">{primaryTag}</span>
|
||||
</span>
|
||||
<span className="inline-flex items-center gap-1 text-[11px] font-semibold text-zinc-200">
|
||||
<span>{entry.visibility === 'published' ? '进入世界' : '继续创作'}</span>
|
||||
<span>
|
||||
{entry.visibility === 'published' ? '进入世界' : '继续创作'}
|
||||
</span>
|
||||
<ArrowRight className="h-3.5 w-3.5 shrink-0" />
|
||||
</span>
|
||||
</div>
|
||||
@@ -286,7 +292,8 @@ function SaveArchiveCard({
|
||||
onClick: () => void;
|
||||
loading?: boolean;
|
||||
}) {
|
||||
const summaryText = entry.summaryText || entry.subtitle || '继续推进上一次保存的故事。';
|
||||
const summaryText =
|
||||
entry.summaryText || entry.subtitle || '继续推进上一次保存的故事。';
|
||||
|
||||
return (
|
||||
<button
|
||||
@@ -295,7 +302,7 @@ function SaveArchiveCard({
|
||||
disabled={loading}
|
||||
className={`platform-surface platform-surface--soft platform-interactive-card relative flex min-h-[13rem] w-full overflow-hidden p-3.5 text-left sm:min-h-[12.5rem] sm:p-4 ${loading ? 'opacity-80' : ''}`}
|
||||
>
|
||||
<div className="absolute inset-0 bg-[radial-gradient(circle_at_top_left,rgba(255,255,255,0.14),transparent_30%),radial-gradient(circle_at_right,rgba(255,205,178,0.14),transparent_28%),linear-gradient(180deg,rgba(8,10,14,0.22),rgba(8,10,14,0.9))]" />
|
||||
<div className="absolute inset-0 bg-[var(--platform-card-overlay-deep)]" />
|
||||
<div className="relative z-10 flex h-full w-full flex-col gap-3">
|
||||
<div className="flex flex-wrap items-center justify-between gap-2">
|
||||
<span className="platform-pill platform-pill--cool">ARCHIVE</span>
|
||||
@@ -422,7 +429,7 @@ function DesktopTrendingItem({
|
||||
<span>{`${rank}`.padStart(2, '0')}</span>
|
||||
<span>{formatPlatformWorldTime(entry.publishedAt)}</span>
|
||||
</div>
|
||||
<div className="mt-2 line-clamp-1 text-lg font-semibold text-white">
|
||||
<div className="mt-2 line-clamp-1 text-lg font-semibold text-[var(--platform-text-strong)]">
|
||||
{entry.worldName}
|
||||
</div>
|
||||
<div className="mt-1 line-clamp-2 text-sm leading-6 text-zinc-300/86">
|
||||
@@ -581,7 +588,9 @@ function ProfileStatCard({
|
||||
<Icon className="h-4 w-4" />
|
||||
<span className="text-[11px] tracking-[0.16em]">{label}</span>
|
||||
</div>
|
||||
<div className="mt-3 text-lg font-black text-white">{value}</div>
|
||||
<div className="mt-3 text-lg font-black text-[var(--platform-text-strong)]">
|
||||
{value}
|
||||
</div>
|
||||
</button>
|
||||
);
|
||||
}
|
||||
@@ -615,7 +624,9 @@ function ProfileShortcutButton({
|
||||
<div className="platform-profile-chip flex h-10 w-10 items-center justify-center rounded-full">
|
||||
<Icon className="h-[1.125rem] w-[1.125rem]" />
|
||||
</div>
|
||||
<div className="text-sm font-semibold text-white">{label}</div>
|
||||
<div className="text-sm font-semibold text-[var(--platform-text-strong)]">
|
||||
{label}
|
||||
</div>
|
||||
</button>
|
||||
);
|
||||
}
|
||||
@@ -756,7 +767,7 @@ export function PlatformHomeView({
|
||||
? `${snapshotCharacterName} 的进度已保存,点这里回到上一次停下来的故事节点。`
|
||||
: '从设定、角色到场景网络,先生成一版可玩的世界底稿,再继续精修和发布。'}
|
||||
</div>
|
||||
<div className="mt-4 flex items-center gap-2 text-sm font-semibold text-violet-100">
|
||||
<div className="mt-4 flex items-center gap-2 text-sm font-semibold text-white/90">
|
||||
<span>{hasSavedGame ? '继续推进故事' : '进入创作工作台'}</span>
|
||||
<ArrowRight className="h-4 w-4" />
|
||||
</div>
|
||||
@@ -832,7 +843,7 @@ export function PlatformHomeView({
|
||||
<div className="mt-2 max-w-[28rem] text-sm leading-6 text-zinc-200/88">
|
||||
先选择游戏类型,再进入对应的创作工作台继续推进。
|
||||
</div>
|
||||
<div className="mt-4 flex items-center gap-2 text-sm font-semibold text-cyan-100">
|
||||
<div className="mt-4 flex items-center gap-2 text-sm font-semibold text-white/90">
|
||||
<span>选择类型并继续</span>
|
||||
<ArrowRight className="h-4 w-4" />
|
||||
</div>
|
||||
@@ -904,7 +915,9 @@ export function PlatformHomeView({
|
||||
) : (
|
||||
<section className={`${PANEL_SURFACE_CLASS} px-4 py-3.5`}>
|
||||
<div className="platform-subpanel rounded-[1.35rem] px-4 py-4">
|
||||
<div className="text-base font-semibold text-white">尚未登录</div>
|
||||
<div className="text-base font-semibold text-[var(--platform-text-strong)]">
|
||||
尚未登录
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => authUi?.openLoginModal()}
|
||||
@@ -1074,7 +1087,9 @@ export function PlatformHomeView({
|
||||
<Settings className="h-[1.125rem] w-[1.125rem]" />
|
||||
</div>
|
||||
<div>
|
||||
<div className="text-base font-semibold text-white">设置</div>
|
||||
<div className="text-base font-semibold text-[var(--platform-text-strong)]">
|
||||
设置
|
||||
</div>
|
||||
<div className="text-xs text-zinc-400">主题与账号</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1085,7 +1100,9 @@ export function PlatformHomeView({
|
||||
) : (
|
||||
<section className={`${PANEL_SURFACE_CLASS} px-4 py-3.5`}>
|
||||
<div className="platform-subpanel rounded-[1.35rem] px-4 py-4">
|
||||
<div className="text-base font-semibold text-white">尚未登录</div>
|
||||
<div className="text-base font-semibold text-[var(--platform-text-strong)]">
|
||||
尚未登录
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => authUi?.openLoginModal()}
|
||||
@@ -1144,15 +1161,19 @@ export function PlatformHomeView({
|
||||
|
||||
<div className="max-w-[35rem]">
|
||||
<div className="text-5xl font-semibold leading-[1.08] text-white">
|
||||
{hasSavedGame ? snapshotWorldName : '把你的世界观直接变成可游玩的舞台'}
|
||||
{hasSavedGame
|
||||
? snapshotWorldName
|
||||
: '把你的世界观直接变成可游玩的舞台'}
|
||||
</div>
|
||||
<div className="mt-4 text-base leading-8 text-zinc-200/86">
|
||||
{hasSavedGame
|
||||
? `${snapshotCharacterName} 的进度已经保存,桌面端可以直接从这里回到上一次停下来的关键节点。`
|
||||
: '从设定、角色、世界结构到可玩流程,一次生成创作底稿,再继续精修并发布到平台广场。'}
|
||||
</div>
|
||||
<div className="mt-5 inline-flex items-center gap-2 rounded-full border border-violet-300/18 bg-violet-500/14 px-4 py-2 text-sm font-semibold text-violet-100">
|
||||
<span>{hasSavedGame ? '继续推进故事' : '进入创作工作台'}</span>
|
||||
<div className="mt-5 inline-flex items-center gap-2 rounded-full border border-white/18 bg-white/18 px-4 py-2 text-sm font-semibold text-white/92">
|
||||
<span>
|
||||
{hasSavedGame ? '继续推进故事' : '进入创作工作台'}
|
||||
</span>
|
||||
<ArrowRight className="h-4 w-4" />
|
||||
</div>
|
||||
</div>
|
||||
@@ -1181,7 +1202,9 @@ export function PlatformHomeView({
|
||||
<span className="text-zinc-500">
|
||||
{`${index + 1}`.padStart(2, '0')}
|
||||
</span>
|
||||
<span className="line-clamp-1">{entry.worldName}</span>
|
||||
<span className="line-clamp-1">
|
||||
{entry.worldName}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@@ -1405,8 +1428,11 @@ export function PlatformHomeView({
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="mt-4 border-t border-white/5 pt-3"
|
||||
style={{ paddingBottom: 'calc(env(safe-area-inset-bottom) + 0.2rem)' }}
|
||||
className="mt-4 border-t pt-3"
|
||||
style={{
|
||||
borderColor: 'var(--platform-line-soft)',
|
||||
paddingBottom: 'calc(env(safe-area-inset-bottom) + 0.2rem)',
|
||||
}}
|
||||
>
|
||||
<div className="platform-bottom-nav grid h-14 grid-cols-4 gap-1 rounded-[1.2rem] px-1 py-1">
|
||||
<PlatformTabButton
|
||||
@@ -1441,10 +1467,7 @@ export function PlatformHomeView({
|
||||
<div className="platform-desktop-shell flex h-full min-h-0 flex-col p-5 xl:p-6">
|
||||
<div className="platform-desktop-topbar flex items-center gap-4 px-5 py-4">
|
||||
<div className="flex min-w-0 flex-1 items-center gap-5">
|
||||
<PlatformBrandLogo
|
||||
className="shrink-0"
|
||||
decorative
|
||||
/>
|
||||
<PlatformBrandLogo className="shrink-0" decorative />
|
||||
<div className="platform-desktop-search flex min-w-0 max-w-[34rem] flex-1 items-center gap-3 px-4 py-3 text-zinc-400">
|
||||
<Search className="h-4 w-4 shrink-0" />
|
||||
<span className="truncate text-sm">
|
||||
@@ -1467,11 +1490,17 @@ export function PlatformHomeView({
|
||||
onClick={openUserSurface}
|
||||
className="platform-desktop-search flex items-center gap-3 px-3 py-2.5 text-left"
|
||||
>
|
||||
<span className="flex h-11 w-11 items-center justify-center rounded-full bg-[linear-gradient(135deg,rgba(91,108,255,0.9),rgba(61,217,255,0.82))] text-base font-black text-white shadow-[0_10px_22px_rgba(91,108,255,0.24)]">
|
||||
<span
|
||||
className="flex h-11 w-11 items-center justify-center rounded-full text-base font-black text-white"
|
||||
style={{
|
||||
background: 'var(--platform-profile-avatar-fill)',
|
||||
boxShadow: 'var(--platform-profile-avatar-shadow)',
|
||||
}}
|
||||
>
|
||||
{avatarLabel}
|
||||
</span>
|
||||
<span className="min-w-0">
|
||||
<span className="block truncate text-sm font-semibold text-white">
|
||||
<span className="block truncate text-sm font-semibold text-[var(--platform-text-strong)]">
|
||||
{authUi?.user?.displayName || '进入账户'}
|
||||
</span>
|
||||
<span className="block truncate text-xs text-zinc-400">
|
||||
|
||||
Reference in New Issue
Block a user