mirror of
https://github.com/afoim/fuwari.git
synced 2026-01-31 09:03:18 +08:00
- 更新Cookie Consent脚本以动态适应暗色/亮色主题
- 添加CSS类切换功能,当文档主题变化时自动更新Cookie Consent界面
- 标记Cookie Consent相关资源为持久化,防止页面切换时被清理
- 优化Google Adsense脚本的格式和属性
- 添加@types/hast类型依赖以支持相关功能 53e134f106
1054 lines
133 KiB
HTML
1054 lines
133 KiB
HTML
<!DOCTYPE html><html lang="zh-CN" class="bg-[var(--page-bg)] transition text-[12px] md:text-[16px] dark" data-overlayscrollbars-initialize data-astro-cid-sckkx6r4 style="--bannerOffset: 15vh;--banner-height-home: 65vh;--banner-height: 35vh;--configHue: 361;--page-width: 75rem;--bg-url: url(/random/h);--bg-enable: 1;--bg-position: center;--bg-size: cover;--bg-repeat: no-repeat;--bg-attachment: fixed;--bg-opacity: 1;--configHue: 361;"> <!-- 手机端适配 --> <head><title>第 11 页 - AcoFork Blog</title><meta charset="UTF-8"><meta name="description" content="分享网络技术、服务器部署、内网穿透、静态网站搭建、CDN优化、容器化部署等技术教程与实践经验的个人技术博客,专注于云原生、无服务器架构和前后端开发,作者为afoim/二叉树树"><meta name="author" content="二叉树树"><meta name="keywords" content><meta property="og:site_name" content="AcoFork Blog"><meta property="og:url" content="https://blog.acofork.com/11/"><meta property="og:title" content="第 11 页 - AcoFork Blog"><meta property="og:description" content="分享网络技术、服务器部署、内网穿透、静态网站搭建、CDN优化、容器化部署等技术教程与实践经验的个人技术博客,专注于云原生、无服务器架构和前后端开发,作者为afoim/二叉树树"><meta property="og:type" content="website"><meta name="twitter:card" content="summary_large_image"><meta property="twitter:url" content="https://blog.acofork.com/11/"><meta name="twitter:title" content="第 11 页 - AcoFork Blog"><meta name="twitter:description" content="分享网络技术、服务器部署、内网穿透、静态网站搭建、CDN优化、容器化部署等技术教程与实践经验的个人技术博客,专注于云原生、无服务器架构和前后端开发,作者为afoim/二叉树树"><meta name="viewport" content="width=device-width"><meta name="generator" content="Astro v5.7.9"><link rel="preconnect" href="https://pic1.acofork.com"><link rel="preconnect" href="https://umami.acofork.com"><link rel="preconnect" href="https://support.nodeget.com"><script src="/js/umami-share.js" defer></script><script data-swup-ignore-script src="https://pic1.acofork.com/random.js" defer></script><link rel="icon" href="https://q2.qlogo.cn/headimg_dl?dst_uin=2726730791&spec=0"><!-- Set the theme before the page is rendered to avoid a flash --><script>(function(){const DEFAULT_THEME = "auto";
|
||
const LIGHT_MODE = "light";
|
||
const DARK_MODE = "dark";
|
||
const AUTO_MODE = "auto";
|
||
const BANNER_HEIGHT_EXTEND = 30;
|
||
const PAGE_WIDTH = 75;
|
||
const configHue = 361;
|
||
const forceDarkMode = false;
|
||
|
||
// Force dark mode if configured
|
||
if (forceDarkMode) {
|
||
document.documentElement.classList.add('dark');
|
||
localStorage.setItem('theme', DARK_MODE);
|
||
} else {
|
||
// Load the theme from local storage
|
||
const theme = localStorage.getItem('theme') || DARK_MODE;
|
||
switch (theme) {
|
||
case LIGHT_MODE:
|
||
document.documentElement.classList.remove('dark');
|
||
break
|
||
case DARK_MODE:
|
||
document.documentElement.classList.add('dark');
|
||
break
|
||
case AUTO_MODE:
|
||
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
||
document.documentElement.classList.add('dark');
|
||
} else {
|
||
document.documentElement.classList.remove('dark');
|
||
}
|
||
}
|
||
}
|
||
|
||
// Load the hue from local storage
|
||
const hue = localStorage.getItem('hue') || configHue;
|
||
document.documentElement.style.setProperty('--hue', hue);
|
||
|
||
// calculate the --banner-height-extend, which needs to be a multiple of 4 to avoid blurry text
|
||
let offset = Math.floor(window.innerHeight * (BANNER_HEIGHT_EXTEND / 100));
|
||
offset = offset - offset % 4;
|
||
document.documentElement.style.setProperty('--banner-height-extend', `${offset}px`);
|
||
})();</script><link rel="alternate" type="application/rss+xml" title="二叉树树" href="https://blog.acofork.com/rss.xml"><link rel="stylesheet" href="/_astro/Layout.BuewHHUq.css">
|
||
<link rel="stylesheet" href="/_astro/Layout.Ds13mcav.css">
|
||
<link rel="stylesheet" href="/_astro/_page_.Duy76CKh.css">
|
||
<link rel="stylesheet" href="/_astro/_page_.DupG3mc-.css">
|
||
<link rel="stylesheet" href="/_astro/_page_.BYnNTCmG.css">
|
||
<link rel="stylesheet" href="/_astro/_slug_.Bf2USRy1.css">
|
||
<style>.donate-card[data-astro-cid-3z6uernf]{display:flex;flex-direction:column;border-radius:.5rem;border-width:1px;border-color:#0000001a;background-color:var(--card-bg);padding:1rem;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.donate-card[data-astro-cid-3z6uernf]:hover{border-color:#0003}.donate-card[data-astro-cid-3z6uernf]:is(.dark *){border-color:#ffffff1a}.donate-card[data-astro-cid-3z6uernf]:hover:is(.dark *){border-color:#fff3}.donate-card[data-astro-cid-3z6uernf]{backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px)}.support-card[data-astro-cid-3z6uernf]{border-radius:.5rem;border-width:1px;border-color:#0000001a;background-color:var(--card-bg);padding:1rem;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.support-card[data-astro-cid-3z6uernf]:hover{border-color:#0003;background-color:#0000000d}.support-card[data-astro-cid-3z6uernf]:is(.dark *){border-color:#ffffff1a}.support-card[data-astro-cid-3z6uernf]:hover:is(.dark *){border-color:#fff3;background-color:#ffffff0d}.support-card[data-astro-cid-3z6uernf]{backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px)}.qr-code-placeholder[data-astro-cid-3z6uernf]{text-align:center}.sponsors-section[data-astro-cid-3z6uernf]{margin-top:1.5rem}.sponsors-grid[data-astro-cid-3z6uernf]{display:grid;grid-template-columns:repeat(1,minmax(0,1fr));gap:1rem}@media (min-width: 768px){.sponsors-grid[data-astro-cid-3z6uernf]{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (min-width: 1024px){.sponsors-grid[data-astro-cid-3z6uernf]{grid-template-columns:repeat(3,minmax(0,1fr))}}.sponsor-placeholder[data-astro-cid-3z6uernf]{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.2s}.sponsor-placeholder[data-astro-cid-3z6uernf]:hover{--tw-scale-x: 1.05;--tw-scale-y: 1.05;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.sponsor-card[data-astro-cid-3z6uernf]{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.2s}.sponsor-card[data-astro-cid-3z6uernf]:hover{--tw-scale-x: 1.05;--tw-scale-y: 1.05;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));--tw-shadow: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1);--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}
|
||
.friend-card[data-astro-cid-spp2p3no]{display:flex;flex-direction:column;gap:.25rem;border-radius:.5rem;border-width:1px;border-color:#0000001a;background-color:var(--card-bg);padding:1rem}.friend-card[data-astro-cid-spp2p3no]:hover{border-color:#0003;background-color:#0000000d}.friend-card[data-astro-cid-spp2p3no]:is(.dark *){border-color:#ffffff1a}.friend-card[data-astro-cid-spp2p3no]:hover:is(.dark *){border-color:#fff3;background-color:#ffffff0d}.friend-card[data-astro-cid-spp2p3no]{transition-property:background-color,border-color,scale;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s;transform:translateZ(0)}.friend-card[data-astro-cid-spp2p3no]:active{scale:.98;background-color:var(--btn-regular-bg-active)}.friend-card[data-astro-cid-spp2p3no]:hover{background-color:var(--btn-regular-bg-hover)}.friend-card[data-astro-cid-spp2p3no]:hover .font-bold[data-astro-cid-spp2p3no]{color:var(--btn-content)}.friend-card[data-astro-cid-spp2p3no]:hover .text-sm[data-astro-cid-spp2p3no]{--tw-text-opacity: 1;color:rgb(55 65 81 / var(--tw-text-opacity, 1))}.friend-card[data-astro-cid-spp2p3no]:hover .text-sm[data-astro-cid-spp2p3no]:is(.dark *){--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.friend-card[data-astro-cid-spp2p3no] .font-bold[data-astro-cid-spp2p3no],.friend-card[data-astro-cid-spp2p3no] .text-sm[data-astro-cid-spp2p3no]{transition-property:color;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}
|
||
input.svelte-wkye0l:focus{outline:0}.search-panel.svelte-wkye0l{background-color:var(--float-panel-bg-opaque);max-height:calc(100vh - 100px);overflow-y:auto;scrollbar-width:none;-ms-overflow-style:none}.search-panel.svelte-wkye0l::-webkit-scrollbar{display:none}#display-setting.svelte-1rks09j input[type=number]:where(.svelte-1rks09j){-moz-appearance:textfield}#display-setting.svelte-1rks09j input[type=number]:where(.svelte-1rks09j)::-webkit-inner-spin-button,#display-setting.svelte-1rks09j input[type=number]:where(.svelte-1rks09j)::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}#display-setting.svelte-1rks09j input[type=range]:where(.svelte-1rks09j){-webkit-appearance:none;height:1.5rem;background-color:transparent;transition:background-image .15s ease-in-out}#display-setting.svelte-1rks09j input[type=range]:where(.svelte-1rks09j):not(#colorSlider){background-image:linear-gradient(to right,var(--primary) 0%,var(--primary) var(--value-percent),transparent var(--value-percent),transparent 100%)}#display-setting.svelte-1rks09j input[type=range]:where(.svelte-1rks09j)::-webkit-slider-thumb{-webkit-appearance:none;height:0;width:0;background:transparent;box-shadow:none;border:none}#display-setting.svelte-1rks09j input[type=range]:where(.svelte-1rks09j)::-moz-range-thumb{-webkit-appearance:none;height:0;width:0;background:transparent;box-shadow:none;border:none}#display-setting.svelte-1rks09j input[type=range]:where(.svelte-1rks09j)::-ms-thumb{-webkit-appearance:none;height:0;width:0;background:transparent;box-shadow:none;border:none}#display-setting.svelte-1rks09j #colorSlider:where(.svelte-1rks09j){background-image:var(--color-selection-bar)}#display-setting.svelte-1rks09j #colorSlider:where(.svelte-1rks09j)::-webkit-slider-thumb{-webkit-appearance:none;height:1rem;width:.5rem;border-radius:.125rem;background:#ffffffb3;box-shadow:none;margin-top:0;transform:none;-webkit-transition:background .15s;transition:background .15s}#display-setting.svelte-1rks09j #colorSlider:where(.svelte-1rks09j)::-webkit-slider-thumb:hover{background:#fffc}#display-setting.svelte-1rks09j #colorSlider:where(.svelte-1rks09j)::-webkit-slider-thumb:active{background:#fff9}#display-setting.svelte-1rks09j #colorSlider:where(.svelte-1rks09j)::-moz-range-thumb{-webkit-appearance:none;height:1rem;width:.5rem;border-radius:.125rem;border-width:0;background:#ffffffb3;box-shadow:none;transform:none;-moz-transition:background .15s;transition:background .15s}#display-setting.svelte-1rks09j #colorSlider:where(.svelte-1rks09j)::-moz-range-thumb:hover{background:#fffc}#display-setting.svelte-1rks09j #colorSlider:where(.svelte-1rks09j)::-moz-range-thumb:active{background:#fff9}#display-setting.svelte-1rks09j #colorSlider:where(.svelte-1rks09j)::-ms-thumb{-webkit-appearance:none;height:1rem;width:.5rem;border-radius:.125rem;background:#ffffffb3;box-shadow:none;transform:none;-ms-transition:background .15s;transition:background .15s}#display-setting.svelte-1rks09j #colorSlider:where(.svelte-1rks09j)::-ms-thumb:hover{background:#fffc}#display-setting.svelte-1rks09j #colorSlider:where(.svelte-1rks09j)::-ms-thumb:active{background:#fff9}#display-setting.svelte-1rks09j .toggle-switch:where(.svelte-1rks09j){-webkit-appearance:none;-moz-appearance:none;appearance:none;width:3rem;height:1.5rem;background:var(--btn-regular-bg);border-radius:999px;position:relative;cursor:pointer;transition:background .3s}#display-setting.svelte-1rks09j .toggle-switch:where(.svelte-1rks09j):after{content:"";position:absolute;top:.25rem;left:.25rem;width:1rem;height:1rem;background:var(--btn-content);border-radius:50%;transition:transform .3s}#display-setting.svelte-1rks09j .toggle-switch:where(.svelte-1rks09j):checked{background:var(--primary)}#display-setting.svelte-1rks09j .toggle-switch:where(.svelte-1rks09j):checked:after{transform:translate(1.5rem);background:#fff}
|
||
</style><script type="module" src="/_astro/page.G51m6u_A.js"></script></head> <body class=" min-h-screen transition " data-overlayscrollbars-initialize data-astro-cid-sckkx6r4 style="--bannerOffset: 15vh;--banner-height-home: 65vh;--banner-height: 35vh;--configHue: 361;--page-width: 75rem;--bg-url: url(/random/h);--bg-enable: 1;--bg-position: center;--bg-size: cover;--bg-repeat: no-repeat;--bg-attachment: fixed;--bg-opacity: 1;--configHue: 361;"> <!-- Cookie Consent by TermsFeed https://www.TermsFeed.com --> <script data-swup-ignore-script type="text/javascript" src="https://www.termsfeed.com/public/cookie-consent/4.2.0/cookie-consent.js" charset="UTF-8"></script> <script data-swup-ignore-script type="text/javascript" charset="UTF-8">
|
||
(function () {
|
||
const getStoredTheme = () => {
|
||
try {
|
||
const theme = localStorage.getItem("theme");
|
||
return theme === "light" || theme === "dark" || theme === "auto" ? theme : null;
|
||
} catch {
|
||
return null;
|
||
}
|
||
};
|
||
|
||
const getHue = () => {
|
||
try {
|
||
const stored = localStorage.getItem("hue");
|
||
if (stored) return Number.parseInt(stored);
|
||
} catch {
|
||
}
|
||
const configCarrier = document.getElementById("config-carrier");
|
||
const fallback = "250";
|
||
const raw = configCarrier?.dataset.hue || fallback;
|
||
return Number.parseInt(raw);
|
||
};
|
||
|
||
const getPalette = () => {
|
||
const theme = getStoredTheme();
|
||
if (theme === "dark") return "dark";
|
||
if (theme === "light") return "light";
|
||
if (document.documentElement.classList.contains("dark")) return "dark";
|
||
return window.matchMedia?.("(prefers-color-scheme: dark)")?.matches ? "dark" : "light";
|
||
};
|
||
|
||
const baseConfig = {
|
||
notice_banner_type: "simple",
|
||
consent_type: "express",
|
||
language: "en",
|
||
page_load_consent_levels: ["strictly-necessary"],
|
||
notice_banner_reject_button_hide: false,
|
||
preferences_center_close_button_hide: false,
|
||
page_refresh_confirmation_buttons: false,
|
||
website_name: "AcoFork Blog",
|
||
website_privacy_policy_url: "https://blog.acofork.com/posts/privacy-policy/",
|
||
};
|
||
|
||
const markCookieConsentHeadAssetsPersistent = () => {
|
||
const attr = "data-swup-theme";
|
||
const candidates = document.head?.querySelectorAll?.("link[rel='stylesheet'][href], style, script[src]") ?? [];
|
||
candidates.forEach(el => {
|
||
if (!(el instanceof HTMLElement)) return;
|
||
if (el.hasAttribute(attr)) return;
|
||
|
||
const tag = el.tagName.toLowerCase();
|
||
if (tag === "link") {
|
||
const href = el.getAttribute("href") || "";
|
||
if (/termsfeed|cookie-consent|cookieconsent/i.test(href)) el.setAttribute(attr, "");
|
||
return;
|
||
}
|
||
if (tag === "script") {
|
||
const src = el.getAttribute("src") || "";
|
||
if (/termsfeed|cookie-consent|cookieconsent/i.test(src)) el.setAttribute(attr, "");
|
||
return;
|
||
}
|
||
if (tag === "style") {
|
||
const css = el.textContent || "";
|
||
if (
|
||
/termsfeed-com---/.test(css) ||
|
||
/\bcc-(nb|pc|cp)\b/.test(css) ||
|
||
/\bcc_(dialog|preferences|cp|nb|overlay|banner|modal)\b/.test(css) ||
|
||
/cookie\s*consent|cookieconsent/i.test(css)
|
||
) {
|
||
el.setAttribute(attr, "");
|
||
}
|
||
}
|
||
});
|
||
};
|
||
|
||
let scheduled = false;
|
||
const scheduleApplyPalette = () => {
|
||
if (scheduled) return;
|
||
scheduled = true;
|
||
requestAnimationFrame(() => {
|
||
scheduled = false;
|
||
const palette = getPalette();
|
||
document
|
||
.querySelectorAll(
|
||
".termsfeed-com---palette-dark, .termsfeed-com---palette-light",
|
||
)
|
||
.forEach(el => {
|
||
el.classList.remove("termsfeed-com---palette-dark", "termsfeed-com---palette-light");
|
||
el.classList.add(`termsfeed-com---palette-${palette}`);
|
||
});
|
||
document
|
||
.querySelectorAll(
|
||
".cc_dialog, .cc_preferences, .cc_cp, .cc_nb, .cc_overlay, .cc_banner, .cc_modal",
|
||
)
|
||
.forEach(el => {
|
||
el.classList.remove("dark", "light");
|
||
el.classList.add(palette);
|
||
el.style.setProperty("--hue", String(getHue()));
|
||
});
|
||
});
|
||
};
|
||
|
||
const runCookieConsent = () => {
|
||
const cc = window.cookieconsent;
|
||
if (!cc || typeof cc.run !== "function") return;
|
||
cc.run({ ...baseConfig, palette: getPalette() });
|
||
scheduleApplyPalette();
|
||
};
|
||
|
||
document.addEventListener("DOMContentLoaded", () => {
|
||
const ensureOverrides = () => {
|
||
if (document.getElementById("cookie-consent-overrides")) return;
|
||
const style = document.createElement("style");
|
||
style.id = "cookie-consent-overrides";
|
||
style.textContent = `
|
||
.termsfeed-com---nb a, .termsfeed-com---pc a, .termsfeed-com---cp a { color: oklch(0.75 0.14 var(--hue)); }
|
||
.termsfeed-com---palette-dark .cc-nb-okagree, .termsfeed-com---palette-light .cc-nb-okagree { background-color: oklch(0.7 0.14 var(--hue)); border-color: oklch(0.7 0.14 var(--hue)); }
|
||
.termsfeed-com---palette-dark .cc-cp-footer-save, .termsfeed-com---palette-light .cc-cp-footer-save { background-color: oklch(0.7 0.14 var(--hue)); border-color: oklch(0.7 0.14 var(--hue)); }
|
||
`.trim();
|
||
document.head.appendChild(style);
|
||
};
|
||
|
||
ensureOverrides();
|
||
markCookieConsentHeadAssetsPersistent();
|
||
new MutationObserver(markCookieConsentHeadAssetsPersistent).observe(document.head, {
|
||
childList: true,
|
||
subtree: true,
|
||
});
|
||
|
||
runCookieConsent();
|
||
|
||
new MutationObserver(scheduleApplyPalette).observe(document.documentElement, {
|
||
attributes: true,
|
||
attributeFilter: ["class", "style"],
|
||
});
|
||
|
||
new MutationObserver(scheduleApplyPalette).observe(document.body, {
|
||
childList: true,
|
||
subtree: true,
|
||
});
|
||
});
|
||
})();
|
||
</script> <!-- Basic Analytics --> <!-- Umami --> <script type="text/plain" data-cookie-consent="strictly-necessary" defer src="https://umami.acofork.com/script.js" data-website-id="5d710dbd-3a2e-43e3-a553-97b415090c63" data-swup-ignore-script></script> <!-- end of Basic Analytics--> <!-- Google Analytics --> <!-- Google tag (gtag.js) --> <script type="text/plain" data-cookie-consent="tracking" async src="https://www.googletagmanager.com/gtag/js?id=G-YG02LLPGWC" data-swup-ignore-script></script> <script type="text/plain" data-cookie-consent="tracking">
|
||
window.dataLayer = window.dataLayer || [];
|
||
function gtag(){dataLayer.push(arguments);}
|
||
gtag('js', new Date());
|
||
gtag('config', 'G-YG02LLPGWC');
|
||
</script> <!-- end of Google Analytics--> <!-- Microsoft Clarity --> <script type="text/plain" data-cookie-consent="tracking" data-swup-ignore-script>
|
||
(function(c,l,a,r,i,t,y){
|
||
c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)};
|
||
t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i;
|
||
y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y);
|
||
})(window, document, "clarity", "script", "v94yrasi99");
|
||
</script> <!-- end of Site Experience & Interaction Analytics--> <!-- Google Adsense --> <script type="text/plain" data-cookie-consent="targeting" async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-1683686345039700" data-swup-ignore-script crossorigin="anonymous"></script> <!-- end of Google Adsense--> <noscript>Free cookie consent management tool by <a href="https://www.termsfeed.com/" data-astro-cid-sckkx6r4 style="--bannerOffset: 15vh;--banner-height-home: 65vh;--banner-height: 35vh;--configHue: 361;--page-width: 75rem;--bg-url: url(/random/h);--bg-enable: 1;--bg-position: center;--bg-size: cover;--bg-repeat: no-repeat;--bg-attachment: fixed;--bg-opacity: 1;--configHue: 361;">TermsFeed</a></noscript> <!-- End Cookie Consent by TermsFeed https://www.TermsFeed.com --> <noscript> <style>
|
||
#bg-box {
|
||
opacity: 1 !important;
|
||
}
|
||
</style> </noscript> <div id="bg-box" data-astro-cid-sckkx6r4 style="--bannerOffset: 15vh;--banner-height-home: 65vh;--banner-height: 35vh;--configHue: 361;--page-width: 75rem;--bg-url: url(/random/h);--bg-enable: 1;--bg-position: center;--bg-size: cover;--bg-repeat: no-repeat;--bg-attachment: fixed;--bg-opacity: 1;--configHue: 361;"></div> <div id="config-carrier" data-hue="361"></div> <div id="new-post-notification" class="fixed bottom-4 right-4 z-50 flex flex-col items-end pointer-events-none" data-astro-cid-6yyxny4o> <!-- Minimized State (Bell Icon) --> <button id="notification-minimized" class="pointer-events-auto bg-[var(--card-bg)] border border-[var(--primary)] text-[var(--primary)] p-3 rounded-full shadow-lg transform translate-y-20 opacity-0 transition-all duration-500 ease-[cubic-bezier(0.34,1.56,0.64,1)] hover:scale-110 active:scale-95 flex items-center justify-center relative group" data-astro-cid-6yyxny4o> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" data-astro-cid-6yyxny4o><path d="M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9" data-astro-cid-6yyxny4o></path><path d="M10.3 21a1.94 1.94 0 0 0 3.4 0" data-astro-cid-6yyxny4o></path></svg> <span id="notification-dot" class="absolute top-0 right-0 w-3 h-3 bg-red-500 rounded-full border-2 border-[var(--card-bg)] hidden animate-pulse" data-astro-cid-6yyxny4o></span> </button> <!-- Expanded State (Panel) --> <div id="notification-panel" class="pointer-events-auto bg-[var(--card-bg)] border border-[var(--primary)] rounded-xl shadow-lg p-4 max-w-[90vw] w-80 transform translate-y-4 opacity-0 scale-95 origin-bottom-right transition-all duration-300 hidden absolute bottom-16 right-0 sm:bottom-14" data-astro-cid-6yyxny4o> <div class="flex items-center justify-between mb-3" data-astro-cid-6yyxny4o> <div class="flex items-center gap-2 text-[var(--primary)]" data-astro-cid-6yyxny4o> <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" data-astro-cid-6yyxny4o><path d="M4 11a9 9 0 0 1 9 9" data-astro-cid-6yyxny4o></path><path d="M4 4a16 16 0 0 1 16 16" data-astro-cid-6yyxny4o></path><circle cx="5" cy="19" r="1" data-astro-cid-6yyxny4o></circle></svg> <h3 class="font-bold text-black dark:text-white" data-astro-cid-6yyxny4o>发现新文章</h3> </div> <div class="flex items-center gap-1" data-astro-cid-6yyxny4o> <button id="clear-notification" class="text-black/50 dark:text-white/50 hover:text-red-500 transition-colors p-1 rounded-md hover:bg-red-500/10" title="清空通知" data-astro-cid-6yyxny4o> <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" data-astro-cid-6yyxny4o><path d="M3 6h18" data-astro-cid-6yyxny4o></path><path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6" data-astro-cid-6yyxny4o></path><path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2" data-astro-cid-6yyxny4o></path></svg> </button> <button id="minimize-notification" class="text-black/50 dark:text-white/50 hover:text-[var(--primary)] transition-colors p-1 rounded-md hover:bg-[var(--primary)]/10" title="隐藏" data-astro-cid-6yyxny4o> <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" data-astro-cid-6yyxny4o><line x1="18" y1="6" x2="6" y2="18" data-astro-cid-6yyxny4o></line><line x1="6" y1="6" x2="18" y2="18" data-astro-cid-6yyxny4o></line></svg> </button> </div> </div> <div id="new-post-list" class="text-sm text-black/80 dark:text-white/80 transition-colors space-y-1 max-h-[60vh] overflow-y-auto overflow-x-hidden custom-scrollbar" data-astro-cid-6yyxny4o></div> </div> </div> <script type="module" src="/_astro/NewPostNotification.astro_astro_type_script_index_0_lang.BVVyTSCq.js"></script> <div id="top-row" class="z-50 pointer-events-none relative transition-all duration-700 max-w-[var(--page-width)] px-4 md:px-4 mx-auto"> <div id="navbar-wrapper" class="pointer-events-auto sticky top-0 transition-all"> <div id="navbar" class="z-50 onload-animation"> <div class="absolute h-8 left-0 right-0 -top-8 bg-[var(--card-bg)] transition"></div> <!-- used for onload animation --> <div class="card-base border border-black/10 dark:border-white/10 !overflow-visible max-w-[var(--page-width)] h-[4.5rem] !rounded-t-none mx-auto flex items-center justify-between px-4"> <a href="/" class="btn-plain scale-animation rounded-lg h-[3.25rem] px-5 font-bold active:scale-95"> <div class="flex flex-row text-[var(--primary)] items-center text-md"> <svg width="1em" height="1em" class="text-[1.75rem] mb-1 mr-2" data-icon="material-symbols:home-outline-rounded"> <symbol id="ai:material-symbols:home-outline-rounded" viewBox="0 0 24 24"><path fill="currentColor" d="M6 19h3v-5q0-.425.288-.712T10 13h4q.425 0 .713.288T15 14v5h3v-9l-6-4.5L6 10zm-2 0v-9q0-.475.213-.9t.587-.7l6-4.5q.525-.4 1.2-.4t1.2.4l6 4.5q.375.275.588.7T20 10v9q0 .825-.588 1.413T18 21h-4q-.425 0-.712-.288T13 20v-5h-2v5q0 .425-.288.713T10 21H6q-.825 0-1.412-.587T4 19m8-6.75"/></symbol><use href="#ai:material-symbols:home-outline-rounded"></use> </svg> AcoFork Blog </div> </a> <div class="hidden md:flex"> <a aria-label="首页" href="/" class="btn-plain scale-animation rounded-lg h-11 font-bold px-5 active:scale-95"> <div class="flex items-center"> 首页 </div> </a><a aria-label="归档" href="/archive/" class="btn-plain scale-animation rounded-lg h-11 font-bold px-5 active:scale-95"> <div class="flex items-center"> 归档 </div> </a><a aria-label="友链" href="/friends/" class="btn-plain scale-animation rounded-lg h-11 font-bold px-5 active:scale-95"> <div class="flex items-center"> 友链 </div> </a><a aria-label="赞助" href="/sponsors/" class="btn-plain scale-animation rounded-lg h-11 font-bold px-5 active:scale-95"> <div class="flex items-center"> 赞助 </div> </a><a aria-label="统计" href="https://umami.acofork.com/share/CdkXbGgZr6ECKOyK" target="_blank" class="btn-plain scale-animation rounded-lg h-11 font-bold px-5 active:scale-95"> <div class="flex items-center"> 统计 <svg width="1em" height="1em" class="text-[0.875rem] transition -translate-y-[1px] ml-1 text-black/[0.2] dark:text-white/[0.2]" data-icon="fa6-solid:arrow-up-right-from-square"> <symbol id="ai:fa6-solid:arrow-up-right-from-square" viewBox="0 0 512 512"><path fill="currentColor" d="M320 0c-17.7 0-32 14.3-32 32s14.3 32 32 32h82.7L201.4 265.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L448 109.3V192c0 17.7 14.3 32 32 32s32-14.3 32-32V32c0-17.7-14.3-32-32-32zM80 32C35.8 32 0 67.8 0 112v320c0 44.2 35.8 80 80 80h320c44.2 0 80-35.8 80-80V320c0-17.7-14.3-32-32-32s-32 14.3-32 32v112c0 8.8-7.2 16-16 16H80c-8.8 0-16-7.2-16-16V112c0-8.8 7.2-16 16-16h112c17.7 0 32-14.3 32-32s-14.3-32-32-32z"/></symbol><use href="#ai:fa6-solid:arrow-up-right-from-square"></use> </svg> </div> </a><a aria-label="监控" href="https://status.acofork.com" target="_blank" class="btn-plain scale-animation rounded-lg h-11 font-bold px-5 active:scale-95"> <div class="flex items-center"> 监控 <svg width="1em" height="1em" viewBox="0 0 512 512" class="text-[0.875rem] transition -translate-y-[1px] ml-1 text-black/[0.2] dark:text-white/[0.2]" data-icon="fa6-solid:arrow-up-right-from-square"> <use href="#ai:fa6-solid:arrow-up-right-from-square"></use> </svg> </div> </a><a aria-label="论坛" href="https://i.2x.nz" target="_blank" class="btn-plain scale-animation rounded-lg h-11 font-bold px-5 active:scale-95"> <div class="flex items-center"> 论坛 <svg width="1em" height="1em" viewBox="0 0 512 512" class="text-[0.875rem] transition -translate-y-[1px] ml-1 text-black/[0.2] dark:text-white/[0.2]" data-icon="fa6-solid:arrow-up-right-from-square"> <use href="#ai:fa6-solid:arrow-up-right-from-square"></use> </svg> </div> </a> </div> <div class="flex"> <!--<SearchPanel client:load>--> <style>astro-island,astro-slot,astro-static-slot{display:contents}</style><script>(()=>{var e=async t=>{await(await t())()};(self.Astro||(self.Astro={})).only=e;window.dispatchEvent(new Event("astro:only"));})();;(()=>{var A=Object.defineProperty;var g=(i,o,a)=>o in i?A(i,o,{enumerable:!0,configurable:!0,writable:!0,value:a}):i[o]=a;var d=(i,o,a)=>g(i,typeof o!="symbol"?o+"":o,a);{let i={0:t=>m(t),1:t=>a(t),2:t=>new RegExp(t),3:t=>new Date(t),4:t=>new Map(a(t)),5:t=>new Set(a(t)),6:t=>BigInt(t),7:t=>new URL(t),8:t=>new Uint8Array(t),9:t=>new Uint16Array(t),10:t=>new Uint32Array(t),11:t=>1/0*t},o=t=>{let[l,e]=t;return l in i?i[l](e):void 0},a=t=>t.map(o),m=t=>typeof t!="object"||t===null?t:Object.fromEntries(Object.entries(t).map(([l,e])=>[l,o(e)]));class y extends HTMLElement{constructor(){super(...arguments);d(this,"Component");d(this,"hydrator");d(this,"hydrate",async()=>{var b;if(!this.hydrator||!this.isConnected)return;let e=(b=this.parentElement)==null?void 0:b.closest("astro-island[ssr]");if(e){e.addEventListener("astro:hydrate",this.hydrate,{once:!0});return}let c=this.querySelectorAll("astro-slot"),n={},h=this.querySelectorAll("template[data-astro-template]");for(let r of h){let s=r.closest(this.tagName);s!=null&&s.isSameNode(this)&&(n[r.getAttribute("data-astro-template")||"default"]=r.innerHTML,r.remove())}for(let r of c){let s=r.closest(this.tagName);s!=null&&s.isSameNode(this)&&(n[r.getAttribute("name")||"default"]=r.innerHTML)}let p;try{p=this.hasAttribute("props")?m(JSON.parse(this.getAttribute("props"))):{}}catch(r){let s=this.getAttribute("component-url")||"<unknown>",v=this.getAttribute("component-export");throw v&&(s+=` (export ${v})`),console.error(`[hydrate] Error parsing props for component ${s}`,this.getAttribute("props"),r),r}let u;await this.hydrator(this)(this.Component,p,n,{client:this.getAttribute("client")}),this.removeAttribute("ssr"),this.dispatchEvent(new CustomEvent("astro:hydrate"))});d(this,"unmount",()=>{this.isConnected||this.dispatchEvent(new CustomEvent("astro:unmount"))})}disconnectedCallback(){document.removeEventListener("astro:after-swap",this.unmount),document.addEventListener("astro:after-swap",this.unmount,{once:!0})}connectedCallback(){if(!this.hasAttribute("await-children")||document.readyState==="interactive"||document.readyState==="complete")this.childrenConnectedCallback();else{let e=()=>{document.removeEventListener("DOMContentLoaded",e),c.disconnect(),this.childrenConnectedCallback()},c=new MutationObserver(()=>{var n;((n=this.lastChild)==null?void 0:n.nodeType)===Node.COMMENT_NODE&&this.lastChild.nodeValue==="astro:end"&&(this.lastChild.remove(),e())});c.observe(this,{childList:!0}),document.addEventListener("DOMContentLoaded",e)}}async childrenConnectedCallback(){let e=this.getAttribute("before-hydration-url");e&&await import(e),this.start()}async start(){let e=JSON.parse(this.getAttribute("opts")),c=this.getAttribute("client");if(Astro[c]===void 0){window.addEventListener(`astro:${c}`,()=>this.start(),{once:!0});return}try{await Astro[c](async()=>{let n=this.getAttribute("renderer-url"),[h,{default:p}]=await Promise.all([import(this.getAttribute("component-url")),n?import(n):()=>()=>{}]),u=this.getAttribute("component-export")||"default";if(!u.includes("."))this.Component=h[u];else{this.Component=h;for(let f of u.split("."))this.Component=this.Component[f]}return this.hydrator=p,this.hydrate},e,this)}catch(n){console.error(`[astro-island] Error hydrating ${this.getAttribute("component-url")}`,n)}}attributeChangedCallback(){this.hydrate()}}d(y,"observedAttributes",["props"]),customElements.get("astro-island")||customElements.define("astro-island",y)}})();</script><astro-island uid="2j02uq" component-url="/_astro/Search.Ciq6IALQ.js" component-export="default" renderer-url="/_astro/client.svelte.B_1DUc79.js" props="{}" ssr client="only" opts="{"name":"Search","value":"svelte"}"></astro-island> <button aria-label="Display Settings" class="btn-plain scale-animation rounded-lg h-11 w-11 active:scale-90" id="display-settings-switch"> <svg width="1em" height="1em" class="text-[1.25rem]" data-icon="material-symbols:palette-outline"> <symbol id="ai:material-symbols:palette-outline" viewBox="0 0 24 24"><path fill="currentColor" d="M12 22q-2.05 0-3.875-.788t-3.187-2.15t-2.15-3.187T2 12q0-2.075.813-3.9t2.2-3.175T8.25 2.788T12.2 2q2 0 3.775.688t3.113 1.9t2.125 2.875T22 11.05q0 2.875-1.75 4.413T16 17h-1.85q-.225 0-.312.125t-.088.275q0 .3.375.863t.375 1.287q0 1.25-.687 1.85T12 22m-5.5-9q.65 0 1.075-.425T8 11.5t-.425-1.075T6.5 10t-1.075.425T5 11.5t.425 1.075T6.5 13m3-4q.65 0 1.075-.425T11 7.5t-.425-1.075T9.5 6t-1.075.425T8 7.5t.425 1.075T9.5 9m5 0q.65 0 1.075-.425T16 7.5t-.425-1.075T14.5 6t-1.075.425T13 7.5t.425 1.075T14.5 9m3 4q.65 0 1.075-.425T19 11.5t-.425-1.075T17.5 10t-1.075.425T16 11.5t.425 1.075T17.5 13M12 20q.225 0 .363-.125t.137-.325q0-.35-.375-.825T11.75 17.3q0-1.05.725-1.675T14.25 15H16q1.65 0 2.825-.962T20 11.05q0-3.025-2.312-5.038T12.2 4Q8.8 4 6.4 6.325T4 12q0 3.325 2.338 5.663T12 20"/></symbol><use href="#ai:material-symbols:palette-outline"></use> </svg> </button> <button aria-label="Menu" name="Nav Menu" class="btn-plain scale-animation rounded-lg w-11 h-11 active:scale-90 md:!hidden" id="nav-menu-switch"> <svg width="1em" height="1em" class="text-[1.25rem]" data-icon="material-symbols:menu-rounded"> <symbol id="ai:material-symbols:menu-rounded" viewBox="0 0 24 24"><path fill="currentColor" d="M4 18q-.425 0-.712-.288T3 17t.288-.712T4 16h16q.425 0 .713.288T21 17t-.288.713T20 18zm0-5q-.425 0-.712-.288T3 12t.288-.712T4 11h16q.425 0 .713.288T21 12t-.288.713T20 13zm0-5q-.425 0-.712-.288T3 7t.288-.712T4 6h16q.425 0 .713.288T21 7t-.288.713T20 8z"/></symbol><use href="#ai:material-symbols:menu-rounded"></use> </svg> </button> </div> <div id="nav-menu-panel" class="float-panel float-panel-closed absolute transition-all fixed right-4 px-2 py-2"> <a href="/" class="group flex justify-between items-center py-2 pl-3 pr-1 rounded-lg gap-8
|
||
hover:bg-[var(--btn-plain-bg-hover)] active:bg-[var(--btn-plain-bg-active)] transition
|
||
"> <div class="transition text-black/75 dark:text-white/75 font-bold group-hover:text-[var(--primary)] group-active:text-[var(--primary)]"> 首页 </div> <svg width="1em" height="1em" class="transition text-[1.25rem] text-[var(--primary)]" data-icon="material-symbols:chevron-right-rounded"> <symbol id="ai:material-symbols:chevron-right-rounded" viewBox="0 0 24 24"><path fill="currentColor" d="M12.6 12L8.7 8.1q-.275-.275-.275-.7t.275-.7t.7-.275t.7.275l4.6 4.6q.15.15.213.325t.062.375t-.062.375t-.213.325l-4.6 4.6q-.275.275-.7.275t-.7-.275t-.275-.7t.275-.7z"/></symbol><use href="#ai:material-symbols:chevron-right-rounded"></use> </svg> </a><a href="/archive/" class="group flex justify-between items-center py-2 pl-3 pr-1 rounded-lg gap-8
|
||
hover:bg-[var(--btn-plain-bg-hover)] active:bg-[var(--btn-plain-bg-active)] transition
|
||
"> <div class="transition text-black/75 dark:text-white/75 font-bold group-hover:text-[var(--primary)] group-active:text-[var(--primary)]"> 归档 </div> <svg width="1em" height="1em" viewBox="0 0 24 24" class="transition text-[1.25rem] text-[var(--primary)]" data-icon="material-symbols:chevron-right-rounded"> <use href="#ai:material-symbols:chevron-right-rounded"></use> </svg> </a><a href="/friends/" class="group flex justify-between items-center py-2 pl-3 pr-1 rounded-lg gap-8
|
||
hover:bg-[var(--btn-plain-bg-hover)] active:bg-[var(--btn-plain-bg-active)] transition
|
||
"> <div class="transition text-black/75 dark:text-white/75 font-bold group-hover:text-[var(--primary)] group-active:text-[var(--primary)]"> 友链 </div> <svg width="1em" height="1em" viewBox="0 0 24 24" class="transition text-[1.25rem] text-[var(--primary)]" data-icon="material-symbols:chevron-right-rounded"> <use href="#ai:material-symbols:chevron-right-rounded"></use> </svg> </a><a href="/sponsors/" class="group flex justify-between items-center py-2 pl-3 pr-1 rounded-lg gap-8
|
||
hover:bg-[var(--btn-plain-bg-hover)] active:bg-[var(--btn-plain-bg-active)] transition
|
||
"> <div class="transition text-black/75 dark:text-white/75 font-bold group-hover:text-[var(--primary)] group-active:text-[var(--primary)]"> 赞助 </div> <svg width="1em" height="1em" viewBox="0 0 24 24" class="transition text-[1.25rem] text-[var(--primary)]" data-icon="material-symbols:chevron-right-rounded"> <use href="#ai:material-symbols:chevron-right-rounded"></use> </svg> </a><a href="https://umami.acofork.com/share/CdkXbGgZr6ECKOyK" class="group flex justify-between items-center py-2 pl-3 pr-1 rounded-lg gap-8
|
||
hover:bg-[var(--btn-plain-bg-hover)] active:bg-[var(--btn-plain-bg-active)] transition
|
||
" target="_blank"> <div class="transition text-black/75 dark:text-white/75 font-bold group-hover:text-[var(--primary)] group-active:text-[var(--primary)]"> 统计 </div> <svg width="1em" height="1em" viewBox="0 0 512 512" class="transition text-[0.75rem] text-black/25 dark:text-white/25 -translate-x-1" data-icon="fa6-solid:arrow-up-right-from-square"> <use href="#ai:fa6-solid:arrow-up-right-from-square"></use> </svg> </a><a href="https://status.acofork.com" class="group flex justify-between items-center py-2 pl-3 pr-1 rounded-lg gap-8
|
||
hover:bg-[var(--btn-plain-bg-hover)] active:bg-[var(--btn-plain-bg-active)] transition
|
||
" target="_blank"> <div class="transition text-black/75 dark:text-white/75 font-bold group-hover:text-[var(--primary)] group-active:text-[var(--primary)]"> 监控 </div> <svg width="1em" height="1em" viewBox="0 0 512 512" class="transition text-[0.75rem] text-black/25 dark:text-white/25 -translate-x-1" data-icon="fa6-solid:arrow-up-right-from-square"> <use href="#ai:fa6-solid:arrow-up-right-from-square"></use> </svg> </a><a href="https://i.2x.nz" class="group flex justify-between items-center py-2 pl-3 pr-1 rounded-lg gap-8
|
||
hover:bg-[var(--btn-plain-bg-hover)] active:bg-[var(--btn-plain-bg-active)] transition
|
||
" target="_blank"> <div class="transition text-black/75 dark:text-white/75 font-bold group-hover:text-[var(--primary)] group-active:text-[var(--primary)]"> 论坛 </div> <svg width="1em" height="1em" viewBox="0 0 512 512" class="transition text-[0.75rem] text-black/25 dark:text-white/25 -translate-x-1" data-icon="fa6-solid:arrow-up-right-from-square"> <use href="#ai:fa6-solid:arrow-up-right-from-square"></use> </svg> </a> </div> <astro-island uid="O8dFd" component-url="/_astro/DisplaySettings.C8pYka5b.js" component-export="default" renderer-url="/_astro/client.svelte.B_1DUc79.js" props="{}" ssr client="only" opts="{"name":"DisplaySettings","value":"svelte"}"></astro-island> </div> </div> <script type="module">function l(){let e=document.getElementById("display-settings-switch");e&&(e.onclick=function(){let t=document.getElementById("display-setting");t&&t.classList.toggle("float-panel-closed")});let n=document.getElementById("nav-menu-switch");n&&(n.onclick=function(){let t=document.getElementById("nav-menu-panel");t&&t.classList.toggle("float-panel-closed")})}l();</script> </div> </div> <div class="absolute w-full z-30 pointer-events-none" style="top: 5.5rem"> <!-- The pointer-events-none here prevent blocking the click event of the TOC --> <div class="relative max-w-[var(--page-width)] mx-auto pointer-events-auto"> <div id="main-grid" class="transition duration-700 w-full left-0 right-0 grid grid-cols-[17.5rem_auto] grid-rows-[auto_auto_auto] lg:grid-rows-[auto_1fr]
|
||
mx-auto gap-4 px-4 md:px-4"> <!-- Banner image credit --> <div id="sidebar" class="mb-4 row-start-2 col-span-2 lg:row-start-1 lg:col-span-1 lg:max-w-[17.5rem] onload-animation w-full"> <div class="flex flex-col w-full gap-4 mb-4"> <div class="card-base p-3 border border-black/10 dark:border-white/10" data-astro-cid-ufwobukd> <div class="relative mx-auto mt-1 lg:mx-0 lg:mt-0 mb-3 max-w-[12rem] lg:max-w-none rounded-xl overflow-hidden" style="--theme-hue: 361" data-astro-cid-ufwobukd> <img src="https://q2.qlogo.cn/headimg_dl?dst_uin=2726730791&spec=0" alt="Profile Image of the Author" class="w-full h-full object-cover transition duration-500" data-astro-cid-ufwobukd> </div> <div class="px-2" data-astro-cid-ufwobukd> <div class="font-bold text-xl text-center mb-1 dark:text-neutral-50 transition" data-astro-cid-ufwobukd>二叉树树</div> <div class="h-1 w-5 bg-[var(--primary)] mx-auto rounded-full mb-2 transition" data-astro-cid-ufwobukd></div> <div class="text-center text-neutral-400 mb-2.5 transition" data-astro-cid-ufwobukd>Protect What You Love.</div> <div class="flex flex-wrap gap-2 justify-center mb-1" data-astro-cid-ufwobukd> <a rel="me" aria-label="QQ" href="https://qm.qq.com/q/FWqOHlwL2m" target="_blank" class="btn-regular rounded-lg h-10 w-10 active:scale-90" data-astro-cid-ufwobukd> <svg width="0.88em" height="1em" class="text-[1.5rem]" data-astro-cid-ufwobukd="true" data-icon="qq"> <symbol id="ai:local:qq" viewBox="0 0 448 512"><path fill="currentColor" d="M433.754 420.445c-11.526 1.393-44.86-52.741-44.86-52.741 0 31.345-16.136 72.247-51.051 101.786 16.842 5.192 54.843 19.167 45.803 34.421-7.316 12.343-125.51 7.881-159.632 4.037-34.122 3.844-152.316 8.306-159.632-4.037-9.045-15.25 28.918-29.214 45.783-34.415-34.92-29.539-51.059-70.445-51.059-101.792 0 0-33.334 54.134-44.859 52.741-5.37-.65-12.424-29.644 9.347-99.704 10.261-33.024 21.995-60.478 40.144-105.779C60.683 98.063 108.982.006 224 0c113.737.006 163.156 96.133 160.264 214.963 18.118 45.223 29.912 72.85 40.144 105.778 21.768 70.06 14.716 99.053 9.346 99.704"/></symbol><use href="#ai:local:qq"></use> </svg> </a><a rel="me" aria-label="Telegram" href="https://t.me/+_07DERp7k1ljYTc1" target="_blank" class="btn-regular rounded-lg h-10 w-10 active:scale-90" data-astro-cid-ufwobukd> <svg width="0.97em" height="1em" class="text-[1.5rem]" data-astro-cid-ufwobukd="true" data-icon="telegram"> <symbol id="ai:local:telegram" viewBox="0 0 496 512"><path fill="currentColor" d="M248 8C111.033 8 0 119.033 0 256s111.033 248 248 248 248-111.033 248-248S384.967 8 248 8m114.952 168.66c-3.732 39.215-19.881 134.378-28.1 178.3-3.476 18.584-10.322 24.816-16.948 25.425-14.4 1.326-25.338-9.517-39.287-18.661-21.827-14.308-34.158-23.215-55.346-37.177-24.485-16.135-8.612-25 5.342-39.5 3.652-3.793 67.107-61.51 68.335-66.746.153-.655.3-3.1-1.154-4.384s-3.59-.849-5.135-.5q-3.283.746-104.608 69.142-14.845 10.194-26.894 9.934c-8.855-.191-25.888-5.006-38.551-9.123-15.531-5.048-27.875-7.717-26.8-16.291q.84-6.7 18.45-13.7 108.446-47.248 144.628-62.3c68.872-28.647 83.183-33.623 92.511-33.789 2.052-.034 6.639.474 9.61 2.885a10.45 10.45 0 0 1 3.53 6.716 43.8 43.8 0 0 1 .417 9.769"/></symbol><use href="#ai:local:telegram"></use> </svg> </a><a rel="me" aria-label="Bilibli" href="https://space.bilibili.com/325903362" target="_blank" class="btn-regular rounded-lg h-10 w-10 active:scale-90" data-astro-cid-ufwobukd> <svg width="1em" height="1em" class="text-[1.5rem]" data-astro-cid-ufwobukd="true" data-icon="bilibili"> <symbol id="ai:local:bilibili" viewBox="0 0 512 512"><path fill="currentColor" d="M488.6 104.1c16.7 18.1 24.4 39.7 23.3 65.7v202.4c-.4 26.4-9.2 48.1-26.5 65.1-17.2 17-39.1 25.9-65.5 26.7H92.02c-26.45-.8-48.21-9.8-65.28-27.2C9.682 419.4.767 396.5 0 368.2V169.8c.767-26 9.682-47.6 26.74-65.7C43.81 87.75 65.57 78.77 92.02 78h29.38L96.05 52.19c-5.75-5.73-8.63-13-8.63-21.79 0-8.8 2.88-16.06 8.63-21.797C101.8 2.868 109.1 0 117.9 0q13.2 0 21.9 8.603L213.1 78h88l74.5-69.397C381.7 2.868 389.2 0 398 0q13.2 0 21.9 8.603c5.7 5.737 8.6 12.997 8.6 21.797 0 8.79-2.9 16.06-8.6 21.79L394.6 78h29.3c26.4.77 48 9.75 64.7 26.1m-38.8 69.7c-.4-9.6-3.7-17.4-10.7-23.5-5.2-6.1-14-9.4-22.7-9.8H96.05c-9.59.4-17.45 3.7-23.58 9.8-6.14 6.1-9.4 13.9-9.78 23.5v194.4c0 9.2 3.26 17 9.78 23.5s14.38 9.8 23.58 9.8H416.4c9.2 0 17-3.3 23.3-9.8s9.7-14.3 10.1-23.5zm-264.3 42.7c6.3 6.3 9.7 14.1 10.1 23.2V273c-.4 9.2-3.7 16.9-9.8 23.2-6.2 6.3-14 9.5-23.6 9.5s-17.5-3.2-23.6-9.5-9.4-14-9.8-23.2v-33.3c.4-9.1 3.8-16.9 10.1-23.2s13.2-9.6 23.3-10c9.2.4 17 3.7 23.3 10m191.5 0c6.3 6.3 9.7 14.1 10.1 23.2V273c-.4 9.2-3.7 16.9-9.8 23.2s-14 9.5-23.6 9.5-17.4-3.2-23.6-9.5c-7-6.3-9.4-14-9.7-23.2v-33.3c.3-9.1 3.7-16.9 10-23.2s14.1-9.6 23.3-10c9.2.4 17 3.7 23.3 10"/></symbol><use href="#ai:local:bilibili"></use> </svg> </a><a rel="me" aria-label="GitHub" href="https://github.com/afoim" target="_blank" class="btn-regular rounded-lg h-10 w-10 active:scale-90" data-astro-cid-ufwobukd> <svg width="0.97em" height="1em" class="text-[1.5rem]" data-astro-cid-ufwobukd="true" data-icon="github"> <symbol id="ai:local:github" viewBox="0 0 496 512"><path fill="currentColor" d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6m-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3m44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9M244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8M97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1m-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7m32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1m-11.4-14.7c-1.6 1-1.6 3.6 0 5.9s4.3 3.3 5.6 2.3c1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2"/></symbol><use href="#ai:local:github"></use> </svg> </a><a rel="me" aria-label="Folo" href="https://app.folo.is/share/feeds/236818461447222272" target="_blank" class="btn-regular rounded-lg h-10 w-10 active:scale-90" data-astro-cid-ufwobukd> <svg width="1em" height="1em" class="text-[1.5rem]" data-astro-cid-ufwobukd="true" data-icon="folo"> <symbol id="ai:local:folo" viewBox="0 0 24 24"><path fill="currentColor" d="M5.382 0h13.236A5.37 5.37 0 0 1 24 5.383v13.235A5.37 5.37 0 0 1 18.618 24H5.382A5.37 5.37 0 0 1 0 18.618V5.383A5.37 5.37 0 0 1 5.382.001Zm7.887 17.31a1.813 1.813 0 1 0-3.626.002 1.813 1.813 0 0 0 3.626-.002m-.535-6.527H7.213a1.813 1.813 0 1 0 0 3.624h5.521a1.813 1.813 0 1 0 0-3.624m4.417-4.712H8.87a1.813 1.813 0 1 0 0 3.625h8.283a1.813 1.813 0 1 0 0-3.624z"/></symbol><use href="#ai:local:folo"></use> </svg> </a> </div> <!-- 全站文章与字数统计 --> <div class="grid grid-cols-2 mt-3 pt-3 border-t border-neutral-300 dark:border-neutral-700" data-astro-cid-ufwobukd> <div class="text-center" data-astro-cid-ufwobukd> <div class="text-xs text-neutral-500 mb-1 flex items-center justify-center gap-1" data-astro-cid-ufwobukd> <svg width="1em" height="1em" class="text-base" data-astro-cid-ufwobukd="true" data-icon="material-symbols:article-outline"> <symbol id="ai:material-symbols:article-outline" viewBox="0 0 24 24"><path fill="currentColor" d="M7 17h7v-2H7zm0-4h10v-2H7zm0-4h10V7H7zM5 21q-.825 0-1.412-.587T3 19V5q0-.825.588-1.412T5 3h14q.825 0 1.413.588T21 5v14q0 .825-.587 1.413T19 21zm0-2h14V5H5zM5 5v14z"/></symbol><use href="#ai:material-symbols:article-outline"></use> </svg> <span class="text-xs" data-astro-cid-ufwobukd>文章数</span> </div> <div class="font-bold text-lg text-neutral-700 dark:text-neutral-300" data-astro-cid-ufwobukd>148</div> </div> <div class="text-center border-l border-neutral-300 dark:border-neutral-700" data-astro-cid-ufwobukd> <div class="text-xs text-neutral-500 mb-1 flex items-center justify-center gap-1" data-astro-cid-ufwobukd> <svg width="1em" height="1em" class="text-base" data-astro-cid-ufwobukd="true" data-icon="material-symbols:format-list-numbered"> <symbol id="ai:material-symbols:format-list-numbered" viewBox="0 0 24 24"><path fill="currentColor" d="M3 22v-1.5h2.5v-.75H4v-1.5h1.5v-.75H3V16h3q.425 0 .713.288T7 17v1q0 .425-.288.713T6 19q.425 0 .713.288T7 20v1q0 .425-.288.713T6 22zm0-7v-2.75q0-.425.288-.712T4 11.25h1.5v-.75H3V9h3q.425 0 .713.288T7 10v1.75q0 .425-.288.713T6 12.75H4.5v.75H7V15zm1.5-7V3.5H3V2h3v6zM9 19v-2h12v2zm0-6v-2h12v2zm0-6V5h12v2z"/></symbol><use href="#ai:material-symbols:format-list-numbered"></use> </svg> <span class="text-xs" data-astro-cid-ufwobukd>总字数</span> </div> <div class="font-bold text-lg text-neutral-700 dark:text-neutral-300" data-astro-cid-ufwobukd> 9.6w
|
||
</div> </div> </div> <!-- 全站访问量统计 --> <div class="grid grid-cols-2 mt-3 pt-3 border-t border-neutral-300 dark:border-neutral-700" data-astro-cid-ufwobukd> <div class="text-center" data-astro-cid-ufwobukd> <div class="text-xs text-neutral-500 mb-1 flex items-center justify-center gap-1" data-astro-cid-ufwobukd> <svg width="1em" height="1em" class="text-base" data-astro-cid-ufwobukd="true" data-icon="material-symbols:visibility-outline"> <symbol id="ai:material-symbols:visibility-outline" viewBox="0 0 24 24"><path fill="currentColor" d="M12 16q1.875 0 3.188-1.312T16.5 11.5t-1.312-3.187T12 7T8.813 8.313T7.5 11.5t1.313 3.188T12 16m0-1.8q-1.125 0-1.912-.788T9.3 11.5t.788-1.912T12 8.8t1.913.788t.787 1.912t-.787 1.913T12 14.2m0 4.8q-3.65 0-6.65-2.037T1 11.5q1.35-3.425 4.35-5.462T12 4t6.65 2.038T23 11.5q-1.35 3.425-4.35 5.463T12 19m0-2q2.825 0 5.188-1.487T20.8 11.5q-1.25-2.525-3.613-4.012T12 6T6.813 7.488T3.2 11.5q1.25 2.525 3.613 4.013T12 17"/></symbol><use href="#ai:material-symbols:visibility-outline"></use> </svg> <span class="text-xs" data-astro-cid-ufwobukd>访问量</span> </div> <div id="site-views" class="font-bold text-lg text-neutral-700 dark:text-neutral-300" data-astro-cid-ufwobukd>0</div> </div> <div class="text-center border-l border-neutral-300 dark:border-neutral-700" data-astro-cid-ufwobukd> <div class="text-xs text-neutral-500 mb-1 flex items-center justify-center gap-1" data-astro-cid-ufwobukd> <svg width="1em" height="1em" class="text-base" data-astro-cid-ufwobukd="true" data-icon="material-symbols:person"> <symbol id="ai:material-symbols:person" viewBox="0 0 24 24"><path fill="currentColor" d="M12 12q-1.65 0-2.825-1.175T8 8t1.175-2.825T12 4t2.825 1.175T16 8t-1.175 2.825T12 12m-8 8v-2.8q0-.85.438-1.562T5.6 14.55q1.55-.775 3.15-1.162T12 13t3.25.388t3.15 1.162q.725.375 1.163 1.088T20 17.2V20z"/></symbol><use href="#ai:material-symbols:person"></use> </svg> <span class="text-xs" data-astro-cid-ufwobukd>访客数</span> </div> <div id="site-visitors" class="font-bold text-lg text-neutral-700 dark:text-neutral-300" data-astro-cid-ufwobukd>0</div> </div> </div> </div> </div> <script>(function(){const umamiConfig = {"enable":true,"baseUrl":"https://umami.acofork.com","shareId":"CdkXbGgZr6ECKOyK","timezone":"Asia/Shanghai"};
|
||
|
||
// 数字动画函数
|
||
function animateValue(obj, start, end, duration) {
|
||
let startTimestamp = null;
|
||
const step = (timestamp) => {
|
||
if (!startTimestamp) startTimestamp = timestamp;
|
||
const progress = Math.min((timestamp - startTimestamp) / duration, 1);
|
||
obj.innerHTML = Math.floor(progress * (end - start) + start);
|
||
if (progress < 1) {
|
||
window.requestAnimationFrame(step);
|
||
} else {
|
||
obj.innerHTML = end;
|
||
}
|
||
};
|
||
window.requestAnimationFrame(step);
|
||
}
|
||
|
||
// 获取全站访问量统计
|
||
async function loadSiteStats() {
|
||
if (!umamiConfig.enable) return;
|
||
try {
|
||
const statsData = await fetchUmamiStats(umamiConfig.baseUrl, umamiConfig.shareId, {
|
||
timezone: umamiConfig.timezone
|
||
});
|
||
|
||
const pageviews = statsData.pageviews || 0;
|
||
const visitors = statsData.visitors || 0;
|
||
|
||
const viewsElement = document.getElementById('site-views');
|
||
const visitorsElement = document.getElementById('site-visitors');
|
||
|
||
if (viewsElement) {
|
||
const startVal = parseInt(viewsElement.textContent) || 0;
|
||
// 如果当前值已经是目标值,就不执行动画
|
||
if (startVal !== pageviews) {
|
||
animateValue(viewsElement, startVal, pageviews, 1000);
|
||
}
|
||
}
|
||
|
||
if (visitorsElement) {
|
||
const startVal = parseInt(visitorsElement.textContent) || 0;
|
||
// 如果当前值已经是目标值,就不执行动画
|
||
if (startVal !== visitors) {
|
||
animateValue(visitorsElement, startVal, visitors, 1000);
|
||
}
|
||
}
|
||
} catch (error) {
|
||
console.error('获取全站统计失败:', error);
|
||
}
|
||
}
|
||
|
||
// 页面加载完成后获取统计数据
|
||
document.addEventListener('DOMContentLoaded', loadSiteStats);
|
||
// 监听 Swup 内容替换事件,确保页面切换后重新获取数据
|
||
document.addEventListener('content:replace', loadSiteStats);
|
||
})();</script> </div> <div id="sidebar-sticky" class="transition-all duration-700 flex flex-col w-full gap-4 top-4 sticky top-4"> <!-- 赞助标 --> <div class="overflow-hidden flex justify-center"> <a href="https://secbit.ai/" target="_blank" rel="noopener noreferrer"> <img src="/aff/secbit-banner-1.gif" alt="Secbit" class="w-full max-w-[280px] rounded-lg hover:opacity-90 transition-opacity"> </a> </div> <div class="overflow-hidden flex justify-center"> <iframe src="https://support.nodeget.com/page/promotion?id=316" style="border:none; border-radius:8px; height:270px; width:100%; max-width:280px;
|
||
transform: scale(1.0); transform-origin: center top;"></iframe> </div> </div> </div> <main id="swup-container" class="transition-swup-fade row-start-1 col-span-2 lg:row-start-1 lg:col-span-1 overflow-visible min-w-0"> <div id="content-wrapper" class="onload-animation"> <!-- the overflow-hidden here prevent long text break the layout--> <!-- make id different from windows.swup global property --> <div class="notice-card mb-4 relative transition-all duration-300 hover:shadow-lg onload-animation" data-astro-cid-afjw4rzz><div class="notice-content flex items-center p-4 rounded-xl bg-[var(--card-bg)] border transition-colors" style="border-color:var(--admonitions-color-note);color:var(--admonitions-color-note)" data-astro-cid-afjw4rzz><div class="icon-wrapper mr-4 flex items-center justify-center shrink-0" data-astro-cid-afjw4rzz><svg width="1em" height="1em" class="text-2xl" data-astro-cid-afjw4rzz="true" data-icon="material-symbols:info-outline-rounded"> <symbol id="ai:material-symbols:info-outline-rounded" viewBox="0 0 24 24"><path fill="currentColor" d="M12 17q.425 0 .713-.288T13 16v-4q0-.425-.288-.712T12 11t-.712.288T11 12v4q0 .425.288.713T12 17m0-8q.425 0 .713-.288T13 8t-.288-.712T12 7t-.712.288T11 8t.288.713T12 9m0 13q-2.075 0-3.9-.788t-3.175-2.137T2.788 15.9T2 12t.788-3.9t2.137-3.175T8.1 2.788T12 2t3.9.788t3.175 2.137T21.213 8.1T22 12t-.788 3.9t-2.137 3.175t-3.175 2.138T12 22m0-2q3.35 0 5.675-2.325T20 12t-2.325-5.675T12 4T6.325 6.325T4 12t2.325 5.675T12 20m0-8"/></symbol><use href="#ai:material-symbols:info-outline-rounded"></use> </svg></div><div class="text-wrapper grow" data-astro-cid-afjw4rzz><div class="notice-text text-sm md:text-base font-bold" data-astro-cid-afjw4rzz>我们刚刚添加了文章更新系统,自此之后的每次文章更新都会通过右下角的小铃铛提醒您。</div></div></div><div class="absolute inset-0 rounded-xl pointer-events-none border-2 opacity-10" style="border-color:var(--admonitions-color-note)" data-astro-cid-afjw4rzz></div></div> <div class="transition flex flex-col rounded-[var(--radius-large)] bg-transparent gap-4 mb-4"> <div class="onload-animation" style="animation-delay: calc(var(--content-delay) + 0ms);"> <div class="card-base card-hover flex flex-col w-full relative" style="undefined; --coverWidth: 28%;" data-astro-cid-iyiqi2so> <div class="pl-9 pr-2 pt-6 pb-6 relative w-[calc(100%_-_var(--coverWidth)_-_12px)]" data-astro-cid-iyiqi2so style="--coverWidth: 28%;"> <a href="/posts/github-edu/" class="transition group w-full block font-bold mb-2 md:mb-3 text-xl md:text-3xl text-90 relative
|
||
hover:text-[var(--primary)] dark:hover:text-[var(--primary)]
|
||
active:text-[var(--title-active)] dark:active:text-[var(--title-active)]
|
||
before:w-1 before:h-5 before:rounded-md before:bg-[var(--primary)]
|
||
before:absolute before:top-1 md:before:top-2 before:-left-[1.125rem] before:block
|
||
" data-astro-cid-iyiqi2so style="--coverWidth: 28%;"> Github新版学生认证怎么过?用记事本! </a> <!-- description --> <div class="transition text-75 mb-3.5 pr-4 line-clamp-1 md:line-clamp-2" data-astro-cid-iyiqi2so style="--coverWidth: 28%;"> 突然被粉丝怂恿来弄Github学生认证,弄了半天,被我发现了奇技淫巧??? </div> <!-- metadata --> <div class="flex flex-wrap text-neutral-500 dark:text-neutral-400 items-center gap-4 gap-x-4 gap-y-2 mb-2 md:mb-4"> <!-- publish date --> <!-- update date --> <!-- page views & visitors --> <div class="flex items-center"> <div class="meta-icon"> <svg width="1em" height="1em" class="text-xl" data-icon="material-symbols:visibility-outline-rounded"> <symbol id="ai:material-symbols:visibility-outline-rounded" viewBox="0 0 24 24"><path fill="currentColor" d="M12 16q1.875 0 3.188-1.312T16.5 11.5t-1.312-3.187T12 7T8.813 8.313T7.5 11.5t1.313 3.188T12 16m0-1.8q-1.125 0-1.912-.788T9.3 11.5t.788-1.912T12 8.8t1.913.788t.787 1.912t-.787 1.913T12 14.2m0 4.8q-3.35 0-6.113-1.8t-4.362-4.75q-.125-.225-.187-.462t-.063-.488t.063-.488t.187-.462q1.6-2.95 4.363-4.75T12 4t6.113 1.8t4.362 4.75q.125.225.188.463t.062.487t-.062.488t-.188.462q-1.6 2.95-4.362 4.75T12 19m0-2q2.825 0 5.188-1.487T20.8 11.5q-1.25-2.525-3.613-4.012T12 6T6.813 7.488T3.2 11.5q1.25 2.525 3.613 4.013T12 17"/></symbol><use href="#ai:material-symbols:visibility-outline-rounded"></use> </svg> </div> <span class="text-50 text-sm font-medium" id="page-views-github-edu">0 次</span> </div> <div class="flex items-center"> <div class="meta-icon"> <svg width="1em" height="1em" viewBox="0 0 24 24" class="text-xl" data-icon="material-symbols:person"> <use href="#ai:material-symbols:person"></use> </svg> </div> <span class="text-50 text-sm font-medium" id="page-visitors-github-edu">0 人</span> </div> </div> <script>(function(){const slug = "github-edu";
|
||
const umamiConfig = {"enable":true,"baseUrl":"https://umami.acofork.com","shareId":"CdkXbGgZr6ECKOyK","timezone":"Asia/Shanghai"};
|
||
|
||
// 数字动画函数
|
||
function animateValue(obj, start, end, duration, suffix = '') {
|
||
let startTimestamp = null;
|
||
const step = (timestamp) => {
|
||
if (!startTimestamp) startTimestamp = timestamp;
|
||
const progress = Math.min((timestamp - startTimestamp) / duration, 1);
|
||
obj.innerHTML = `${Math.floor(progress * (end - start) + start)} ${suffix}`;
|
||
if (progress < 1) {
|
||
window.requestAnimationFrame(step);
|
||
} else {
|
||
obj.innerHTML = `${end} ${suffix}`;
|
||
}
|
||
};
|
||
window.requestAnimationFrame(step);
|
||
}
|
||
|
||
// 获取访问量统计
|
||
async function fetchPageViews() {
|
||
if (!umamiConfig.enable) return;
|
||
try {
|
||
const statsData = await fetchUmamiStats(umamiConfig.baseUrl, umamiConfig.shareId, {
|
||
timezone: umamiConfig.timezone,
|
||
path: `eq./posts/${slug}/`
|
||
});
|
||
|
||
const pageViews = (statsData.pageviews && statsData.pageviews.value) || statsData.pageviews || 0;
|
||
const visits = (statsData.visitors && statsData.visitors.value) || statsData.visitors || 0;
|
||
|
||
const viewsElement = document.getElementById(`page-views-${slug}`);
|
||
const visitorsElement = document.getElementById(`page-visitors-${slug}`);
|
||
|
||
// 如果数据来自缓存,直接显示结果,跳过动画
|
||
if (statsData._fromCache) {
|
||
if (viewsElement) viewsElement.innerHTML = `${pageViews} 次`;
|
||
if (visitorsElement) visitorsElement.innerHTML = `${visits} 人`;
|
||
return;
|
||
}
|
||
|
||
if (viewsElement) {
|
||
const currentViews = parseInt(viewsElement.textContent) || 0;
|
||
if (currentViews !== pageViews) {
|
||
if (currentViews === 0) {
|
||
animateValue(viewsElement, currentViews, pageViews, 1000, '次');
|
||
} else {
|
||
viewsElement.innerHTML = `${pageViews} 次`;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (visitorsElement) {
|
||
const currentVisits = parseInt(visitorsElement.textContent) || 0;
|
||
if (currentVisits !== visits) {
|
||
if (currentVisits === 0) {
|
||
animateValue(visitorsElement, currentVisits, visits, 1000, '人');
|
||
} else {
|
||
visitorsElement.innerHTML = `${visits} 人`;
|
||
}
|
||
}
|
||
}
|
||
} catch (error) {
|
||
console.error('Error fetching page views:', error);
|
||
}
|
||
}
|
||
|
||
// 页面加载完成后获取统计数据
|
||
if (document.readyState === 'loading') {
|
||
document.addEventListener('DOMContentLoaded', fetchPageViews);
|
||
} else {
|
||
fetchPageViews();
|
||
}
|
||
})();</script> <!-- word count, read time and page views --> <div class="text-sm text-black/30 dark:text-white/30 flex gap-4 transition" data-astro-cid-iyiqi2so style="--coverWidth: 28%;"> <div data-astro-cid-iyiqi2so style="--coverWidth: 28%;">2025-08-08</div> <div data-astro-cid-iyiqi2so style="--coverWidth: 28%;">|</div> <div data-astro-cid-iyiqi2so style="--coverWidth: 28%;">259 字</div> <div data-astro-cid-iyiqi2so style="--coverWidth: 28%;">|</div> <div data-astro-cid-iyiqi2so style="--coverWidth: 28%;">1 分钟</div> </div> </div> <a href="/posts/github-edu/" aria-label="Github新版学生认证怎么过?用记事本!" class="group max-h-none mx-0 mt-0 w-[var(--coverWidth)] absolute top-3 bottom-3 right-3 rounded-xl overflow-hidden active:scale-95" data-astro-cid-iyiqi2so style="--coverWidth: 28%;"> <div class="absolute pointer-events-none z-10 w-full h-full group-hover:bg-black/30 group-active:bg-black/50 transition" data-astro-cid-iyiqi2so style="--coverWidth: 28%;"></div> <!-- 封面图上的箭头 --> <div class="absolute pointer-events-none z-20 w-full h-full flex items-center justify-center " data-astro-cid-iyiqi2so style="--coverWidth: 28%;"> <svg width="1em" height="1em" viewBox="0 0 24 24" class="transition opacity-0 group-hover:opacity-100 scale-50 group-hover:scale-100 text-white text-5xl" data-astro-cid-iyiqi2so="true" data-icon="material-symbols:chevron-right-rounded"> <use href="#ai:material-symbols:chevron-right-rounded"></use> </svg> </div> <div class="w-full h-full overflow-hidden relative image-wrapper" style="--theme-hue: 361" data-astro-cid-i2xmscho> <img src="/_astro/2025-08-08-01-01-00-image.DZm12-wh.png" alt="Cover Image of the Post" style="object-position: center" data-astro-cid-i2xmscho="true" width="972" height="759" loading="lazy" decoding="async" class="w-full h-full object-cover image-content"> </div> </a> </div> <div class="transition border-t-[1px] border-dashed mx-6 border-black/10 dark:border-white/[0.15] last:border-t-0 hidden" data-astro-cid-iyiqi2so style="--coverWidth: 28%;"></div> <script type="module">function m(r,t,s,o){let a=null;const i=e=>{a||(a=e);const n=Math.min((e-a)/o,1);r.innerHTML=Math.floor(n*(s-t)+t),n<1?window.requestAnimationFrame(i):r.innerHTML=s};window.requestAnimationFrame(i)}async function d(){document.querySelectorAll(".post-pageviews").forEach(async t=>{if(t.classList.contains("processed")&&t.textContent!=="0")return;t.classList.add("processed");const s=t.dataset.url,o=t.dataset.umamiBaseUrl,a=t.dataset.umamiShareId,i=t.dataset.umamiTimezone;if(!(!o||!a))try{if(typeof window.fetchUmamiStats!="function")return;const e=await window.fetchUmamiStats(o,a,{url:s,timezone:i}),n=e.pageviews&&e.pageviews.value||e.pageviews||0;if(e._fromCache){t.innerHTML=n;return}const c=parseInt(t.textContent)||0;c!==n&&(c===0?m(t,c,n,1e3):t.innerHTML=n)}catch(e){console.error("Failed to load stats for",s,e)}})}document.addEventListener("DOMContentLoaded",d);document.addEventListener("swup:contentReplaced",d);</script> </div><div class="onload-animation" style="animation-delay: calc(var(--content-delay) + 50ms);"> <div class="card-base card-hover flex flex-col w-full relative" style="undefined; --coverWidth: 28%;" data-astro-cid-iyiqi2so> <div class="pl-9 pr-2 pt-6 pb-6 relative w-[calc(100%_-_var(--coverWidth)_-_12px)]" data-astro-cid-iyiqi2so style="--coverWidth: 28%;"> <a href="/posts/qiyewx-deepseek/" class="transition group w-full block font-bold mb-2 md:mb-3 text-xl md:text-3xl text-90 relative
|
||
hover:text-[var(--primary)] dark:hover:text-[var(--primary)]
|
||
active:text-[var(--title-active)] dark:active:text-[var(--title-active)]
|
||
before:w-1 before:h-5 before:rounded-md before:bg-[var(--primary)]
|
||
before:absolute before:top-1 md:before:top-2 before:-left-[1.125rem] before:block
|
||
" data-astro-cid-iyiqi2so style="--coverWidth: 28%;"> 你说什么?企业微信能免费用Deepseek?!还能调成猫娘?!! </a> <!-- description --> <div class="transition text-75 mb-3.5 pr-4 line-clamp-1 md:line-clamp-2" data-astro-cid-iyiqi2so style="--coverWidth: 28%;"> 今天无意中建了个企业微信群,然后就发现可以加智能体,然后就调了个猫娘出来... </div> <!-- metadata --> <div class="flex flex-wrap text-neutral-500 dark:text-neutral-400 items-center gap-4 gap-x-4 gap-y-2 mb-2 md:mb-4"> <!-- publish date --> <!-- update date --> <!-- page views & visitors --> <div class="flex items-center"> <div class="meta-icon"> <svg width="1em" height="1em" viewBox="0 0 24 24" class="text-xl" data-icon="material-symbols:visibility-outline-rounded"> <use href="#ai:material-symbols:visibility-outline-rounded"></use> </svg> </div> <span class="text-50 text-sm font-medium" id="page-views-qiyewx-deepseek">0 次</span> </div> <div class="flex items-center"> <div class="meta-icon"> <svg width="1em" height="1em" viewBox="0 0 24 24" class="text-xl" data-icon="material-symbols:person"> <use href="#ai:material-symbols:person"></use> </svg> </div> <span class="text-50 text-sm font-medium" id="page-visitors-qiyewx-deepseek">0 人</span> </div> </div> <script>(function(){const slug = "qiyewx-deepseek";
|
||
const umamiConfig = {"enable":true,"baseUrl":"https://umami.acofork.com","shareId":"CdkXbGgZr6ECKOyK","timezone":"Asia/Shanghai"};
|
||
|
||
// 数字动画函数
|
||
function animateValue(obj, start, end, duration, suffix = '') {
|
||
let startTimestamp = null;
|
||
const step = (timestamp) => {
|
||
if (!startTimestamp) startTimestamp = timestamp;
|
||
const progress = Math.min((timestamp - startTimestamp) / duration, 1);
|
||
obj.innerHTML = `${Math.floor(progress * (end - start) + start)} ${suffix}`;
|
||
if (progress < 1) {
|
||
window.requestAnimationFrame(step);
|
||
} else {
|
||
obj.innerHTML = `${end} ${suffix}`;
|
||
}
|
||
};
|
||
window.requestAnimationFrame(step);
|
||
}
|
||
|
||
// 获取访问量统计
|
||
async function fetchPageViews() {
|
||
if (!umamiConfig.enable) return;
|
||
try {
|
||
const statsData = await fetchUmamiStats(umamiConfig.baseUrl, umamiConfig.shareId, {
|
||
timezone: umamiConfig.timezone,
|
||
path: `eq./posts/${slug}/`
|
||
});
|
||
|
||
const pageViews = (statsData.pageviews && statsData.pageviews.value) || statsData.pageviews || 0;
|
||
const visits = (statsData.visitors && statsData.visitors.value) || statsData.visitors || 0;
|
||
|
||
const viewsElement = document.getElementById(`page-views-${slug}`);
|
||
const visitorsElement = document.getElementById(`page-visitors-${slug}`);
|
||
|
||
// 如果数据来自缓存,直接显示结果,跳过动画
|
||
if (statsData._fromCache) {
|
||
if (viewsElement) viewsElement.innerHTML = `${pageViews} 次`;
|
||
if (visitorsElement) visitorsElement.innerHTML = `${visits} 人`;
|
||
return;
|
||
}
|
||
|
||
if (viewsElement) {
|
||
const currentViews = parseInt(viewsElement.textContent) || 0;
|
||
if (currentViews !== pageViews) {
|
||
if (currentViews === 0) {
|
||
animateValue(viewsElement, currentViews, pageViews, 1000, '次');
|
||
} else {
|
||
viewsElement.innerHTML = `${pageViews} 次`;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (visitorsElement) {
|
||
const currentVisits = parseInt(visitorsElement.textContent) || 0;
|
||
if (currentVisits !== visits) {
|
||
if (currentVisits === 0) {
|
||
animateValue(visitorsElement, currentVisits, visits, 1000, '人');
|
||
} else {
|
||
visitorsElement.innerHTML = `${visits} 人`;
|
||
}
|
||
}
|
||
}
|
||
} catch (error) {
|
||
console.error('Error fetching page views:', error);
|
||
}
|
||
}
|
||
|
||
// 页面加载完成后获取统计数据
|
||
if (document.readyState === 'loading') {
|
||
document.addEventListener('DOMContentLoaded', fetchPageViews);
|
||
} else {
|
||
fetchPageViews();
|
||
}
|
||
})();</script> <!-- word count, read time and page views --> <div class="text-sm text-black/30 dark:text-white/30 flex gap-4 transition" data-astro-cid-iyiqi2so style="--coverWidth: 28%;"> <div data-astro-cid-iyiqi2so style="--coverWidth: 28%;">2025-08-07</div> <div data-astro-cid-iyiqi2so style="--coverWidth: 28%;">|</div> <div data-astro-cid-iyiqi2so style="--coverWidth: 28%;">77 字</div> <div data-astro-cid-iyiqi2so style="--coverWidth: 28%;">|</div> <div data-astro-cid-iyiqi2so style="--coverWidth: 28%;">1 分钟</div> </div> </div> <a href="/posts/qiyewx-deepseek/" aria-label="你说什么?企业微信能免费用Deepseek?!还能调成猫娘?!!" class="group max-h-none mx-0 mt-0 w-[var(--coverWidth)] absolute top-3 bottom-3 right-3 rounded-xl overflow-hidden active:scale-95" data-astro-cid-iyiqi2so style="--coverWidth: 28%;"> <div class="absolute pointer-events-none z-10 w-full h-full group-hover:bg-black/30 group-active:bg-black/50 transition" data-astro-cid-iyiqi2so style="--coverWidth: 28%;"></div> <!-- 封面图上的箭头 --> <div class="absolute pointer-events-none z-20 w-full h-full flex items-center justify-center " data-astro-cid-iyiqi2so style="--coverWidth: 28%;"> <svg width="1em" height="1em" viewBox="0 0 24 24" class="transition opacity-0 group-hover:opacity-100 scale-50 group-hover:scale-100 text-white text-5xl" data-astro-cid-iyiqi2so="true" data-icon="material-symbols:chevron-right-rounded"> <use href="#ai:material-symbols:chevron-right-rounded"></use> </svg> </div> <div class="w-full h-full overflow-hidden relative image-wrapper" style="--theme-hue: 361" data-astro-cid-i2xmscho> <img src="/_astro/2025-08-07-04-10-58-image.C_p5_AmY.png" alt="Cover Image of the Post" style="object-position: center" data-astro-cid-i2xmscho="true" width="735" height="660" loading="lazy" decoding="async" class="w-full h-full object-cover image-content"> </div> </a> </div> <div class="transition border-t-[1px] border-dashed mx-6 border-black/10 dark:border-white/[0.15] last:border-t-0 hidden" data-astro-cid-iyiqi2so style="--coverWidth: 28%;"></div> </div><div class="onload-animation" style="animation-delay: calc(var(--content-delay) + 100ms);"> <div class="card-base card-hover flex flex-col w-full relative" style="undefined; --coverWidth: 28%;" data-astro-cid-iyiqi2so> <div class="pl-9 pr-2 pt-6 pb-6 relative w-[calc(100%_-_var(--coverWidth)_-_12px)]" data-astro-cid-iyiqi2so style="--coverWidth: 28%;"> <a href="/posts/element/" class="transition group w-full block font-bold mb-2 md:mb-3 text-xl md:text-3xl text-90 relative
|
||
hover:text-[var(--primary)] dark:hover:text-[var(--primary)]
|
||
active:text-[var(--title-active)] dark:active:text-[var(--title-active)]
|
||
before:w-1 before:h-5 before:rounded-md before:bg-[var(--primary)]
|
||
before:absolute before:top-1 md:before:top-2 before:-left-[1.125rem] before:block
|
||
" data-astro-cid-iyiqi2so style="--coverWidth: 28%;"> 关于如何加入我们自托管的m.2x.nz端到端加密聊天服务器 </a> <!-- description --> <div class="transition text-75 mb-3.5 pr-4 line-clamp-1 md:line-clamp-2" data-astro-cid-iyiqi2so style="--coverWidth: 28%;"> 我在一台主机上托管了synapse,现在你可以使用Element通过我的邀请链接加入这个端到端加密聊天服务器 </div> <!-- metadata --> <div class="flex flex-wrap text-neutral-500 dark:text-neutral-400 items-center gap-4 gap-x-4 gap-y-2 mb-2 md:mb-4"> <!-- publish date --> <!-- update date --> <!-- page views & visitors --> <div class="flex items-center"> <div class="meta-icon"> <svg width="1em" height="1em" viewBox="0 0 24 24" class="text-xl" data-icon="material-symbols:visibility-outline-rounded"> <use href="#ai:material-symbols:visibility-outline-rounded"></use> </svg> </div> <span class="text-50 text-sm font-medium" id="page-views-element">0 次</span> </div> <div class="flex items-center"> <div class="meta-icon"> <svg width="1em" height="1em" viewBox="0 0 24 24" class="text-xl" data-icon="material-symbols:person"> <use href="#ai:material-symbols:person"></use> </svg> </div> <span class="text-50 text-sm font-medium" id="page-visitors-element">0 人</span> </div> </div> <script>(function(){const slug = "element";
|
||
const umamiConfig = {"enable":true,"baseUrl":"https://umami.acofork.com","shareId":"CdkXbGgZr6ECKOyK","timezone":"Asia/Shanghai"};
|
||
|
||
// 数字动画函数
|
||
function animateValue(obj, start, end, duration, suffix = '') {
|
||
let startTimestamp = null;
|
||
const step = (timestamp) => {
|
||
if (!startTimestamp) startTimestamp = timestamp;
|
||
const progress = Math.min((timestamp - startTimestamp) / duration, 1);
|
||
obj.innerHTML = `${Math.floor(progress * (end - start) + start)} ${suffix}`;
|
||
if (progress < 1) {
|
||
window.requestAnimationFrame(step);
|
||
} else {
|
||
obj.innerHTML = `${end} ${suffix}`;
|
||
}
|
||
};
|
||
window.requestAnimationFrame(step);
|
||
}
|
||
|
||
// 获取访问量统计
|
||
async function fetchPageViews() {
|
||
if (!umamiConfig.enable) return;
|
||
try {
|
||
const statsData = await fetchUmamiStats(umamiConfig.baseUrl, umamiConfig.shareId, {
|
||
timezone: umamiConfig.timezone,
|
||
path: `eq./posts/${slug}/`
|
||
});
|
||
|
||
const pageViews = (statsData.pageviews && statsData.pageviews.value) || statsData.pageviews || 0;
|
||
const visits = (statsData.visitors && statsData.visitors.value) || statsData.visitors || 0;
|
||
|
||
const viewsElement = document.getElementById(`page-views-${slug}`);
|
||
const visitorsElement = document.getElementById(`page-visitors-${slug}`);
|
||
|
||
// 如果数据来自缓存,直接显示结果,跳过动画
|
||
if (statsData._fromCache) {
|
||
if (viewsElement) viewsElement.innerHTML = `${pageViews} 次`;
|
||
if (visitorsElement) visitorsElement.innerHTML = `${visits} 人`;
|
||
return;
|
||
}
|
||
|
||
if (viewsElement) {
|
||
const currentViews = parseInt(viewsElement.textContent) || 0;
|
||
if (currentViews !== pageViews) {
|
||
if (currentViews === 0) {
|
||
animateValue(viewsElement, currentViews, pageViews, 1000, '次');
|
||
} else {
|
||
viewsElement.innerHTML = `${pageViews} 次`;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (visitorsElement) {
|
||
const currentVisits = parseInt(visitorsElement.textContent) || 0;
|
||
if (currentVisits !== visits) {
|
||
if (currentVisits === 0) {
|
||
animateValue(visitorsElement, currentVisits, visits, 1000, '人');
|
||
} else {
|
||
visitorsElement.innerHTML = `${visits} 人`;
|
||
}
|
||
}
|
||
}
|
||
} catch (error) {
|
||
console.error('Error fetching page views:', error);
|
||
}
|
||
}
|
||
|
||
// 页面加载完成后获取统计数据
|
||
if (document.readyState === 'loading') {
|
||
document.addEventListener('DOMContentLoaded', fetchPageViews);
|
||
} else {
|
||
fetchPageViews();
|
||
}
|
||
})();</script> <!-- word count, read time and page views --> <div class="text-sm text-black/30 dark:text-white/30 flex gap-4 transition" data-astro-cid-iyiqi2so style="--coverWidth: 28%;"> <div data-astro-cid-iyiqi2so style="--coverWidth: 28%;">2025-08-06</div> <div data-astro-cid-iyiqi2so style="--coverWidth: 28%;">|</div> <div data-astro-cid-iyiqi2so style="--coverWidth: 28%;">354 字</div> <div data-astro-cid-iyiqi2so style="--coverWidth: 28%;">|</div> <div data-astro-cid-iyiqi2so style="--coverWidth: 28%;">2 分钟</div> </div> </div> <a href="/posts/element/" aria-label="关于如何加入我们自托管的m.2x.nz端到端加密聊天服务器" class="group max-h-none mx-0 mt-0 w-[var(--coverWidth)] absolute top-3 bottom-3 right-3 rounded-xl overflow-hidden active:scale-95" data-astro-cid-iyiqi2so style="--coverWidth: 28%;"> <div class="absolute pointer-events-none z-10 w-full h-full group-hover:bg-black/30 group-active:bg-black/50 transition" data-astro-cid-iyiqi2so style="--coverWidth: 28%;"></div> <!-- 封面图上的箭头 --> <div class="absolute pointer-events-none z-20 w-full h-full flex items-center justify-center " data-astro-cid-iyiqi2so style="--coverWidth: 28%;"> <svg width="1em" height="1em" viewBox="0 0 24 24" class="transition opacity-0 group-hover:opacity-100 scale-50 group-hover:scale-100 text-white text-5xl" data-astro-cid-iyiqi2so="true" data-icon="material-symbols:chevron-right-rounded"> <use href="#ai:material-symbols:chevron-right-rounded"></use> </svg> </div> <div class="w-full h-full overflow-hidden relative image-wrapper" style="--theme-hue: 361" data-astro-cid-i2xmscho> <img src="/_astro/d676d367-061a-48ea-9157-ce00c6120232.De3T8UHr.webp" alt="Cover Image of the Post" style="object-position: center" data-astro-cid-i2xmscho="true" width="1110" height="869" loading="lazy" decoding="async" class="w-full h-full object-cover image-content"> </div> </a> </div> <div class="transition border-t-[1px] border-dashed mx-6 border-black/10 dark:border-white/[0.15] last:border-t-0 hidden" data-astro-cid-iyiqi2so style="--coverWidth: 28%;"></div> </div><div class="onload-animation" style="animation-delay: calc(var(--content-delay) + 150ms);"> <div class="card-base card-hover flex flex-col w-full relative" style="undefined; --coverWidth: 28%;" data-astro-cid-iyiqi2so> <div class="pl-9 pr-2 pt-6 pb-6 relative w-[calc(100%_-_var(--coverWidth)_-_12px)]" data-astro-cid-iyiqi2so style="--coverWidth: 28%;"> <a href="/posts/giscus-akismet/" class="transition group w-full block font-bold mb-2 md:mb-3 text-xl md:text-3xl text-90 relative
|
||
hover:text-[var(--primary)] dark:hover:text-[var(--primary)]
|
||
active:text-[var(--title-active)] dark:active:text-[var(--title-active)]
|
||
before:w-1 before:h-5 before:rounded-md before:bg-[var(--primary)]
|
||
before:absolute before:top-1 md:before:top-2 before:-left-[1.125rem] before:block
|
||
" data-astro-cid-iyiqi2so style="--coverWidth: 28%;"> 为任何站点对接Giscus并且配置反垃圾! </a> <!-- description --> <div class="transition text-75 mb-3.5 pr-4 line-clamp-1 md:line-clamp-2" data-astro-cid-iyiqi2so style="--coverWidth: 28%;"> 你是否在寻找一个评论系统而又不想自托管?又饱受垃圾评论的叨扰? </div> <!-- metadata --> <div class="flex flex-wrap text-neutral-500 dark:text-neutral-400 items-center gap-4 gap-x-4 gap-y-2 mb-2 md:mb-4"> <!-- publish date --> <!-- update date --> <!-- page views & visitors --> <div class="flex items-center"> <div class="meta-icon"> <svg width="1em" height="1em" viewBox="0 0 24 24" class="text-xl" data-icon="material-symbols:visibility-outline-rounded"> <use href="#ai:material-symbols:visibility-outline-rounded"></use> </svg> </div> <span class="text-50 text-sm font-medium" id="page-views-giscus-akismet">0 次</span> </div> <div class="flex items-center"> <div class="meta-icon"> <svg width="1em" height="1em" viewBox="0 0 24 24" class="text-xl" data-icon="material-symbols:person"> <use href="#ai:material-symbols:person"></use> </svg> </div> <span class="text-50 text-sm font-medium" id="page-visitors-giscus-akismet">0 人</span> </div> </div> <script>(function(){const slug = "giscus-akismet";
|
||
const umamiConfig = {"enable":true,"baseUrl":"https://umami.acofork.com","shareId":"CdkXbGgZr6ECKOyK","timezone":"Asia/Shanghai"};
|
||
|
||
// 数字动画函数
|
||
function animateValue(obj, start, end, duration, suffix = '') {
|
||
let startTimestamp = null;
|
||
const step = (timestamp) => {
|
||
if (!startTimestamp) startTimestamp = timestamp;
|
||
const progress = Math.min((timestamp - startTimestamp) / duration, 1);
|
||
obj.innerHTML = `${Math.floor(progress * (end - start) + start)} ${suffix}`;
|
||
if (progress < 1) {
|
||
window.requestAnimationFrame(step);
|
||
} else {
|
||
obj.innerHTML = `${end} ${suffix}`;
|
||
}
|
||
};
|
||
window.requestAnimationFrame(step);
|
||
}
|
||
|
||
// 获取访问量统计
|
||
async function fetchPageViews() {
|
||
if (!umamiConfig.enable) return;
|
||
try {
|
||
const statsData = await fetchUmamiStats(umamiConfig.baseUrl, umamiConfig.shareId, {
|
||
timezone: umamiConfig.timezone,
|
||
path: `eq./posts/${slug}/`
|
||
});
|
||
|
||
const pageViews = (statsData.pageviews && statsData.pageviews.value) || statsData.pageviews || 0;
|
||
const visits = (statsData.visitors && statsData.visitors.value) || statsData.visitors || 0;
|
||
|
||
const viewsElement = document.getElementById(`page-views-${slug}`);
|
||
const visitorsElement = document.getElementById(`page-visitors-${slug}`);
|
||
|
||
// 如果数据来自缓存,直接显示结果,跳过动画
|
||
if (statsData._fromCache) {
|
||
if (viewsElement) viewsElement.innerHTML = `${pageViews} 次`;
|
||
if (visitorsElement) visitorsElement.innerHTML = `${visits} 人`;
|
||
return;
|
||
}
|
||
|
||
if (viewsElement) {
|
||
const currentViews = parseInt(viewsElement.textContent) || 0;
|
||
if (currentViews !== pageViews) {
|
||
if (currentViews === 0) {
|
||
animateValue(viewsElement, currentViews, pageViews, 1000, '次');
|
||
} else {
|
||
viewsElement.innerHTML = `${pageViews} 次`;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (visitorsElement) {
|
||
const currentVisits = parseInt(visitorsElement.textContent) || 0;
|
||
if (currentVisits !== visits) {
|
||
if (currentVisits === 0) {
|
||
animateValue(visitorsElement, currentVisits, visits, 1000, '人');
|
||
} else {
|
||
visitorsElement.innerHTML = `${visits} 人`;
|
||
}
|
||
}
|
||
}
|
||
} catch (error) {
|
||
console.error('Error fetching page views:', error);
|
||
}
|
||
}
|
||
|
||
// 页面加载完成后获取统计数据
|
||
if (document.readyState === 'loading') {
|
||
document.addEventListener('DOMContentLoaded', fetchPageViews);
|
||
} else {
|
||
fetchPageViews();
|
||
}
|
||
})();</script> <!-- word count, read time and page views --> <div class="text-sm text-black/30 dark:text-white/30 flex gap-4 transition" data-astro-cid-iyiqi2so style="--coverWidth: 28%;"> <div data-astro-cid-iyiqi2so style="--coverWidth: 28%;">2025-08-04</div> <div data-astro-cid-iyiqi2so style="--coverWidth: 28%;">|</div> <div data-astro-cid-iyiqi2so style="--coverWidth: 28%;">517 字</div> <div data-astro-cid-iyiqi2so style="--coverWidth: 28%;">|</div> <div data-astro-cid-iyiqi2so style="--coverWidth: 28%;">3 分钟</div> </div> </div> <a href="/posts/giscus-akismet/" aria-label="为任何站点对接Giscus并且配置反垃圾!" class="group max-h-none mx-0 mt-0 w-[var(--coverWidth)] absolute top-3 bottom-3 right-3 rounded-xl overflow-hidden active:scale-95" data-astro-cid-iyiqi2so style="--coverWidth: 28%;"> <div class="absolute pointer-events-none z-10 w-full h-full group-hover:bg-black/30 group-active:bg-black/50 transition" data-astro-cid-iyiqi2so style="--coverWidth: 28%;"></div> <!-- 封面图上的箭头 --> <div class="absolute pointer-events-none z-20 w-full h-full flex items-center justify-center " data-astro-cid-iyiqi2so style="--coverWidth: 28%;"> <svg width="1em" height="1em" viewBox="0 0 24 24" class="transition opacity-0 group-hover:opacity-100 scale-50 group-hover:scale-100 text-white text-5xl" data-astro-cid-iyiqi2so="true" data-icon="material-symbols:chevron-right-rounded"> <use href="#ai:material-symbols:chevron-right-rounded"></use> </svg> </div> <div class="w-full h-full overflow-hidden relative image-wrapper" style="--theme-hue: 361" data-astro-cid-i2xmscho> <img src="/_astro/2025-08-04-12-14-21-image.NW2YsMSp.png" alt="Cover Image of the Post" style="object-position: center" data-astro-cid-i2xmscho="true" width="702" height="465" loading="lazy" decoding="async" class="w-full h-full object-cover image-content"> </div> </a> </div> <div class="transition border-t-[1px] border-dashed mx-6 border-black/10 dark:border-white/[0.15] last:border-t-0 hidden" data-astro-cid-iyiqi2so style="--coverWidth: 28%;"></div> </div><div class="onload-animation" style="animation-delay: calc(var(--content-delay) + 200ms);"> <div class="card-base card-hover flex flex-col w-full relative" style="undefined; --coverWidth: 28%;" data-astro-cid-iyiqi2so> <div class="pl-9 pr-2 pt-6 pb-6 relative w-[calc(100%_-_var(--coverWidth)_-_12px)]" data-astro-cid-iyiqi2so style="--coverWidth: 28%;"> <a href="/posts/hideimg/" class="transition group w-full block font-bold mb-2 md:mb-3 text-xl md:text-3xl text-90 relative
|
||
hover:text-[var(--primary)] dark:hover:text-[var(--primary)]
|
||
active:text-[var(--title-active)] dark:active:text-[var(--title-active)]
|
||
before:w-1 before:h-5 before:rounded-md before:bg-[var(--primary)]
|
||
before:absolute before:top-1 md:before:top-2 before:-left-[1.125rem] before:block
|
||
" data-astro-cid-iyiqi2so style="--coverWidth: 28%;"> 平平无奇的一张图,拉高曝光就能显现另一张图? </a> <!-- description --> <div class="transition text-75 mb-3.5 pr-4 line-clamp-1 md:line-clamp-2" data-astro-cid-iyiqi2so style="--coverWidth: 28%;"> 教你制作自己的“光棱坦克”! </div> <!-- metadata --> <div class="flex flex-wrap text-neutral-500 dark:text-neutral-400 items-center gap-4 gap-x-4 gap-y-2 mb-2 md:mb-4"> <!-- publish date --> <!-- update date --> <!-- page views & visitors --> <div class="flex items-center"> <div class="meta-icon"> <svg width="1em" height="1em" viewBox="0 0 24 24" class="text-xl" data-icon="material-symbols:visibility-outline-rounded"> <use href="#ai:material-symbols:visibility-outline-rounded"></use> </svg> </div> <span class="text-50 text-sm font-medium" id="page-views-hideimg">0 次</span> </div> <div class="flex items-center"> <div class="meta-icon"> <svg width="1em" height="1em" viewBox="0 0 24 24" class="text-xl" data-icon="material-symbols:person"> <use href="#ai:material-symbols:person"></use> </svg> </div> <span class="text-50 text-sm font-medium" id="page-visitors-hideimg">0 人</span> </div> </div> <script>(function(){const slug = "hideimg";
|
||
const umamiConfig = {"enable":true,"baseUrl":"https://umami.acofork.com","shareId":"CdkXbGgZr6ECKOyK","timezone":"Asia/Shanghai"};
|
||
|
||
// 数字动画函数
|
||
function animateValue(obj, start, end, duration, suffix = '') {
|
||
let startTimestamp = null;
|
||
const step = (timestamp) => {
|
||
if (!startTimestamp) startTimestamp = timestamp;
|
||
const progress = Math.min((timestamp - startTimestamp) / duration, 1);
|
||
obj.innerHTML = `${Math.floor(progress * (end - start) + start)} ${suffix}`;
|
||
if (progress < 1) {
|
||
window.requestAnimationFrame(step);
|
||
} else {
|
||
obj.innerHTML = `${end} ${suffix}`;
|
||
}
|
||
};
|
||
window.requestAnimationFrame(step);
|
||
}
|
||
|
||
// 获取访问量统计
|
||
async function fetchPageViews() {
|
||
if (!umamiConfig.enable) return;
|
||
try {
|
||
const statsData = await fetchUmamiStats(umamiConfig.baseUrl, umamiConfig.shareId, {
|
||
timezone: umamiConfig.timezone,
|
||
path: `eq./posts/${slug}/`
|
||
});
|
||
|
||
const pageViews = (statsData.pageviews && statsData.pageviews.value) || statsData.pageviews || 0;
|
||
const visits = (statsData.visitors && statsData.visitors.value) || statsData.visitors || 0;
|
||
|
||
const viewsElement = document.getElementById(`page-views-${slug}`);
|
||
const visitorsElement = document.getElementById(`page-visitors-${slug}`);
|
||
|
||
// 如果数据来自缓存,直接显示结果,跳过动画
|
||
if (statsData._fromCache) {
|
||
if (viewsElement) viewsElement.innerHTML = `${pageViews} 次`;
|
||
if (visitorsElement) visitorsElement.innerHTML = `${visits} 人`;
|
||
return;
|
||
}
|
||
|
||
if (viewsElement) {
|
||
const currentViews = parseInt(viewsElement.textContent) || 0;
|
||
if (currentViews !== pageViews) {
|
||
if (currentViews === 0) {
|
||
animateValue(viewsElement, currentViews, pageViews, 1000, '次');
|
||
} else {
|
||
viewsElement.innerHTML = `${pageViews} 次`;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (visitorsElement) {
|
||
const currentVisits = parseInt(visitorsElement.textContent) || 0;
|
||
if (currentVisits !== visits) {
|
||
if (currentVisits === 0) {
|
||
animateValue(visitorsElement, currentVisits, visits, 1000, '人');
|
||
} else {
|
||
visitorsElement.innerHTML = `${visits} 人`;
|
||
}
|
||
}
|
||
}
|
||
} catch (error) {
|
||
console.error('Error fetching page views:', error);
|
||
}
|
||
}
|
||
|
||
// 页面加载完成后获取统计数据
|
||
if (document.readyState === 'loading') {
|
||
document.addEventListener('DOMContentLoaded', fetchPageViews);
|
||
} else {
|
||
fetchPageViews();
|
||
}
|
||
})();</script> <!-- word count, read time and page views --> <div class="text-sm text-black/30 dark:text-white/30 flex gap-4 transition" data-astro-cid-iyiqi2so style="--coverWidth: 28%;"> <div data-astro-cid-iyiqi2so style="--coverWidth: 28%;">2025-08-04</div> <div data-astro-cid-iyiqi2so style="--coverWidth: 28%;">|</div> <div data-astro-cid-iyiqi2so style="--coverWidth: 28%;">141 字</div> <div data-astro-cid-iyiqi2so style="--coverWidth: 28%;">|</div> <div data-astro-cid-iyiqi2so style="--coverWidth: 28%;">1 分钟</div> </div> </div> <a href="/posts/hideimg/" aria-label="平平无奇的一张图,拉高曝光就能显现另一张图?" class="group max-h-none mx-0 mt-0 w-[var(--coverWidth)] absolute top-3 bottom-3 right-3 rounded-xl overflow-hidden active:scale-95" data-astro-cid-iyiqi2so style="--coverWidth: 28%;"> <div class="absolute pointer-events-none z-10 w-full h-full group-hover:bg-black/30 group-active:bg-black/50 transition" data-astro-cid-iyiqi2so style="--coverWidth: 28%;"></div> <!-- 封面图上的箭头 --> <div class="absolute pointer-events-none z-20 w-full h-full flex items-center justify-center " data-astro-cid-iyiqi2so style="--coverWidth: 28%;"> <svg width="1em" height="1em" viewBox="0 0 24 24" class="transition opacity-0 group-hover:opacity-100 scale-50 group-hover:scale-100 text-white text-5xl" data-astro-cid-iyiqi2so="true" data-icon="material-symbols:chevron-right-rounded"> <use href="#ai:material-symbols:chevron-right-rounded"></use> </svg> </div> <div class="w-full h-full overflow-hidden relative image-wrapper" style="--theme-hue: 361" data-astro-cid-i2xmscho> <img src="/_astro/2025-08-04-12-05-21-image.D9Pacm7p.png" alt="Cover Image of the Post" style="object-position: center" data-astro-cid-i2xmscho="true" width="739" height="720" loading="lazy" decoding="async" class="w-full h-full object-cover image-content"> </div> </a> </div> <div class="transition border-t-[1px] border-dashed mx-6 border-black/10 dark:border-white/[0.15] last:border-t-0 hidden" data-astro-cid-iyiqi2so style="--coverWidth: 28%;"></div> </div><div class="onload-animation" style="animation-delay: calc(var(--content-delay) + 250ms);"> <div class="card-base card-hover flex flex-col w-full relative" style="undefined; --coverWidth: 28%;" data-astro-cid-iyiqi2so> <div class="pl-9 pr-2 pt-6 pb-6 relative w-[calc(100%_-_var(--coverWidth)_-_12px)]" data-astro-cid-iyiqi2so style="--coverWidth: 28%;"> <a href="/posts/sshfs/" class="transition group w-full block font-bold mb-2 md:mb-3 text-xl md:text-3xl text-90 relative
|
||
hover:text-[var(--primary)] dark:hover:text-[var(--primary)]
|
||
active:text-[var(--title-active)] dark:active:text-[var(--title-active)]
|
||
before:w-1 before:h-5 before:rounded-md before:bg-[var(--primary)]
|
||
before:absolute before:top-1 md:before:top-2 before:-left-[1.125rem] before:block
|
||
" data-astro-cid-iyiqi2so style="--coverWidth: 28%;"> 将你的Linux硬盘映射到Windows? </a> <!-- description --> <div class="transition text-75 mb-3.5 pr-4 line-clamp-1 md:line-clamp-2" data-astro-cid-iyiqi2so style="--coverWidth: 28%;"> 如何像Windows一样管理Linux文件?SSHFS来帮你! </div> <!-- metadata --> <div class="flex flex-wrap text-neutral-500 dark:text-neutral-400 items-center gap-4 gap-x-4 gap-y-2 mb-2 md:mb-4"> <!-- publish date --> <!-- update date --> <!-- page views & visitors --> <div class="flex items-center"> <div class="meta-icon"> <svg width="1em" height="1em" viewBox="0 0 24 24" class="text-xl" data-icon="material-symbols:visibility-outline-rounded"> <use href="#ai:material-symbols:visibility-outline-rounded"></use> </svg> </div> <span class="text-50 text-sm font-medium" id="page-views-sshfs">0 次</span> </div> <div class="flex items-center"> <div class="meta-icon"> <svg width="1em" height="1em" viewBox="0 0 24 24" class="text-xl" data-icon="material-symbols:person"> <use href="#ai:material-symbols:person"></use> </svg> </div> <span class="text-50 text-sm font-medium" id="page-visitors-sshfs">0 人</span> </div> </div> <script>(function(){const slug = "sshfs";
|
||
const umamiConfig = {"enable":true,"baseUrl":"https://umami.acofork.com","shareId":"CdkXbGgZr6ECKOyK","timezone":"Asia/Shanghai"};
|
||
|
||
// 数字动画函数
|
||
function animateValue(obj, start, end, duration, suffix = '') {
|
||
let startTimestamp = null;
|
||
const step = (timestamp) => {
|
||
if (!startTimestamp) startTimestamp = timestamp;
|
||
const progress = Math.min((timestamp - startTimestamp) / duration, 1);
|
||
obj.innerHTML = `${Math.floor(progress * (end - start) + start)} ${suffix}`;
|
||
if (progress < 1) {
|
||
window.requestAnimationFrame(step);
|
||
} else {
|
||
obj.innerHTML = `${end} ${suffix}`;
|
||
}
|
||
};
|
||
window.requestAnimationFrame(step);
|
||
}
|
||
|
||
// 获取访问量统计
|
||
async function fetchPageViews() {
|
||
if (!umamiConfig.enable) return;
|
||
try {
|
||
const statsData = await fetchUmamiStats(umamiConfig.baseUrl, umamiConfig.shareId, {
|
||
timezone: umamiConfig.timezone,
|
||
path: `eq./posts/${slug}/`
|
||
});
|
||
|
||
const pageViews = (statsData.pageviews && statsData.pageviews.value) || statsData.pageviews || 0;
|
||
const visits = (statsData.visitors && statsData.visitors.value) || statsData.visitors || 0;
|
||
|
||
const viewsElement = document.getElementById(`page-views-${slug}`);
|
||
const visitorsElement = document.getElementById(`page-visitors-${slug}`);
|
||
|
||
// 如果数据来自缓存,直接显示结果,跳过动画
|
||
if (statsData._fromCache) {
|
||
if (viewsElement) viewsElement.innerHTML = `${pageViews} 次`;
|
||
if (visitorsElement) visitorsElement.innerHTML = `${visits} 人`;
|
||
return;
|
||
}
|
||
|
||
if (viewsElement) {
|
||
const currentViews = parseInt(viewsElement.textContent) || 0;
|
||
if (currentViews !== pageViews) {
|
||
if (currentViews === 0) {
|
||
animateValue(viewsElement, currentViews, pageViews, 1000, '次');
|
||
} else {
|
||
viewsElement.innerHTML = `${pageViews} 次`;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (visitorsElement) {
|
||
const currentVisits = parseInt(visitorsElement.textContent) || 0;
|
||
if (currentVisits !== visits) {
|
||
if (currentVisits === 0) {
|
||
animateValue(visitorsElement, currentVisits, visits, 1000, '人');
|
||
} else {
|
||
visitorsElement.innerHTML = `${visits} 人`;
|
||
}
|
||
}
|
||
}
|
||
} catch (error) {
|
||
console.error('Error fetching page views:', error);
|
||
}
|
||
}
|
||
|
||
// 页面加载完成后获取统计数据
|
||
if (document.readyState === 'loading') {
|
||
document.addEventListener('DOMContentLoaded', fetchPageViews);
|
||
} else {
|
||
fetchPageViews();
|
||
}
|
||
})();</script> <!-- word count, read time and page views --> <div class="text-sm text-black/30 dark:text-white/30 flex gap-4 transition" data-astro-cid-iyiqi2so style="--coverWidth: 28%;"> <div data-astro-cid-iyiqi2so style="--coverWidth: 28%;">2025-08-03</div> <div data-astro-cid-iyiqi2so style="--coverWidth: 28%;">|</div> <div data-astro-cid-iyiqi2so style="--coverWidth: 28%;">93 字</div> <div data-astro-cid-iyiqi2so style="--coverWidth: 28%;">|</div> <div data-astro-cid-iyiqi2so style="--coverWidth: 28%;">1 分钟</div> </div> </div> <a href="/posts/sshfs/" aria-label="将你的Linux硬盘映射到Windows?" class="group max-h-none mx-0 mt-0 w-[var(--coverWidth)] absolute top-3 bottom-3 right-3 rounded-xl overflow-hidden active:scale-95" data-astro-cid-iyiqi2so style="--coverWidth: 28%;"> <div class="absolute pointer-events-none z-10 w-full h-full group-hover:bg-black/30 group-active:bg-black/50 transition" data-astro-cid-iyiqi2so style="--coverWidth: 28%;"></div> <!-- 封面图上的箭头 --> <div class="absolute pointer-events-none z-20 w-full h-full flex items-center justify-center " data-astro-cid-iyiqi2so style="--coverWidth: 28%;"> <svg width="1em" height="1em" viewBox="0 0 24 24" class="transition opacity-0 group-hover:opacity-100 scale-50 group-hover:scale-100 text-white text-5xl" data-astro-cid-iyiqi2so="true" data-icon="material-symbols:chevron-right-rounded"> <use href="#ai:material-symbols:chevron-right-rounded"></use> </svg> </div> <div class="w-full h-full overflow-hidden relative image-wrapper" style="--theme-hue: 361" data-astro-cid-i2xmscho> <img src="/_astro/2025-08-03-19-15-42-image.NS6g0Mtj.png" alt="Cover Image of the Post" style="object-position: center" data-astro-cid-i2xmscho="true" width="700" height="500" loading="lazy" decoding="async" class="w-full h-full object-cover image-content"> </div> </a> </div> <div class="transition border-t-[1px] border-dashed mx-6 border-black/10 dark:border-white/[0.15] last:border-t-0 hidden" data-astro-cid-iyiqi2so style="--coverWidth: 28%;"></div> </div><div class="onload-animation" style="animation-delay: calc(var(--content-delay) + 300ms);"> <div class="card-base card-hover flex flex-col w-full relative" style="undefined; --coverWidth: 28%;" data-astro-cid-iyiqi2so> <div class="pl-9 pr-2 pt-6 pb-6 relative w-[calc(100%_-_var(--coverWidth)_-_12px)]" data-astro-cid-iyiqi2so style="--coverWidth: 28%;"> <a href="/posts/proxy-tgweb/" class="transition group w-full block font-bold mb-2 md:mb-3 text-xl md:text-3xl text-90 relative
|
||
hover:text-[var(--primary)] dark:hover:text-[var(--primary)]
|
||
active:text-[var(--title-active)] dark:active:text-[var(--title-active)]
|
||
before:w-1 before:h-5 before:rounded-md before:bg-[var(--primary)]
|
||
before:absolute before:top-1 md:before:top-2 before:-left-[1.125rem] before:block
|
||
" data-astro-cid-iyiqi2so style="--coverWidth: 28%;"> 大陆直连TG Web?触手可及! </a> <!-- description --> <div class="transition text-75 mb-3.5 pr-4 line-clamp-1 md:line-clamp-2" data-astro-cid-iyiqi2so style="--coverWidth: 28%;"> TG Web采用前后端分离,前端可以部署到静态托管平台,而后端可以用各种服务反代 </div> <!-- metadata --> <div class="flex flex-wrap text-neutral-500 dark:text-neutral-400 items-center gap-4 gap-x-4 gap-y-2 mb-2 md:mb-4"> <!-- publish date --> <!-- update date --> <!-- page views & visitors --> <div class="flex items-center"> <div class="meta-icon"> <svg width="1em" height="1em" viewBox="0 0 24 24" class="text-xl" data-icon="material-symbols:visibility-outline-rounded"> <use href="#ai:material-symbols:visibility-outline-rounded"></use> </svg> </div> <span class="text-50 text-sm font-medium" id="page-views-proxy-tgweb">0 次</span> </div> <div class="flex items-center"> <div class="meta-icon"> <svg width="1em" height="1em" viewBox="0 0 24 24" class="text-xl" data-icon="material-symbols:person"> <use href="#ai:material-symbols:person"></use> </svg> </div> <span class="text-50 text-sm font-medium" id="page-visitors-proxy-tgweb">0 人</span> </div> </div> <script>(function(){const slug = "proxy-tgweb";
|
||
const umamiConfig = {"enable":true,"baseUrl":"https://umami.acofork.com","shareId":"CdkXbGgZr6ECKOyK","timezone":"Asia/Shanghai"};
|
||
|
||
// 数字动画函数
|
||
function animateValue(obj, start, end, duration, suffix = '') {
|
||
let startTimestamp = null;
|
||
const step = (timestamp) => {
|
||
if (!startTimestamp) startTimestamp = timestamp;
|
||
const progress = Math.min((timestamp - startTimestamp) / duration, 1);
|
||
obj.innerHTML = `${Math.floor(progress * (end - start) + start)} ${suffix}`;
|
||
if (progress < 1) {
|
||
window.requestAnimationFrame(step);
|
||
} else {
|
||
obj.innerHTML = `${end} ${suffix}`;
|
||
}
|
||
};
|
||
window.requestAnimationFrame(step);
|
||
}
|
||
|
||
// 获取访问量统计
|
||
async function fetchPageViews() {
|
||
if (!umamiConfig.enable) return;
|
||
try {
|
||
const statsData = await fetchUmamiStats(umamiConfig.baseUrl, umamiConfig.shareId, {
|
||
timezone: umamiConfig.timezone,
|
||
path: `eq./posts/${slug}/`
|
||
});
|
||
|
||
const pageViews = (statsData.pageviews && statsData.pageviews.value) || statsData.pageviews || 0;
|
||
const visits = (statsData.visitors && statsData.visitors.value) || statsData.visitors || 0;
|
||
|
||
const viewsElement = document.getElementById(`page-views-${slug}`);
|
||
const visitorsElement = document.getElementById(`page-visitors-${slug}`);
|
||
|
||
// 如果数据来自缓存,直接显示结果,跳过动画
|
||
if (statsData._fromCache) {
|
||
if (viewsElement) viewsElement.innerHTML = `${pageViews} 次`;
|
||
if (visitorsElement) visitorsElement.innerHTML = `${visits} 人`;
|
||
return;
|
||
}
|
||
|
||
if (viewsElement) {
|
||
const currentViews = parseInt(viewsElement.textContent) || 0;
|
||
if (currentViews !== pageViews) {
|
||
if (currentViews === 0) {
|
||
animateValue(viewsElement, currentViews, pageViews, 1000, '次');
|
||
} else {
|
||
viewsElement.innerHTML = `${pageViews} 次`;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (visitorsElement) {
|
||
const currentVisits = parseInt(visitorsElement.textContent) || 0;
|
||
if (currentVisits !== visits) {
|
||
if (currentVisits === 0) {
|
||
animateValue(visitorsElement, currentVisits, visits, 1000, '人');
|
||
} else {
|
||
visitorsElement.innerHTML = `${visits} 人`;
|
||
}
|
||
}
|
||
}
|
||
} catch (error) {
|
||
console.error('Error fetching page views:', error);
|
||
}
|
||
}
|
||
|
||
// 页面加载完成后获取统计数据
|
||
if (document.readyState === 'loading') {
|
||
document.addEventListener('DOMContentLoaded', fetchPageViews);
|
||
} else {
|
||
fetchPageViews();
|
||
}
|
||
})();</script> <!-- word count, read time and page views --> <div class="text-sm text-black/30 dark:text-white/30 flex gap-4 transition" data-astro-cid-iyiqi2so style="--coverWidth: 28%;"> <div data-astro-cid-iyiqi2so style="--coverWidth: 28%;">2025-08-02</div> <div data-astro-cid-iyiqi2so style="--coverWidth: 28%;">|</div> <div data-astro-cid-iyiqi2so style="--coverWidth: 28%;">1723 字</div> <div data-astro-cid-iyiqi2so style="--coverWidth: 28%;">|</div> <div data-astro-cid-iyiqi2so style="--coverWidth: 28%;">9 分钟</div> </div> </div> <a href="/posts/proxy-tgweb/" aria-label="大陆直连TG Web?触手可及!" class="group max-h-none mx-0 mt-0 w-[var(--coverWidth)] absolute top-3 bottom-3 right-3 rounded-xl overflow-hidden active:scale-95" data-astro-cid-iyiqi2so style="--coverWidth: 28%;"> <div class="absolute pointer-events-none z-10 w-full h-full group-hover:bg-black/30 group-active:bg-black/50 transition" data-astro-cid-iyiqi2so style="--coverWidth: 28%;"></div> <!-- 封面图上的箭头 --> <div class="absolute pointer-events-none z-20 w-full h-full flex items-center justify-center " data-astro-cid-iyiqi2so style="--coverWidth: 28%;"> <svg width="1em" height="1em" viewBox="0 0 24 24" class="transition opacity-0 group-hover:opacity-100 scale-50 group-hover:scale-100 text-white text-5xl" data-astro-cid-iyiqi2so="true" data-icon="material-symbols:chevron-right-rounded"> <use href="#ai:material-symbols:chevron-right-rounded"></use> </svg> </div> <div class="w-full h-full overflow-hidden relative image-wrapper" style="--theme-hue: 361" data-astro-cid-i2xmscho> <img src="/_astro/2025-08-02-18-10-18-image.AbayxPCy.png" alt="Cover Image of the Post" style="object-position: center" data-astro-cid-i2xmscho="true" width="574" height="546" loading="lazy" decoding="async" class="w-full h-full object-cover image-content"> </div> </a> </div> <div class="transition border-t-[1px] border-dashed mx-6 border-black/10 dark:border-white/[0.15] last:border-t-0 hidden" data-astro-cid-iyiqi2so style="--coverWidth: 28%;"></div> </div><div class="onload-animation" style="animation-delay: calc(var(--content-delay) + 350ms);"> <div class="card-base card-hover flex flex-col w-full relative" style="undefined; --coverWidth: 28%;" data-astro-cid-iyiqi2so> <div class="pl-9 pr-2 pt-6 pb-6 relative w-[calc(100%_-_var(--coverWidth)_-_12px)]" data-astro-cid-iyiqi2so style="--coverWidth: 28%;"> <a href="/posts/self-host-matrix/" class="transition group w-full block font-bold mb-2 md:mb-3 text-xl md:text-3xl text-90 relative
|
||
hover:text-[var(--primary)] dark:hover:text-[var(--primary)]
|
||
active:text-[var(--title-active)] dark:active:text-[var(--title-active)]
|
||
before:w-1 before:h-5 before:rounded-md before:bg-[var(--primary)]
|
||
before:absolute before:top-1 md:before:top-2 before:-left-[1.125rem] before:block
|
||
" data-astro-cid-iyiqi2so style="--coverWidth: 28%;"> QQ微信不够私密?自建自己的聊天服务器! </a> <!-- description --> <div class="transition text-75 mb-3.5 pr-4 line-clamp-1 md:line-clamp-2" data-astro-cid-iyiqi2so style="--coverWidth: 28%;"> 通过自建Synapse,用户可以通过Element等软件来直接在你的服务器上聊天 </div> <!-- metadata --> <div class="flex flex-wrap text-neutral-500 dark:text-neutral-400 items-center gap-4 gap-x-4 gap-y-2 mb-2 md:mb-4"> <!-- publish date --> <!-- update date --> <!-- page views & visitors --> <div class="flex items-center"> <div class="meta-icon"> <svg width="1em" height="1em" viewBox="0 0 24 24" class="text-xl" data-icon="material-symbols:visibility-outline-rounded"> <use href="#ai:material-symbols:visibility-outline-rounded"></use> </svg> </div> <span class="text-50 text-sm font-medium" id="page-views-self-host-matrix">0 次</span> </div> <div class="flex items-center"> <div class="meta-icon"> <svg width="1em" height="1em" viewBox="0 0 24 24" class="text-xl" data-icon="material-symbols:person"> <use href="#ai:material-symbols:person"></use> </svg> </div> <span class="text-50 text-sm font-medium" id="page-visitors-self-host-matrix">0 人</span> </div> </div> <script>(function(){const slug = "self-host-matrix";
|
||
const umamiConfig = {"enable":true,"baseUrl":"https://umami.acofork.com","shareId":"CdkXbGgZr6ECKOyK","timezone":"Asia/Shanghai"};
|
||
|
||
// 数字动画函数
|
||
function animateValue(obj, start, end, duration, suffix = '') {
|
||
let startTimestamp = null;
|
||
const step = (timestamp) => {
|
||
if (!startTimestamp) startTimestamp = timestamp;
|
||
const progress = Math.min((timestamp - startTimestamp) / duration, 1);
|
||
obj.innerHTML = `${Math.floor(progress * (end - start) + start)} ${suffix}`;
|
||
if (progress < 1) {
|
||
window.requestAnimationFrame(step);
|
||
} else {
|
||
obj.innerHTML = `${end} ${suffix}`;
|
||
}
|
||
};
|
||
window.requestAnimationFrame(step);
|
||
}
|
||
|
||
// 获取访问量统计
|
||
async function fetchPageViews() {
|
||
if (!umamiConfig.enable) return;
|
||
try {
|
||
const statsData = await fetchUmamiStats(umamiConfig.baseUrl, umamiConfig.shareId, {
|
||
timezone: umamiConfig.timezone,
|
||
path: `eq./posts/${slug}/`
|
||
});
|
||
|
||
const pageViews = (statsData.pageviews && statsData.pageviews.value) || statsData.pageviews || 0;
|
||
const visits = (statsData.visitors && statsData.visitors.value) || statsData.visitors || 0;
|
||
|
||
const viewsElement = document.getElementById(`page-views-${slug}`);
|
||
const visitorsElement = document.getElementById(`page-visitors-${slug}`);
|
||
|
||
// 如果数据来自缓存,直接显示结果,跳过动画
|
||
if (statsData._fromCache) {
|
||
if (viewsElement) viewsElement.innerHTML = `${pageViews} 次`;
|
||
if (visitorsElement) visitorsElement.innerHTML = `${visits} 人`;
|
||
return;
|
||
}
|
||
|
||
if (viewsElement) {
|
||
const currentViews = parseInt(viewsElement.textContent) || 0;
|
||
if (currentViews !== pageViews) {
|
||
if (currentViews === 0) {
|
||
animateValue(viewsElement, currentViews, pageViews, 1000, '次');
|
||
} else {
|
||
viewsElement.innerHTML = `${pageViews} 次`;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (visitorsElement) {
|
||
const currentVisits = parseInt(visitorsElement.textContent) || 0;
|
||
if (currentVisits !== visits) {
|
||
if (currentVisits === 0) {
|
||
animateValue(visitorsElement, currentVisits, visits, 1000, '人');
|
||
} else {
|
||
visitorsElement.innerHTML = `${visits} 人`;
|
||
}
|
||
}
|
||
}
|
||
} catch (error) {
|
||
console.error('Error fetching page views:', error);
|
||
}
|
||
}
|
||
|
||
// 页面加载完成后获取统计数据
|
||
if (document.readyState === 'loading') {
|
||
document.addEventListener('DOMContentLoaded', fetchPageViews);
|
||
} else {
|
||
fetchPageViews();
|
||
}
|
||
})();</script> <!-- word count, read time and page views --> <div class="text-sm text-black/30 dark:text-white/30 flex gap-4 transition" data-astro-cid-iyiqi2so style="--coverWidth: 28%;"> <div data-astro-cid-iyiqi2so style="--coverWidth: 28%;">2025-08-02</div> <div data-astro-cid-iyiqi2so style="--coverWidth: 28%;">|</div> <div data-astro-cid-iyiqi2so style="--coverWidth: 28%;">840 字</div> <div data-astro-cid-iyiqi2so style="--coverWidth: 28%;">|</div> <div data-astro-cid-iyiqi2so style="--coverWidth: 28%;">4 分钟</div> </div> </div> <a href="/posts/self-host-matrix/" aria-label="QQ微信不够私密?自建自己的聊天服务器!" class="group max-h-none mx-0 mt-0 w-[var(--coverWidth)] absolute top-3 bottom-3 right-3 rounded-xl overflow-hidden active:scale-95" data-astro-cid-iyiqi2so style="--coverWidth: 28%;"> <div class="absolute pointer-events-none z-10 w-full h-full group-hover:bg-black/30 group-active:bg-black/50 transition" data-astro-cid-iyiqi2so style="--coverWidth: 28%;"></div> <!-- 封面图上的箭头 --> <div class="absolute pointer-events-none z-20 w-full h-full flex items-center justify-center " data-astro-cid-iyiqi2so style="--coverWidth: 28%;"> <svg width="1em" height="1em" viewBox="0 0 24 24" class="transition opacity-0 group-hover:opacity-100 scale-50 group-hover:scale-100 text-white text-5xl" data-astro-cid-iyiqi2so="true" data-icon="material-symbols:chevron-right-rounded"> <use href="#ai:material-symbols:chevron-right-rounded"></use> </svg> </div> <div class="w-full h-full overflow-hidden relative image-wrapper" style="--theme-hue: 361" data-astro-cid-i2xmscho> <img src="/_astro/2025-08-02-17-20-32-image.5NEDl4FG.png" alt="Cover Image of the Post" style="object-position: center" data-astro-cid-i2xmscho="true" width="545" height="505" loading="lazy" decoding="async" class="w-full h-full object-cover image-content"> </div> </a> </div> <div class="transition border-t-[1px] border-dashed mx-6 border-black/10 dark:border-white/[0.15] last:border-t-0 hidden" data-astro-cid-iyiqi2so style="--coverWidth: 28%;"></div> </div> </div> <div class="mx-auto onload-animation flex flex-row gap-3 justify-center" style="animation-delay: calc(var(--content-delay) + 400ms)"> <a href="/10/" aria-label="Previous Page" class="btn-card overflow-hidden rounded-lg text-[var(--primary)] w-11 h-11"> <svg width="1em" height="1em" class="text-[1.75rem]" data-icon="material-symbols:chevron-left-rounded"> <symbol id="ai:material-symbols:chevron-left-rounded" viewBox="0 0 24 24"><path fill="currentColor" d="m10.8 12l3.9 3.9q.275.275.275.7t-.275.7t-.7.275t-.7-.275l-4.6-4.6q-.15-.15-.212-.325T8.425 12t.063-.375t.212-.325l4.6-4.6q.275-.275.7-.275t.7.275t.275.7t-.275.7z"/></symbol><use href="#ai:material-symbols:chevron-left-rounded"></use> </svg> </a> <div class="bg-[var(--card-bg)] flex flex-row rounded-lg items-center text-neutral-700 dark:text-neutral-300 font-bold" style="backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);"> <a href="/" aria-label="Page 1" class="transition flex items-center justify-center w-11 h-11 rounded-lg overflow-hidden active:scale-[0.85] hover:bg-[var(--btn-card-bg-hover)] active:bg-[var(--btn-card-bg-active)] text-black/75 dark:text-white/75">1</a><svg width="1em" height="1em" class="mx-1" data-icon="material-symbols:more-horiz"> <symbol id="ai:material-symbols:more-horiz" viewBox="0 0 24 24"><path fill="currentColor" d="M6 14q-.825 0-1.412-.587T4 12t.588-1.412T6 10t1.413.588T8 12t-.587 1.413T6 14m6 0q-.825 0-1.412-.587T10 12t.588-1.412T12 10t1.413.588T14 12t-.587 1.413T12 14m6 0q-.825 0-1.412-.587T16 12t.588-1.412T18 10t1.413.588T20 12t-.587 1.413T18 14"/></symbol><use href="#ai:material-symbols:more-horiz"></use> </svg><a href="/9/" aria-label="Page 9" class="transition flex items-center justify-center w-11 h-11 rounded-lg overflow-hidden active:scale-[0.85] hover:bg-[var(--btn-card-bg-hover)] active:bg-[var(--btn-card-bg-active)] text-black/75 dark:text-white/75">9</a><a href="/10/" aria-label="Page 10" class="transition flex items-center justify-center w-11 h-11 rounded-lg overflow-hidden active:scale-[0.85] hover:bg-[var(--btn-card-bg-hover)] active:bg-[var(--btn-card-bg-active)] text-black/75 dark:text-white/75">10</a><div class="h-11 w-11 rounded-lg bg-[var(--primary)] flex items-center justify-center
|
||
font-bold text-white dark:text-black/70"> 11 </div><a href="/12/" aria-label="Page 12" class="transition flex items-center justify-center w-11 h-11 rounded-lg overflow-hidden active:scale-[0.85] hover:bg-[var(--btn-card-bg-hover)] active:bg-[var(--btn-card-bg-active)] text-black/75 dark:text-white/75">12</a><a href="/13/" aria-label="Page 13" class="transition flex items-center justify-center w-11 h-11 rounded-lg overflow-hidden active:scale-[0.85] hover:bg-[var(--btn-card-bg-hover)] active:bg-[var(--btn-card-bg-active)] text-black/75 dark:text-white/75">13</a><svg width="1em" height="1em" viewBox="0 0 24 24" class="mx-1" data-icon="material-symbols:more-horiz"> <use href="#ai:material-symbols:more-horiz"></use> </svg><a href="/19/" aria-label="Page 19" class="transition flex items-center justify-center w-11 h-11 rounded-lg overflow-hidden active:scale-[0.85] hover:bg-[var(--btn-card-bg-hover)] active:bg-[var(--btn-card-bg-active)] text-black/75 dark:text-white/75">19</a> </div> <a href="/12/" aria-label="Next Page" class="btn-card overflow-hidden rounded-lg text-[var(--primary)] w-11 h-11"> <svg width="1em" height="1em" viewBox="0 0 24 24" class="text-[1.75rem]" data-icon="material-symbols:chevron-right-rounded"> <use href="#ai:material-symbols:chevron-right-rounded"></use> </svg> </a> </div> </div> </main> <div class="footer col-span-2 row-start-3 lg:col-span-1 lg:col-start-2 lg:row-start-2 onload-animation"> <!--<div class="border-t border-[var(--primary)] mx-16 border-dashed py-8 max-w-[var(--page-width)] flex flex-col items-center justify-center px-6">--><div class="transition border-t border-black/10 dark:border-white/15 my-10 border-dashed mx-4 md:mx-32"></div> <div class="card-base w-fit mx-auto rounded-xl mt-4 mb-4"> <div class="transition text-50 text-sm text-center p-6">
|
||
© <span id="copyright-year">2024 - 2026</span> <a class="transition link text-[var(--primary)] font-medium" target="_blank" href="https://space.bilibili.com/325903362"> 二叉树树 </a>,采用
|
||
<a class="transition link text-[var(--primary)] font-medium" target="_blank" href="https://creativecommons.org/licenses/by-nc-sa/4.0/">CC BY-NC-SA 4.0</a> 许可
|
||
<br> <a class="transition link text-[var(--primary)] font-medium" target="_blank" href="/rss.xml">RSS</a> /
|
||
<a class="transition link text-[var(--primary)] font-medium" target="_blank" href="/sitemap-index.xml">网站地图</a> /
|
||
<!-- Below is the link that users can use to open Preferences Center to change their preferences. Do not modify the ID parameter. Place it where appropriate, style it as needed. --> <a class="transition link text-[var(--primary)] font-medium" href="#" id="open_preferences_center">更新您的Cookie</a> <br>
|
||
由
|
||
<a class="transition link text-[var(--primary)] font-medium" target="_blank" href="https://astro.build">Astro</a> 和
|
||
<a class="transition link text-[var(--primary)] font-medium" target="_blank" href="https://github.com/saicaca/fuwari">Fuwari</a> 强力驱动
|
||
<br>
|
||
本网站代码
|
||
<a class="transition link text-[var(--primary)] font-medium" target="_blank" href="https://github.com/afoim/fuwari">已开源</a> <a class="transition link text-black/30 dark:text-white/30 hover:text-[var(--primary)] text-xs ml-1" target="_blank" href="https://github.com/afoim/fuwari/commit/53e134f">(53e134f @ 2026-01-30 14:24:11)</a> <br> <a class="transition link text-[var(--primary)] font-medium inline-flex items-center" href="https://beian.miit.gov.cn/#/Integrated/index" target="_blank"><img alt="" src="/favicon/foot-icp.png" class="h-4 mr-1">皖ICP备2025099787号-2</a> <br> <div class="server-info-container flex flex-col items-center justify-center gap-1 mt-1"> <!-- Server info will be injected here --> </div> <!-- <a class="transition link text-[var(--primary)] font-medium inline-flex items-center" href="https://beian.mps.gov.cn/#/query/webSearch?code=34010302002608" target="_blank"><img alt="" src="/favicon/foot-ga.png" class="h-4 mr-1">皖公网安备34010302002608号</a>
|
||
<br> --> </div> </div> <script>(function(){const serverConfig = [{"url":"","text":"Blog"},{"url":"https://umami.acofork.com","text":"Umami"},{"url":"https://pic1.acofork.com","text":"RandomPic"}];
|
||
|
||
(() => {
|
||
if (window.__footerServerInit) return;
|
||
window.__footerServerInit = true;
|
||
|
||
function normalizeUrl(input) {
|
||
if (!input) return "";
|
||
return input.trim().replace(/:+$/, "");
|
||
}
|
||
|
||
function createServerEntry(config) {
|
||
const div = document.createElement('div');
|
||
div.className = 'flex items-center justify-center';
|
||
|
||
const label = document.createElement('span');
|
||
label.className = 'text-black/30 dark:text-white/30 text-xs mr-1';
|
||
label.innerText = `${config.text}:`;
|
||
div.appendChild(label);
|
||
|
||
const valueSpan = document.createElement('span');
|
||
valueSpan.className = 'server-value text-black/30 dark:text-white/30 text-xs';
|
||
valueSpan.innerText = '检测中...';
|
||
div.appendChild(valueSpan);
|
||
|
||
const iconImg = document.createElement('img');
|
||
iconImg.className = 'server-icon h-4 ml-1 hidden';
|
||
iconImg.alt = 'Server Icon';
|
||
div.appendChild(iconImg);
|
||
|
||
return { div, valueSpan, iconImg };
|
||
}
|
||
|
||
function updateEntryDisplay(elements, server) {
|
||
const { valueSpan, iconImg } = elements;
|
||
|
||
if (server) {
|
||
const serverLower = server.toLowerCase();
|
||
let iconSrc = null;
|
||
|
||
if (serverLower.includes('esa')) {
|
||
iconSrc = '/cdn/esa.svg';
|
||
} else if (serverLower.includes('edgeone')) {
|
||
iconSrc = '/cdn/eo.svg';
|
||
} else if (serverLower.includes('cloudflare')) {
|
||
iconSrc = '/cdn/cf.svg';
|
||
} else if (serverLower.includes('github')) {
|
||
iconSrc = '/cdn/gh.svg';
|
||
}
|
||
|
||
if (iconSrc) {
|
||
iconImg.src = iconSrc;
|
||
iconImg.classList.remove('hidden');
|
||
valueSpan.classList.add('hidden');
|
||
} else {
|
||
valueSpan.innerText = server;
|
||
iconImg.classList.add('hidden');
|
||
valueSpan.classList.remove('hidden');
|
||
}
|
||
} else {
|
||
valueSpan.innerText = "未知";
|
||
iconImg.classList.add('hidden');
|
||
valueSpan.classList.remove('hidden');
|
||
}
|
||
}
|
||
|
||
async function checkServer(url) {
|
||
try {
|
||
const targetUrl = normalizeUrl(url) || window.location.href;
|
||
const response = await fetch(targetUrl, { method: "HEAD" });
|
||
return response.headers.get('server');
|
||
} catch (error) {
|
||
console.warn(`Failed to fetch server info for ${url}:`, error);
|
||
return null;
|
||
}
|
||
}
|
||
|
||
async function initServerInfo() {
|
||
const containers = document.querySelectorAll('.server-info-container');
|
||
if (containers.length === 0) return;
|
||
|
||
// Check for Dev Mode
|
||
const isDevMode = localStorage.getItem("dev-mode") === "true";
|
||
if (isDevMode) {
|
||
const devServer = localStorage.getItem("dev-server");
|
||
containers.forEach(container => {
|
||
container.innerHTML = '';
|
||
const elements = createServerEntry({ text: 'Dev Node' });
|
||
container.appendChild(elements.div);
|
||
updateEntryDisplay(elements, devServer);
|
||
});
|
||
return;
|
||
}
|
||
|
||
window.__serverInfoCache = window.__serverInfoCache || {};
|
||
const cache = window.__serverInfoCache;
|
||
|
||
const getServerInfo = (url) => {
|
||
const key = normalizeUrl(url);
|
||
if (cache[key]) return cache[key];
|
||
cache[key] = checkServer(key);
|
||
return cache[key];
|
||
};
|
||
|
||
containers.forEach(container => {
|
||
container.innerHTML = '';
|
||
|
||
if (!serverConfig || serverConfig.length === 0) {
|
||
const elements = createServerEntry({ text: '访问节点' });
|
||
container.appendChild(elements.div);
|
||
getServerInfo('').then(server => updateEntryDisplay(elements, server));
|
||
return;
|
||
}
|
||
|
||
serverConfig.forEach((config) => {
|
||
const elements = createServerEntry(config);
|
||
container.appendChild(elements.div);
|
||
getServerInfo(config.url).then(server => updateEntryDisplay(elements, server));
|
||
});
|
||
});
|
||
}
|
||
|
||
initServerInfo();
|
||
document.addEventListener('astro:after-swap', initServerInfo);
|
||
document.addEventListener('content:replace', initServerInfo);
|
||
})();
|
||
})();</script> </div> </div> <!-- There can't be a filter on parent element, or it will break `fixed` --><div class="back-to-top-wrapper hidden lg:block" data-astro-cid-eymb5ayk> <div id="go-to-comments-btn" class="back-to-top-btn hide flex items-center rounded-2xl overflow-hidden transition" onclick="goToComments()" data-astro-cid-eymb5ayk> <button aria-label="Go to Comments" class="btn-card h-[3.75rem] w-[3.75rem]" data-astro-cid-eymb5ayk> <svg width="1em" height="1em" class="mx-auto" data-astro-cid-eymb5ayk="true" data-icon="material-symbols:comment-rounded"> <symbol id="ai:material-symbols:comment-rounded" viewBox="0 0 24 24"><path fill="currentColor" d="M7 14h10q.425 0 .713-.288T18 13t-.288-.712T17 12H7q-.425 0-.712.288T6 13t.288.713T7 14m0-3h10q.425 0 .713-.288T18 10t-.288-.712T17 9H7q-.425 0-.712.288T6 10t.288.713T7 11m0-3h10q.425 0 .713-.288T18 7t-.288-.712T17 6H7q-.425 0-.712.288T6 7t.288.713T7 8M4 18q-.825 0-1.412-.587T2 16V4q0-.825.588-1.412T4 2h16q.825 0 1.413.588T22 4v15.575q0 .675-.612.938T20.3 20.3L18 18z"/></symbol><use href="#ai:material-symbols:comment-rounded"></use> </svg> </button> </div> <div id="back-to-top-btn" class="back-to-top-btn hide flex items-center rounded-2xl overflow-hidden transition" onclick="backToTop()" data-astro-cid-eymb5ayk> <button aria-label="Back to Top" class="btn-card h-[3.75rem] w-[3.75rem]" data-astro-cid-eymb5ayk> <svg width="1em" height="1em" class="mx-auto" data-astro-cid-eymb5ayk="true" data-icon="material-symbols:keyboard-arrow-up-rounded"> <symbol id="ai:material-symbols:keyboard-arrow-up-rounded" viewBox="0 0 24 24"><path fill="currentColor" d="m12 10.8l-3.9 3.9q-.275.275-.7.275t-.7-.275t-.275-.7t.275-.7l4.6-4.6q.3-.3.7-.3t.7.3l4.6 4.6q.275.275.275.7t-.275.7t-.7.275t-.7-.275z"/></symbol><use href="#ai:material-symbols:keyboard-arrow-up-rounded"></use> </svg> </button> </div> </div> <script>
|
||
function backToTop() {
|
||
window.scroll({ top: 0, behavior: 'smooth' });
|
||
}
|
||
|
||
function goToComments() {
|
||
const comments = document.getElementById('giscus-container');
|
||
if (comments) {
|
||
comments.scrollIntoView({ behavior: 'smooth' });
|
||
}
|
||
}
|
||
</script> </div> </div> <div class="absolute w-full z-0 hidden 2xl:block"> <div class="relative max-w-[var(--page-width)] mx-auto"> <!-- TOC component --> <div id="toc-wrapper" class="hidden lg:block transition absolute top-0 -right-[var(--toc-width)] w-[var(--toc-width)] flex items-center"> <div id="toc-inner-wrapper" class="fixed top-14 w-[var(--toc-width)] h-[calc(100vh_-_20rem)] overflow-y-scroll overflow-x-hidden hide-scrollbar"> <div id="toc" class="w-full h-full transition-swup-fade "> <div class="h-8 w-full"></div> <script type="module">class o extends HTMLElement{tocEl=null;visibleClass="visible";observer;anchorNavTarget=null;headingIdxMap=new Map;headings=[];sections=[];tocEntries=[];active=[];activeIndicator=null;constructor(){super(),this.observer=new IntersectionObserver(this.markVisibleSection,{threshold:0})}markVisibleSection=t=>{if(t.forEach(e=>{const i=e.target.children[0]?.getAttribute("id"),s=i?this.headingIdxMap.get(i):void 0;s!=null&&(this.active[s]=e.isIntersecting),e.isIntersecting&&this.anchorNavTarget==e.target.firstChild&&(this.anchorNavTarget=null)}),!this.active.includes(!0)){this.activeIndicator?.setAttribute("style","display: none;"),this.fallback();return}this.update()};toggleActiveHeading=()=>{let t=this.active.length-1,e=this.active.length-1,i=0;for(;t>=0&&!this.active[t];)this.tocEntries[t].classList.remove(this.visibleClass),t--;for(;t>=0&&this.active[t];)this.tocEntries[t].classList.add(this.visibleClass),e=Math.min(e,t),i=Math.max(i,t),t--;for(;t>=0;)this.tocEntries[t].classList.remove(this.visibleClass),t--;let s=this.tocEntries[e].offsetTop,n=this.tocEntries[i].offsetTop+this.tocEntries[i].offsetHeight;this.activeIndicator?.setAttribute("style",`display: block; top: ${s}px; height: ${n-s}px`)};scrollToActiveHeading=()=>{if(this.anchorNavTarget||!this.tocEl)return;const t=document.querySelectorAll(`#toc .${this.visibleClass}`);if(!t.length)return;const e=t[0],i=t[t.length-1],s=this.tocEl.clientHeight;let n;i.getBoundingClientRect().bottom-e.getBoundingClientRect().top<.9*s?n=e.offsetTop-32:n=i.offsetTop-s*.8,this.tocEl.scrollTo({top:n,left:0,behavior:"smooth"})};update=()=>{requestAnimationFrame(()=>{this.toggleActiveHeading(),this.scrollToActiveHeading()})};fallback=()=>{if(this.sections.length)for(let t=0;t<this.sections.length;t++){let e=this.sections[t].getBoundingClientRect().top,i=this.sections[t].getBoundingClientRect().bottom;if(this.isInRange(e,0,window.innerHeight)||this.isInRange(i,0,window.innerHeight)||e<0&&i>window.innerHeight)this.markActiveHeading(t);else if(e>window.innerHeight)break}};markActiveHeading=t=>{this.active[t]=!0};handleAnchorClick=t=>{const e=t.composedPath().find(i=>i instanceof HTMLAnchorElement);if(e){const i=decodeURIComponent(e.hash?.substring(1)),s=this.headingIdxMap.get(i);s!==void 0?this.anchorNavTarget=this.headings[s]:this.anchorNavTarget=null}};isInRange(t,e,i){return e<t&&t<i}connectedCallback(){const t=document.querySelector(".prose");t?t.addEventListener("animationend",()=>{this.init()},{once:!0}):console.debug("Animation element not found")}init(){if(this.tocEl=document.getElementById("toc-inner-wrapper"),!!this.tocEl&&(this.tocEl.addEventListener("click",this.handleAnchorClick,{capture:!0}),this.activeIndicator=document.getElementById("active-indicator"),this.tocEntries=Array.from(document.querySelectorAll("#toc a[href^='#']")),this.tocEntries.length!==0)){this.sections=new Array(this.tocEntries.length),this.headings=new Array(this.tocEntries.length);for(let t=0;t<this.tocEntries.length;t++){const e=decodeURIComponent(this.tocEntries[t].hash?.substring(1)),i=document.getElementById(e),s=i?.parentElement;i instanceof HTMLElement&&s instanceof HTMLElement&&(this.headings[t]=i,this.sections[t]=s,this.headingIdxMap.set(e,t))}this.active=new Array(this.tocEntries.length).fill(!1),this.sections.forEach(t=>this.observer.observe(t)),this.fallback(),this.update()}}disconnectedCallback(){this.sections.forEach(t=>this.observer.unobserve(t)),this.observer.disconnect(),this.tocEl?.removeEventListener("click",this.handleAnchorClick)}}customElements.get("table-of-contents")||customElements.define("table-of-contents",o);</script> <div class="h-8 w-full"></div> </div> </div> </div> <!-- #toc needs to exist for Swup to work normally --> </div> </div> <!-- increase the page height during page transition to prevent the scrolling animation from jumping --> <div id="page-height-extend" class="hidden h-[300vh]" data-astro-cid-sckkx6r4 style="--bannerOffset: 15vh;--banner-height-home: 65vh;--banner-height: 35vh;--configHue: 361;--page-width: 75rem;--bg-url: url(/random/h);--bg-enable: 1;--bg-position: center;--bg-size: cover;--bg-repeat: no-repeat;--bg-attachment: fixed;--bg-opacity: 1;--configHue: 361;"></div> <script type="module" src="/_astro/Layout.astro_astro_type_script_index_0_lang.BoB-OW5-.js"></script> <script type="module" src="/_astro/Layout.astro_astro_type_script_index_1_lang.BK9HixGO.js"></script> <svg style="position: absolute; width: 0; height: 0; overflow: hidden;; --bannerOffset: 15vh;--banner-height-home: 65vh;--banner-height: 35vh;--configHue: 361;--page-width: 75rem;--bg-url: url(/random/h);--bg-enable: 1;--bg-position: center;--bg-size: cover;--bg-repeat: no-repeat;--bg-attachment: fixed;--bg-opacity: 1;--configHue: 361;" aria-hidden="true" data-astro-cid-sckkx6r4> <defs data-astro-cid-sckkx6r4 style="--bannerOffset: 15vh;--banner-height-home: 65vh;--banner-height: 35vh;--configHue: 361;--page-width: 75rem;--bg-url: url(/random/h);--bg-enable: 1;--bg-position: center;--bg-size: cover;--bg-repeat: no-repeat;--bg-attachment: fixed;--bg-opacity: 1;--configHue: 361;"> <filter id="liquid-glass" data-astro-cid-sckkx6r4 style="--bannerOffset: 15vh;--banner-height-home: 65vh;--banner-height: 35vh;--configHue: 361;--page-width: 75rem;--bg-url: url(/random/h);--bg-enable: 1;--bg-position: center;--bg-size: cover;--bg-repeat: no-repeat;--bg-attachment: fixed;--bg-opacity: 1;--configHue: 361;"> <feTurbulence type="fractalNoise" baseFrequency="0.05" numOctaves="2" result="noise" data-astro-cid-sckkx6r4 style="--bannerOffset: 15vh;--banner-height-home: 65vh;--banner-height: 35vh;--configHue: 361;--page-width: 75rem;--bg-url: url(/random/h);--bg-enable: 1;--bg-position: center;--bg-size: cover;--bg-repeat: no-repeat;--bg-attachment: fixed;--bg-opacity: 1;--configHue: 361;"></feTurbulence> <feDisplacementMap in="SourceGraphic" in2="noise" scale="20" xChannelSelector="R" yChannelSelector="G" data-astro-cid-sckkx6r4 style="--bannerOffset: 15vh;--banner-height-home: 65vh;--banner-height: 35vh;--configHue: 361;--page-width: 75rem;--bg-url: url(/random/h);--bg-enable: 1;--bg-position: center;--bg-size: cover;--bg-repeat: no-repeat;--bg-attachment: fixed;--bg-opacity: 1;--configHue: 361;"></feDisplacementMap> </filter> </defs> </svg></body></html> |