newechoes/src/components/Layout.astro

88 lines
3.1 KiB
Plaintext
Raw Normal View History

2025-03-03 21:16:16 +08:00
---
import "@/styles/global.css";
import Header from "@/components/Header.astro";
import Footer from "@/components/Footer.astro";
import { ICP, PSB_ICP, PSB_ICP_URL, SITE_NAME, SITE_DESCRIPTION } from "@/consts";
2025-03-08 18:16:42 +08:00
// 定义Props接口
interface Props {
title?: string;
description?: string;
date?: Date;
author?: string;
tags?: string[];
image?: string;
}
// 获取完整的 URL
const canonicalURL = new URL(Astro.url.pathname, Astro.site);
// 从props中获取页面特定信息
const { title = SITE_NAME, description = SITE_DESCRIPTION, date, author, tags, image } = Astro.props;
2025-03-03 21:16:16 +08:00
---
<!doctype html>
2025-03-08 18:16:42 +08:00
<html lang="zh-CN" class="m-0 w-full h-full">
2025-03-03 21:16:16 +08:00
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width" />
<meta name="referrer" content="no-referrer" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="generator" content={Astro.generator} />
2025-03-08 18:16:42 +08:00
<!-- 基本元数据 -->
<title>{title}</title>
<meta name="description" content={description || `${SITE_NAME} - 个人博客`} />
<link rel="canonical" href={canonicalURL} />
<!-- Open Graph / Facebook -->
<meta property="og:type" content="article" />
<meta property="og:url" content={canonicalURL} />
<meta property="og:title" content={title} />
<meta property="og:description" content={description || `${SITE_NAME} - 个人博客`} />
{image && <meta property="og:image" content={new URL(image, Astro.site)} />}
<!-- Twitter -->
<meta property="twitter:card" content="summary_large_image" />
<meta property="twitter:url" content={canonicalURL} />
<meta property="twitter:title" content={title} />
<meta property="twitter:description" content={description || `${SITE_NAME} - 个人博客`} />
{image && <meta property="twitter:image" content={new URL(image, Astro.site)} />}
<!-- 文章特定元数据 -->
{date && <meta property="article:published_time" content={date.toISOString()} />}
{author && <meta name="author" content={author} />}
{tags && tags.map(tag => (
<meta property="article:tag" content={tag} />
))}
2025-03-03 21:16:16 +08:00
<script is:inline>
// 立即执行主题初始化,并防止变量重复声明
(function() {
// 检查变量是否已存在
if (typeof window.__themeInitDone === 'undefined') {
// 设置标志,表示初始化已完成
window.__themeInitDone = true;
const systemTheme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
const savedTheme = typeof localStorage !== 'undefined' ? localStorage.getItem('theme') : null;
const theme = savedTheme || systemTheme;
// 立即设置文档主题
document.documentElement.dataset.theme = theme;
// 将主题信息存储在全局变量中,以便 React 组件可以立即访问
window.__THEME_DATA__ = {
currentTheme: theme,
systemTheme: systemTheme
};
2025-03-03 21:16:16 +08:00
}
})();
</script>
</head>
<body class="m-0 w-full h-full bg-gray-50 dark:bg-dark-bg flex flex-col min-h-screen">
<Header />
2025-03-08 18:16:42 +08:00
<main class="pt-16 flex-grow">
2025-03-03 21:16:16 +08:00
<slot />
</main>
2025-03-08 18:16:42 +08:00
<Footer icp={ICP} psbIcp={PSB_ICP} psbIcpUrl={PSB_ICP_URL} />
2025-03-03 21:16:16 +08:00
</body>
</html>