feat(themes): 添加可编辑的站点外观和皮肤主题(#408)

This commit is contained in:
Ray authored and GitHub committed 2026-09-03 21:13:41 +08:00
1 parent c768fccbc2
commit 5e66cb7c45
70 files changed
+3654 -327

No files matched your search

+10 -11
View File
@@ -4,6 +4,7 @@ import { ArrowLeft, Play } from "lucide-react";
import { Link, Outlet, useLocation, useNavigate } from "react-router";
import { BrandLogo } from "@/components/brand/brand-logo";
import { SiteComplianceFooter } from "@/components/layout/site-compliance-footer";
import { aceternityMotion } from "@/lib/aceternity-motion";
import { getAntThemeConfig } from "@/lib/app-theme";
import { brandStudioLabel, useAppearanceStore } from "@/stores/use-appearance-store";
@@ -54,12 +55,12 @@ export function AuthScene() {
const copy = recovery ? authCopy.recovery : activeTab === "register" ? authCopy.register : authCopy.login;
return (
<main className="h-dvh min-h-0 overflow-y-auto bg-[#08090c] text-white lg:overflow-hidden">
<main className="auth-scene h-dvh min-h-0 overflow-y-auto text-white lg:overflow-hidden">
<div className="grid min-h-full lg:h-full lg:grid-cols-[minmax(0,1.32fr)_minmax(520px,1fr)]">
<section className="relative min-h-[250px] overflow-hidden sm:min-h-[320px] lg:min-h-0" aria-label={`${appearance.brandName}品牌影片`}>
<video className="absolute inset-0 size-full object-cover" src={appearance.authVideoUrl} poster={appearance.authVideoPosterUrl || undefined} autoPlay={!reducedMotion} muted loop playsInline preload="metadata" />
<div aria-hidden className="absolute inset-0 bg-[linear-gradient(180deg,rgba(4,5,8,.58),transparent_42%,rgba(4,5,8,.74))]" />
<div aria-hidden className="absolute inset-y-0 right-0 hidden w-[clamp(120px,14vw,240px)] bg-[linear-gradient(90deg,transparent_0%,rgba(11,12,16,.68)_58%,#0b0c10_100%)] lg:block" />
<div aria-hidden className="auth-scene-video-blend absolute inset-y-0 right-0 hidden w-[clamp(120px,14vw,240px)] lg:block" />
<div className="absolute inset-x-0 top-0 flex items-center justify-between gap-4 p-5 sm:p-7 lg:p-9">
<Link to="/" className="inline-flex items-center gap-2.5 text-sm font-semibold text-white drop-shadow-sm transition-opacity hover:opacity-80">
<BrandLogo theme="dark" className="size-7" alt="" fallback={<span className="size-7 bg-current" style={{ mask: "url(/logo.svg) center / contain no-repeat", WebkitMask: "url(/logo.svg) center / contain no-repeat" }} />} />
@@ -82,11 +83,8 @@ export function AuthScene() {
</motion.div>
</section>
<section className="relative flex min-h-[620px] items-start justify-center overflow-y-auto bg-[#0b0c10] px-4 pb-8 pt-20 sm:px-8 lg:min-h-0 lg:px-10 lg:pb-10 lg:pt-20">
<Link
to="/"
className="absolute right-5 top-5 z-20 inline-flex h-9 items-center gap-2 rounded-full border border-white/10 bg-white/[0.04] px-4 text-xs text-white/58 backdrop-blur-xl transition hover:border-white/20 hover:bg-white/[0.08] hover:text-white lg:right-8 lg:top-8"
>
<section className="auth-scene-form-pane relative flex min-h-[660px] items-start justify-center overflow-y-auto px-4 pb-24 pt-20 sm:px-8 lg:min-h-0 lg:px-10 lg:pb-24 lg:pt-20">
<Link to="/" className="auth-scene-return absolute right-5 top-5 z-20 inline-flex h-9 items-center gap-2 rounded-full px-4 text-xs backdrop-blur-xl transition lg:right-8 lg:top-8">
<ArrowLeft className="size-3.5" />
返回首页
</Link>
@@ -98,13 +96,13 @@ export function AuthScene() {
transition={{ duration: aceternityMotion.duration.panel, ease: aceternityMotion.easing.enter }}
className="my-auto w-full max-w-[460px]"
>
<ConfigProvider theme={getAntThemeConfig(true)}>
<div className="auth-card-dark h-auto overflow-hidden rounded-lg bg-[#121318]/94 shadow-[0_28px_80px_rgba(0,0,0,.34)] backdrop-blur-2xl">
<ConfigProvider theme={getAntThemeConfig(true, appearance.activeSkin)}>
<div className="auth-card-dark auth-scene-card h-auto overflow-hidden rounded-lg backdrop-blur-2xl">
<section aria-label={copy.title} className={`flex flex-col ${recovery ? "min-h-[600px]" : activeTab === "login" ? "min-h-[500px]" : "min-h-[620px] sm:min-h-[640px]"}`}>
<header className="px-6 pb-5 pt-6 sm:px-8 sm:pt-7">
<p className="text-xs font-semibold tracking-[0.18em] text-blue-300/80">{copy.eyebrow}</p>
<p className="auth-scene-eyebrow text-xs font-semibold tracking-[0.18em]">{copy.eyebrow}</p>
<h2 className="mt-2 text-3xl font-semibold">{copy.title}</h2>
<p className="mt-2 text-sm leading-6 text-white/45">{copy.description}</p>
<p className="auth-scene-muted mt-2 text-sm leading-6">{copy.description}</p>
</header>
{!recovery ? (
<div className="px-6 sm:px-8">
@@ -118,6 +116,7 @@ export function AuthScene() {
</div>
</ConfigProvider>
</motion.div>
<SiteComplianceFooter variant="auth" className="absolute inset-x-0 bottom-0" />
</section>
</div>
</main>