131 lines
3.8 KiB
Plaintext
131 lines
3.8 KiB
Plaintext
---
|
|
import "../styles/global.css";
|
|
import packageJson from "../../package.json";
|
|
import { contactLinks, navItems, site } from "../data/site";
|
|
|
|
interface Props {
|
|
title?: string;
|
|
}
|
|
|
|
const { title = site.title } = Astro.props;
|
|
const buildTime = new Intl.DateTimeFormat("zh-CN", {
|
|
timeZone: "Asia/Shanghai",
|
|
year: "numeric",
|
|
month: "2-digit",
|
|
day: "2-digit",
|
|
hour: "2-digit",
|
|
minute: "2-digit",
|
|
second: "2-digit",
|
|
hour12: false
|
|
}).format(new Date());
|
|
---
|
|
|
|
<!doctype html>
|
|
<html lang="zh-CN">
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
<title>{title}</title>
|
|
<link
|
|
rel="stylesheet"
|
|
href="https://cdn.jsdelivr.net/npm/@fancyapps/ui@5.0/dist/fancybox/fancybox.css"
|
|
/>
|
|
<link
|
|
rel="stylesheet"
|
|
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css"
|
|
/>
|
|
</head>
|
|
<body>
|
|
<header class="site-header" aria-label="网站导航">
|
|
<a class="brand" href="/">{site.className}</a>
|
|
<button
|
|
class="nav-toggle"
|
|
type="button"
|
|
aria-label="打开菜单"
|
|
aria-controls="site-nav"
|
|
aria-expanded="false"
|
|
>
|
|
<span aria-hidden="true"></span>
|
|
<span aria-hidden="true"></span>
|
|
<span aria-hidden="true"></span>
|
|
</button>
|
|
<nav class="nav" id="site-nav">
|
|
{navItems.map((item) => <a href={item.href}>{item.label}</a>)}
|
|
</nav>
|
|
</header>
|
|
|
|
<slot />
|
|
|
|
<footer class="site-footer">
|
|
<p>{site.footer}</p>
|
|
<p class="footer-meta">v{packageJson.version} · 构建于 {buildTime}</p>
|
|
<nav class="footer-contacts" aria-label="联系方式">
|
|
{
|
|
contactLinks.map((item) => (
|
|
<a
|
|
href={item.href}
|
|
class:list={[item.qrImage && "has-qr"]}
|
|
aria-label={item.label}
|
|
title={item.label}
|
|
target={item.href.startsWith("http") ? "_blank" : undefined}
|
|
rel={item.href.startsWith("http") ? "noreferrer" : undefined}
|
|
>
|
|
<i class={item.icon} aria-hidden="true"></i>
|
|
<span>{item.label}</span>
|
|
{
|
|
item.qrImage && (
|
|
<span class="contact-qr" aria-hidden="true">
|
|
<img src={item.qrImage} alt="" loading="lazy" />
|
|
<small>{item.label}</small>
|
|
</span>
|
|
)
|
|
}
|
|
</a>
|
|
))
|
|
}
|
|
</nav>
|
|
</footer>
|
|
<script>
|
|
const header = document.querySelector(".site-header");
|
|
const toggle = document.querySelector(".nav-toggle");
|
|
const nav = document.querySelector("#site-nav");
|
|
|
|
if (header && toggle && nav) {
|
|
const closeMenu = () => {
|
|
header.classList.remove("is-open");
|
|
toggle.setAttribute("aria-expanded", "false");
|
|
toggle.setAttribute("aria-label", "打开菜单");
|
|
};
|
|
|
|
toggle.addEventListener("click", () => {
|
|
const isOpen = header.classList.toggle("is-open");
|
|
toggle.setAttribute("aria-expanded", String(isOpen));
|
|
toggle.setAttribute("aria-label", isOpen ? "关闭菜单" : "打开菜单");
|
|
});
|
|
|
|
nav.addEventListener("click", (event) => {
|
|
if (event.target instanceof HTMLAnchorElement) {
|
|
closeMenu();
|
|
}
|
|
});
|
|
|
|
window.addEventListener("resize", () => {
|
|
if (window.matchMedia("(min-width: 821px)").matches) {
|
|
closeMenu();
|
|
}
|
|
});
|
|
}
|
|
</script>
|
|
<script
|
|
is:inline
|
|
src="https://cdn.jsdelivr.net/npm/@fancyapps/ui@5.0/dist/fancybox/fancybox.umd.js"
|
|
></script>
|
|
<script is:inline>
|
|
window.Fancybox?.bind("[data-fancybox]", {
|
|
animated: true,
|
|
dragToClose: true
|
|
});
|
|
</script>
|
|
</body>
|
|
</html>
|