blog / src /layouts /AdminLayout.astro
cacode's picture
Upload 439 files
99cf942 verified
---
import OverlayWallpaper from "@components/features/OverlayWallpaper.astro";
import Navbar from "@components/layout/Navbar.astro";
import ImageWrapper from "@/components/common/ImageWrapper.astro";
import { backgroundWallpaper, siteConfig } from "@/config";
import { getBackgroundImages } from "@/utils/layout-utils";
import Layout from "./Layout.astro";
interface Props {
title?: string;
description?: string;
}
const { title, description } = Astro.props;
const backgroundImages = getBackgroundImages();
const bannerImage =
typeof backgroundImages.desktop === "string"
? backgroundImages.desktop
: typeof backgroundImages.mobile === "string"
? backgroundImages.mobile
: "";
const isOverlayMode = backgroundWallpaper.mode === "overlay";
const isWallpaperSwitchable = backgroundWallpaper.switchable ?? true;
---
<Layout title={title} description={description}>
{(isWallpaperSwitchable || isOverlayMode) && (
<OverlayWallpaper
config={{
src: {
desktop:
typeof backgroundImages.desktop === "string"
? backgroundImages.desktop
: "",
mobile:
typeof backgroundImages.mobile === "string"
? backgroundImages.mobile
: "",
},
zIndex: backgroundWallpaper.overlay?.zIndex,
opacity: backgroundWallpaper.overlay?.opacity,
blur: backgroundWallpaper.overlay?.blur,
}}
className={isOverlayMode ? undefined : "hidden opacity-0"}
/>
)}
<slot slot="head" name="head" />
<div
id="admin-top-row"
class:list={[
"z-50 pointer-events-none relative transition-all duration-700 mx-auto",
siteConfig.navbar.widthFull ? "" : "max-w-(--page-width) px-0 md:px-4",
]}
>
<div id="navbar-wrapper" class="pointer-events-auto sticky top-0 transition-all">
<Navbar />
</div>
</div>
<section class="relative z-20 w-full px-2 pt-6 md:px-4 md:pt-8">
<div class="mx-auto max-w-(--page-width)">
<div class="card-base admin-hero overflow-hidden">
<div class="admin-hero-frame">
{bannerImage ? (
<ImageWrapper
src={bannerImage}
alt="Admin banner image"
class="admin-hero-media absolute inset-0 h-full w-full"
loading="eager"
fetchpriority="high"
layout="none"
widths={[1280, 1920]}
sizes="100vw"
/>
) : (
<div class="admin-hero-fallback absolute inset-0" />
)}
<div class="absolute inset-0 admin-hero-overlay" />
<div class="absolute inset-0 admin-hero-grid gap-5 p-6 text-white md:p-8">
<div class="admin-hero-copy flex max-w-3xl flex-col gap-4">
<div class="inline-flex w-fit items-center gap-2 rounded-full bg-white/15 px-3 py-1 text-sm font-medium backdrop-blur-md">
<span class="h-2.5 w-2.5 rounded-full bg-[oklch(0.75_0.14_var(--hue))]" />
Firefly Admin
</div>
<div class="max-w-3xl">
<h1 class="banner-title text-3xl font-bold md:text-5xl">
博客后台管理
</h1>
<p class="banner-subtitle mt-3 max-w-2xl text-sm text-white/85 md:text-lg">
统一管理站点配置、文章、图片与重建状态,界面风格和前台博客保持一致。
</p>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<main class="relative z-30 -mt-5 w-full px-2 pb-10 pt-0 md:-mt-6 md:px-4">
<div class="mx-auto max-w-(--page-width)">
<slot />
</div>
</main>
</Layout>
<style>
#admin-top-row {
height: auto;
}
.admin-hero-overlay {
background:
linear-gradient(135deg, rgb(9 23 30 / 0.86), rgb(18 38 48 / 0.56)),
linear-gradient(180deg, rgb(0 0 0 / 0.12), rgb(0 0 0 / 0.42));
}
.admin-hero-frame {
position: relative;
height: clamp(15rem, 26vw, 20rem);
}
.admin-hero-media {
position: absolute;
inset: 0;
}
.admin-hero :global(picture),
.admin-hero :global(img[data-astro-image]),
.admin-hero :global(img) {
display: block;
width: 100%;
height: 100% !important;
max-width: none;
object-fit: cover;
}
.admin-hero-fallback {
background:
radial-gradient(circle at top right, rgb(255 255 255 / 0.18), transparent 36%),
linear-gradient(135deg, oklch(0.32 0.06 calc(var(--hue) * 1deg)), oklch(0.42 0.08 calc(var(--hue) * 1deg)));
}
.admin-hero-grid {
display: flex;
align-items: flex-start;
}
.admin-hero-copy {
padding-top: clamp(0.5rem, 2vw, 1.25rem);
}
@media (max-width: 959px) {
.admin-hero-frame {
height: auto;
min-height: 14rem;
}
}
</style>