Files
blog/categories/site-notes/index.html
T
biss ebd245deb2 upgrade astro
-- [CST 2026-10-02 Friday 21:58:32]
2026-10-02 21:58:32 +08:00

373 lines
50 KiB
HTML

<!DOCTYPE html><html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="description" content="Personal blog by biss."><meta name="author" content="biss"><link rel="canonical" href="https://blog.biss.click/categories/site-notes/"><link rel="alternate" type="application/rss+xml" title="Bi's Blog RSS" href="https://blog.biss.click/rss.xml"><meta property="og:site_name" content="Bi's Blog"><meta property="og:locale" content="zh_CN"><meta property="og:type" content="website"><meta property="og:title" content="建站手札 | Bi's Blog"><meta property="og:description" content="Personal blog by biss."><meta property="og:url" content="https://blog.biss.click/categories/site-notes/"><meta property="og:image" content="https://free.picui.cn/free/2025/08/10/689845496a283.png"><meta property="og:image:alt" content="建站手札"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:title" content="建站手札 | Bi's Blog"><meta name="twitter:description" content="Personal blog by biss."><meta name="twitter:image" content="https://free.picui.cn/free/2025/08/10/689845496a283.png"><link rel="icon" href="/images/Bi.ico"><link rel="manifest" href="/manifest.webmanifest"><link rel="apple-touch-icon" href="/images/apple-touch-icon.png"><meta name="theme-color" content="#f7f5ef" media="(prefers-color-scheme: light)"><meta name="theme-color" content="#0b1014" media="(prefers-color-scheme: dark)"><script defer src="https://umami.biss.click/script.js" data-website-id="3d97b310-b241-4fc6-bc9c-68e317fc7d42"></script><script>window.SITE_CONFIG = {"site":{"url":"https://blog.biss.click","name":"Bi's Blog","description":"Personal blog by biss.","language":"zh-CN","domain":"blog.biss.click","slogan":"好奇心转化为代码的空间。","startTime":"2025-01-01T00:00:00+08:00","copyrightStartYear":2025,"license":"内容采用 CC BY-NC-SA 4.0 协议"},"author":{"name":"biss","email":"bishsh2006@gmail.com","github":"https://github.com/bishshi","avatar":"https://free.picui.cn/free/2025/08/10/689845496a283.png"},"comments":{"envId":"https://comment.biss.click","region":"","script":"https://cdn.jsdelivr.net/npm/twikoo@1.7.7/dist/twikoo.min.js"},"analytics":{"umami":{"script":"https://umami.biss.click/script.js","websiteId":"3d97b310-b241-4fc6-bc9c-68e317fc7d42","statsEndpoint":"https://blogumami.biss.click"}},"talks":{"apiUrl":"https://mm.biss.click/api/echo/page","pageSize":30,"homeLimit":6,"cacheKey":"talksCache","cacheTimeKey":"talksCacheTime","cacheDurationMs":1800000,"fallbackAvatar":"https://free.picui.cn/free/2025/08/10/689845496a283.png"},"search":{"apiKey":"2uxQzk7eD2GBCljdSmIiuU3ause7UK9n","server":{"host":"typesense.biss.click","port":"443","protocol":"https"},"indexName":"blogs","searchParams":{"query_by":"title,content","highlight_full_fields":"title,content","per_page":8,"num_typos":1,"typo_tokens_threshold":1,"prefix":true},"ui":{"maxRetries":10,"retryDelay":100,"animationDuration":300,"maxInitRetries":30,"placeholder":"输入关键词寻找故事..."}},"externalLinks":{"waitSeconds":10,"whitelist":["blog.biss.click","biss.click","github.com","localhost","127.0.0.1"]}};</script><script>
(() => {
const storageKey = 'site-theme';
const media = window.matchMedia('(prefers-color-scheme: dark)');
const getSystemTheme = () => (media.matches ? 'dark' : 'light');
const getSavedTheme = () => {
try {
const theme = localStorage.getItem(storageKey);
return theme === 'dark' || theme === 'light' ? theme : null;
} catch {
return null;
}
};
document.documentElement.dataset.theme = getSavedTheme() || getSystemTheme();
})();
</script><link rel="stylesheet" href="https://cdn.jsdmirror.com/npm/instantsearch.css/themes/reset-min.css"><link rel="stylesheet" href="https://cdn.jsdmirror.com/npm/@fancyapps/ui@5.0/dist/fancybox/fancybox.css"><link rel="stylesheet" href="https://cdn.jsdmirror.com/npm/@fortawesome/fontawesome-free@6.7.2/css/all.min.css"><title>建站手札 | Bi&#39;s Blog</title><link rel="stylesheet" href="/_astro/BaseLayout.BC0-3eVR.css"></head><body><header class="site-header"><nav class="nav"><a class="brand" href="/" aria-label="Bi's Blog 首页"><span>biss</span><i>.log</i></a><button class="nav-menu-toggle" type="button" aria-label="打开菜单" aria-expanded="false" data-nav-toggle><i class="fa-solid fa-bars nav-menu-open" aria-hidden="true"></i><i class="fa-solid fa-xmark nav-menu-close" aria-hidden="true"></i></button><div class="nav-drawer-backdrop" data-nav-backdrop></div><div class="nav-menu" data-nav-menu><div class="nav-links nav-center"><a href="/archives/"><i class="fa-solid fa-box-archive nav-icon" aria-hidden="true"></i><span>归档</span></a><a href="/categories/"><i class="fa-solid fa-folder-open nav-icon" aria-hidden="true"></i><span>分类</span></a><a href="/tags/"><i class="fa-solid fa-tags nav-icon" aria-hidden="true"></i><span>标签</span></a><a href="/shuoshuo/"><i class="fa-regular fa-comments nav-icon" aria-hidden="true"></i><span>说说</span></a><a href="/about/"><i class="fa-solid fa-heart nav-icon" aria-hidden="true"></i><span>关于</span></a><a href="/link/"><i class="fa-solid fa-link nav-icon" aria-hidden="true"></i><span>友链</span></a></div><div class="nav-links nav-actions"><button class="nav-random" type="button" onclick="randomPost()" aria-label="前往随机文章" title="前往随机文章"><i class="fa-solid fa-shuffle nav-icon" aria-hidden="true"></i><span>随机文章</span></button><button class="nav-search search-typesense-trigger" type="button" aria-label="搜索" title="搜索"><i class="fa-solid fa-magnifying-glass nav-icon" aria-hidden="true"></i><span>搜索</span></button><button class="nav-console" type="button" aria-label="打开中控台" title="中控台" data-console-open><i class="fa-solid fa-gauge-high nav-icon" aria-hidden="true"></i><span>中控台</span></button><button class="theme-toggle" type="button" aria-label="切换夜间模式" title="切换夜间模式" data-theme-toggle><i class="fa-solid fa-sun theme-toggle-sun nav-icon" aria-hidden="true"></i><i class="fa-solid fa-moon theme-toggle-moon nav-icon" aria-hidden="true"></i></button></div></div></nav></header><div class="control-console" data-console-modal aria-hidden="true"><div class="control-console-backdrop" data-console-close></div><section class="control-console-panel" role="dialog" aria-modal="true" aria-labelledby="control-console-title" tabindex="-1"><header class="control-console-head"><div><p>CONTROL CENTER</p><h2 id="control-console-title">中控台</h2></div><button class="control-console-close" type="button" aria-label="关闭中控台" title="关闭" data-console-close><i class="fa-solid fa-xmark" aria-hidden="true"></i></button></header><div class="control-console-grid"><a class="control-site-card" href="https://biss.click" target="_blank" rel="noreferrer"><i class="fa-solid fa-house-chimney" aria-hidden="true"></i><span><strong>主站入口</strong><em>个人主页与常用入口集合</em></span><small>biss.click</small></a><a class="control-site-card" href="https://mm.biss.click" target="_blank" rel="noreferrer"><i class="fa-regular fa-comments" aria-hidden="true"></i><span><strong>说说动态</strong><em>短句、碎片记录和近况更新</em></span><small>mm.biss.click</small></a><a class="control-site-card" href="https://comment.biss.click" target="_blank" rel="noreferrer"><i class="fa-solid fa-message" aria-hidden="true"></i><span><strong>评论系统</strong><em>Twikoo 评论服务与访客互动</em></span><small>comment.biss.click</small></a><a class="control-site-card" href="https://umami.biss.click" target="_blank" rel="noreferrer"><i class="fa-solid fa-chart-line" aria-hidden="true"></i><span><strong>站点统计</strong><em>Umami 访问统计与站点数据</em></span><small>umami.biss.click</small></a></div><div class="control-console-info" aria-label="站点信息"><section><span>当前站点</span><strong>blog.biss.click</strong></section><section><span>站点作者</span><strong>biss</strong></section><section><span>运行起点</span><strong>2025-01-01</strong></section></div></section></div><main><section class="content-wrap"><header class="page-header-card"><p class="page-header-eyebrow">Bi&#39;s Blog</p><h1>建站手札</h1><p class="page-header-subtitle">共 18 篇文章</p></header><div class="post-list"><article class="post-card"><a class="post-card-main" href="/posts/8f3b9d21/"><span class="post-card-index" aria-hidden="true"><small>LOG</small><strong>06.19</strong></span><span class="post-card-copy"><time datetime="2026-06-19T16:45:00.000Z">2026/06/20</time><span class="post-card-title">网站迁移日志</span><span class="post-card-summary">这篇文章记录一次个人网站迁移过程:为什么要从旧的博客构建流程迁到 Astro,迁移时处理了哪些内容、路由、评论、统计和搜索问题,以及这次折腾之后留下的一些经验。</span></span><span class="post-card-open" aria-hidden="true">↗</span></a><div class="meta-list"><a href="/categories/site-notes/">建站手札</a><a href="/tags/%E7%BD%91%E7%AB%99/">#网站</a><a href="/tags/Astro/">#Astro</a><a href="/tags/%E8%BF%81%E7%A7%BB/">#迁移</a></div></article><article class="post-card"><a class="post-card-main" href="/posts/4c91a8f2/"><span class="post-card-index" aria-hidden="true"><small>LOG</small><strong>06.19</strong></span><span class="post-card-copy"><time datetime="2026-06-19T08:58:00.000Z">2026/06/19</time><span class="post-card-title">用 Umami 分享链接给网站信息卡提供统计数据</span><span class="post-card-summary">这篇文章记录如何通过 Umami 的分享链接获取公开统计数据,再用 Cloudflare Worker 做一层缓存代理,最后把访客数和访问量显示到博客侧边栏的网站信息卡里。</span></span><span class="post-card-open" aria-hidden="true">↗</span></a><div class="meta-list"><a href="/categories/site-notes/">建站手札</a><a href="/tags/%E7%BD%91%E7%AB%99/">#网站</a><a href="/tags/Umami/">#Umami</a><a href="/tags/Cloudflare%20Worker/">#Cloudflare Worker</a></div></article><article class="post-card"><a class="post-card-main" href="/posts/7e921903/"><span class="post-card-index" aria-hidden="true"><small>LOG</small><strong>02.10</strong></span><span class="post-card-copy"><time datetime="2026-02-10T07:11:14.000Z">2026/02/10</time><span class="post-card-title">添加网站左上角菜单</span><span class="post-card-summary">这篇文章详细介绍了如何在柳神的网站上添加一个自定义的左上角菜单,包括菜单的结构、样式以及响应式设计。作者提供了具体的HTML和CSS代码示例,展示了如何实现一个包含多个链接和功能的导航栏,同时确保在不同屏幕尺寸下的适配性。此外,还解释了一些关键的CSS属性和JavaScript交互效果,以实现平滑的菜单显示和隐藏。通过这些步骤,用户可以轻松地自定义和美化网站的顶部导航栏,提升用户体验。</span></span><span class="post-card-open" aria-hidden="true">↗</span></a><div class="meta-list"><a href="/categories/site-notes/">建站手札</a><a href="/tags/%E7%BD%91%E7%AB%99/">#网站</a></div></article><article class="post-card"><a class="post-card-main" href="/posts/f287c563/"><span class="post-card-index" aria-hidden="true"><small>LOG</small><strong>02.05</strong></span><span class="post-card-copy"><time datetime="2026-02-05T13:14:16.000Z">2026/02/05</time><span class="post-card-title">添加typesense搜索</span><span class="post-card-summary">这篇文章介绍了如何在博客中集成Typesense搜索引擎,包括安装Typesense、添加数据集以及同步数据的详细步骤。首先,通过命令行安装Typesense并配置相关参数,如API密钥和数据目录。接着,安装必要的npm包,并在Hexo博客中配置搜索功能,指定存储搜索数据的JSON文件路径。然后,编写了一个同步脚本,用于读取XML文件、解析数据、检查或创建集合以及导入数据到Typesense。最后,在博客底部添加了InstantSearch和Typesense的JavaScript库,并根据实际情况修改了配置。</span></span><span class="post-card-open" aria-hidden="true">↗</span></a><div class="meta-list"><a href="/categories/tech/">技术</a><a href="/categories/site-notes/">建站手札</a></div></article><article class="post-card"><a class="post-card-main" href="/posts/b5601a7e/"><span class="post-card-index" aria-hidden="true"><small>LOG</small><strong>01.16</strong></span><span class="post-card-copy"><time datetime="2026-01-16T07:47:15.000Z">2026/01/16</time><span class="post-card-title">自定义字体</span><span class="post-card-summary">这篇文章讨论了如何自定义网站字体,以提升网站的美观性和用户体验。作者首先提到了在移动端和电脑上使用woff或woff2字体能够完美显示的重要性,并提到谷歌字体库可能已经可以直接在中国大陆访问,这使得自定义字体的需求可能不再那么迫切。接着,文章详细介绍了如何在网上寻找并下载喜欢的字体,包括字体格式的转换方法。然后,展示了如何在CSS文件中添加字体,包括如何声明字体族和指定字体文件的路径。最后,文章还提供了关于其他字体格式的参考,并指导如何在主题文件的font配置区域修改字体设置。</span></span><span class="post-card-open" aria-hidden="true">↗</span></a><div class="meta-list"><a href="/categories/site-notes/">建站手札</a><a href="/tags/%E7%BD%91%E7%AB%99/">#网站</a></div></article><article class="post-card"><a class="post-card-main" href="/posts/5ed2f1e6/"><span class="post-card-index" aria-hidden="true"><small>LOG</small><strong>01.16</strong></span><span class="post-card-copy"><time datetime="2026-01-16T07:47:07.000Z">2026/01/16</time><span class="post-card-title">在侧边栏添加日历和倒计时</span><span class="post-card-summary">实现了一个侧边栏日历与倒计时卡片,包含以下核心功能:日历展示:显示当前日期(公历与农历)、星期、生肖、干支年份。动态生成当月日历网格,高亮当天日期。倒计时模块:距离除夕倒计时:实时计算并显示剩余天数(示例中为2026年2月16日)。进度条:分别展示本年、本月、本周的已过去进度(百分比)及剩余天数。农历支持:调用 chinese-lunar.js 库将公历转换为农历,格式化显示为“干支年+生肖年+农历月+农历日”。</span></span><span class="post-card-open" aria-hidden="true">↗</span></a><div class="meta-list"><a href="/categories/site-notes/">建站手札</a><a href="/tags/%E7%BD%91%E7%AB%99/">#网站</a></div></article><article class="post-card"><a class="post-card-main" href="/posts/3a26a97a/"><span class="post-card-index" aria-hidden="true"><small>LOG</small><strong>08.25</strong></span><span class="post-card-copy"><time datetime="2025-08-25T22:03:00.000Z">2025/08/26</time><span class="post-card-title">为博客添加CMS系统</span><span class="post-card-summary">这篇文章介绍了如何为Hexo博客添加一个基于Sveltia CMS的CMS系统。首先,作者通过npm安装了Sveltia CMS,并在博客源码目录下创建了必要的文件和目录结构。接着,作者详细说明了如何在config.yml文件中配置CMS,包括字段定义、页面和集合的设置。由于作者使用的是自己的服务器,无法使用官方的认证系统,因此他还讲解了如何配置GitHub OAuth应用,并在Cloudflare上设置环境变量以支持CI/CD流程。最后,作者指出完成这些步骤后,可以通过访问博客的admin后台来管理内容。</span></span><span class="post-card-open" aria-hidden="true">↗</span></a><div class="meta-list"><a href="/categories/site-notes/">建站手札</a><a href="/tags/%E7%BD%91%E7%AB%99/">#网站</a></div></article><article class="post-card"><a class="post-card-main" href="/posts/ce1ec3fe/"><span class="post-card-index" aria-hidden="true"><small>LOG</small><strong>08.18</strong></span><span class="post-card-copy"><time datetime="2025-08-18T17:10:18.000Z">2025/08/19</time><span class="post-card-title">使用GitHub推送Hexo到服务器</span><span class="post-card-summary">这篇文章介绍了如何使用GitHub推送Hexo到服务器,包括建立GitHub仓库、上传文件、创建Action以及配置环境变量等步骤。首先,文章提供了在香港直连GitHub的方法,并指导如何在本地安装git、配置用户名和邮箱、创建SSH Key并在GitHub上上传公钥。接着,文章详细说明了如何在自己的hexo根目录下初始化git仓库,并使用PowerShell将文件推送到新建的私有仓库。此外,文章还创建了一个Action,用于自动化部署过程,包括检查分支、缓存项目、安装Node和Hexo、安装依赖、清理文件树、生成静态文件并压缩、部署到服务器等环节。最后,文章列出了需要配置的环境变量,如服务器IP、用户名、密钥密码、私钥和SSH登录端口,并强调了测试的重要性,以确保整个部署流程无报错。</span></span><span class="post-card-open" aria-hidden="true">↗</span></a><div class="meta-list"><a href="/categories/site-notes/">建站手札</a><a href="/tags/%E7%BD%91%E7%AB%99/">#网站</a></div></article><article class="post-card"><a class="post-card-main" href="/posts/c6143ad3/"><span class="post-card-index" aria-hidden="true"><small>LOG</small><strong>08.14</strong></span><span class="post-card-copy"><time datetime="2025-08-14T17:05:27.000Z">2025/08/15</time><span class="post-card-title">自定义页脚(新)</span><span class="post-card-summary">您提供的代码是一个自定义页脚的HTML和CSS代码 要在您的网站中使用这个自定义页脚,请按照以下步骤操作: 1. 首先,将提供的CSS代码复制到您网站的CSS文件中。如果您没有单独的CSS文件,可以在HTML文件的`&lt;head&gt;`部分添加`&lt;style&gt;`标签,并将CSS代码粘贴到其中。 2. 接下来,将提供的HTML代码复制到您网站的HTML文件中。将其放置在`&lt;body&gt;`标签内,最好在页面的底部。 3. 根据需要自定义页脚内容,例如更改版权信息、菜单链接、社交链接等。 4. 保存更改并在浏览器中查看您的网站,您应该能看到自定义页脚。</span></span><span class="post-card-open" aria-hidden="true">↗</span></a><div class="meta-list"><a href="/categories/site-notes/">建站手札</a><a href="/tags/%E7%BD%91%E7%AB%99/">#网站</a></div></article><article class="post-card"><a class="post-card-main" href="/posts/33249733/"><span class="post-card-index" aria-hidden="true"><small>LOG</small><strong>08.14</strong></span><span class="post-card-copy"><time datetime="2025-08-14T16:25:49.000Z">2025/08/15</time><span class="post-card-title">自定义分类条</span><span class="post-card-summary">这篇文章介绍了如何在博客系统中自定义分类栏的设计和实现过程。首先,通过Pug模板语言创建了一个名为categoryBar.pug的文件,用于定义分类栏的结构和样式。接着,在Stylus样式文件category-bar.styl中详细定义了分类栏的样式,包括内边距、背景颜色、边框圆角等,并设置了滚动条的样式。最后,在JavaScript文件main.js中添加了一个setCategoryBarActive函数,用于根据当前页面路径自动激活相应的分类项。此外,还讨论了如何将自定义的分类栏集成到主题中,并提供了相关的Pug混入代码。整个过程确保了分类栏的可定制性和易维护性。</span></span><span class="post-card-open" aria-hidden="true">↗</span></a><div class="meta-list"><a href="/categories/site-notes/">建站手札</a><a href="/tags/%E7%BD%91%E7%AB%99/">#网站</a></div></article><article class="post-card"><a class="post-card-main" href="/posts/3e61a389/"><span class="post-card-index" aria-hidden="true"><small>LOG</small><strong>08.13</strong></span><span class="post-card-copy"><time datetime="2025-08-13T16:12:25.000Z">2025/08/14</time><span class="post-card-title">自定义导航栏</span><span class="post-card-summary">这篇文章介绍了如何在最新版的Butterfly 5.4中自定义导航栏,包括PC端和PE端的修改方法以及CSS文件的调整。主要内容包括修改header\nav.pug和menu_item.pug文件中的内容,调整head.styl和sidebar.styl中的CSS样式,以及在CSS文件中添加新的样式规则。这些修改旨在实现导航栏的个性化设置,如菜单项的显示、位置调整、背景颜色变化等,以提升网站的用户体验和视觉效果。</span></span><span class="post-card-open" aria-hidden="true">↗</span></a><div class="meta-list"><a href="/categories/site-notes/">建站手札</a><a href="/tags/%E7%BD%91%E7%AB%99/">#网站</a></div></article><article class="post-card"><a class="post-card-main" href="/posts/b5866b9e/"><span class="post-card-index" aria-hidden="true"><small>LOG</small><strong>08.12</strong></span><span class="post-card-copy"><time datetime="2025-08-12T15:15:32.000Z">2025/08/12</time><span class="post-card-title">利用 SiteMap 随机访问站内页面</span><span class="post-card-summary">提供了一个很好的解决方案,通过使用 Hexo 的 sitemap 生成器和 JavaScript 代码来实现随机访问站内页面的功能 以下是你提供的步骤的详细解释:</span></span><span class="post-card-open" aria-hidden="true">↗</span></a><div class="meta-list"><a href="/categories/site-notes/">建站手札</a><a href="/tags/%E7%BD%91%E7%AB%99/">#网站</a></div></article><article class="post-card"><a class="post-card-main" href="/posts/41b9aff7/"><span class="post-card-index" aria-hidden="true"><small>LOG</small><strong>08.12</strong></span><span class="post-card-copy"><time datetime="2025-08-12T09:46:25.000Z">2025/08/12</time><span class="post-card-title">博客添加AI总结</span><span class="post-card-summary">这篇文章介绍了如何在Hexo博客中添加AI摘要功能,作者寻找并尝试了多个AI摘要插件后,最终选择了hexo-ai-summary-liushen插件。安装过程中,作者详细说明了如何安装额外依赖,并在Hexo配置文件中添加了相关配置。文章还提供了关于内容清洗、摘要字段设置、日志等级、API接口配置、插件适配等方面的详细说明和配置示例。此外,作者还介绍了如何将AI摘要集成到Hexo主题中,并提供了相关的CSS样式和JavaScript动效代码,以实现更加逼真的摘要效果。最后,作者提醒用户在运行插件前注意备份,并介绍了如何处理可能出现的缓存问题。</span></span><span class="post-card-open" aria-hidden="true">↗</span></a><div class="meta-list"><a href="/categories/site-notes/">建站手札</a><a href="/tags/%E7%BD%91%E7%AB%99/">#网站</a></div></article><article class="post-card"><a class="post-card-main" href="/posts/a6ab0925/"><span class="post-card-index" aria-hidden="true"><small>LOG</small><strong>08.12</strong></span><span class="post-card-copy"><time datetime="2025-08-12T09:19:16.000Z">2025/08/12</time><span class="post-card-title">利用插件自定义页脚菜单</span><span class="post-card-summary">这篇文章介绍了如何使用插件来自定义Hexo博客的页脚菜单。首先,通过npm安装了hexo-butterfly-footer-marcus插件,并根据需要安装了yamljs插件。接着,在博客的配置文件中添加了相关配置信息,包括页脚美化、图标链接、作者信息等。文章还提供了具体的参数释义和使用方法,指导读者如何填写配置项和修改源码来调整页脚样式和布局。最后,文章还提到了如何解决在黑暗模式下修改按钮层级的问题,并提供了相关的代码修改示例。</span></span><span class="post-card-open" aria-hidden="true">↗</span></a><div class="meta-list"><a href="/categories/site-notes/">建站手札</a><a href="/tags/%E7%BD%91%E7%AB%99/">#网站</a></div></article><article class="post-card"><a class="post-card-main" href="/posts/8bdb35fb/"><span class="post-card-index" aria-hidden="true"><small>LOG</small><strong>08.11</strong></span><span class="post-card-copy"><time datetime="2025-08-11T16:02:12.000Z">2025/08/12</time><span class="post-card-title">自定义右键菜单</span><span class="post-card-summary">这篇文章介绍了如何在自定义右键菜单中添加各种功能,包括返回、前进、刷新、滚动到页面不同位置、复制文本、搜索页面、打开链接、粘贴内容、复制本文地址、在新窗口打开链接、保存图片、随机文章浏览、切换深色模式、繁简转换、阅读模式以及隐私声明、Cookie协议和版权声明等。同时,文章还提供了创建Pug文件和JavaScript文件的步骤,详细说明了如何编写右键菜单的HTML结构和交互逻辑。</span></span><span class="post-card-open" aria-hidden="true">↗</span></a><div class="meta-list"><a href="/categories/site-notes/">建站手札</a><a href="/tags/%E7%BD%91%E7%AB%99/">#网站</a></div></article><article class="post-card"><a class="post-card-main" href="/posts/da17d00/"><span class="post-card-index" aria-hidden="true"><small>LOG</small><strong>08.10</strong></span><span class="post-card-copy"><time datetime="2025-08-10T19:30:40.000Z">2025/08/11</time><span class="post-card-title">在侧边栏中添加欢迎信息</span><span class="post-card-summary">这篇文章介绍了如何在侧边栏中添加欢迎信息,包括申请腾讯地图API key、添加js脚本以及根据用户的地理位置显示个性化欢迎语。首先,文章指导读者如何申请腾讯地图API key,并提醒注意填写信任域名时不要包含&#39;https://&#39;。接着,文章说明了在主题的js目录下添加txmap.js脚本的过程,并提到了一个更完善的js脚本。最后,文章详细描述了如何使用获取到的地理位置信息,通过switch语句根据不同的国家、省份和城市显示相应的欢迎语。</span></span><span class="post-card-open" aria-hidden="true">↗</span></a><div class="meta-list"><a href="/categories/site-notes/">建站手札</a><a href="/tags/%E7%BD%91%E7%AB%99/">#网站</a></div></article><article class="post-card"><a class="post-card-main" href="/posts/ad244066/"><span class="post-card-index" aria-hidden="true"><small>LOG</small><strong>08.10</strong></span><span class="post-card-copy"><time datetime="2025-08-10T08:25:39.000Z">2025/08/10</time><span class="post-card-title">配置说说页面</span><span class="post-card-summary">这段文字看起来是一个部署教程,主要是关于如何在服务器上部署一个名为“Moments”的应用,并将其与网站集成。以下是对这段文字的概括: 1. 介绍了硬件和软件的要求,包括服务器、域名、Docker环境和反向代理工具(如Nginx)。 2. 提供了Moments应用的部署方法,包括使用docker-compose进行部署和配置Nginx反向代理。 3. 介绍了如何在前端集成Moments应用,包括引入必要的CSS和JS文件,以及创建一个新的页面来显示Moments的内容。 需要注意的是,这段文字中的一些链接和代码可能已经过时或者不适用于所有场景,建议在实际操作时参考最新的官方</span></span><span class="post-card-open" aria-hidden="true">↗</span></a><div class="meta-list"><a href="/categories/site-notes/">建站手札</a><a href="/tags/%E7%BD%91%E7%AB%99/">#网站</a></div></article><article class="post-card"><a class="post-card-main" href="/posts/6e5f5039/"><span class="post-card-index" aria-hidden="true"><small>LOG</small><strong>08.02</strong></span><span class="post-card-copy"><time datetime="2025-08-02T19:07:05.000Z">2025/08/03</time><span class="post-card-title">部署历程</span><span class="post-card-summary">这篇文章详细介绍了如何部署Hexo博客到Linux服务器,包括前提条件、本地环境准备、SSH密钥认证、配置步骤、工作流程以及故障排除提示。文章首先列出了部署所需满足的条件,然后逐步指导读者如何在服务器上安装Git、创建裸仓库、配置Git钩子以自动部署Hexo博客,并提供了验证部署成功的步骤。最后,文章还给出了一些常见问题的解决建议,帮助读者顺利完成部署。整个过程简单高效,适合需要自动化部署博客的用户。</span></span><span class="post-card-open" aria-hidden="true">↗</span></a><div class="meta-list"><a href="/categories/site-notes/">建站手札</a><a href="/tags/%E7%BD%91%E7%AB%99/">#网站</a></div></article></div></section></main><footer class="site-footer" aria-label="站点页脚"><div class="footer-inner"><section class="footer-top" aria-label="站点信息"><a class="footer-brand" href="/" aria-label="Bi's Blog 首页"><img src="/images/Bi.ico" alt="" loading="lazy"><span>Bi&#39;s Blog</span></a><p class="footer-slogan">好奇心转化为代码的空间。</p></section><section class="footer-contact" aria-label="联系方式"><p>联系方式</p><div class="footer-socials"><a href="mailto:bishsh2006@gmail.com" aria-label="发送邮件" title="发送邮件"><i class="fa-solid fa-envelope" aria-hidden="true"></i></a><a href="/rss.xml" aria-label="订阅 RSS" title="订阅 RSS"><i class="fa-solid fa-rss" aria-hidden="true"></i></a><a href="https://github.com/bishshi" target="_blank" rel="noreferrer" aria-label="GitHub" title="GitHub"><i class="fa-brands fa-github" aria-hidden="true"></i></a></div><nav class="footer-contact-links" aria-label="页脚链接"><a href="/archives/">发展历程</a><span aria-hidden="true">|</span><a href="/privacy/">隐私政策</a></nav></section><section class="footer-bottom" aria-label="版权信息"><div><p>© 2025 - 2026 Bi&#39;s Blog</p><p>blog.biss.click | 内容采用 CC BY-NC-SA 4.0 协议</p></div><div class="footer-meta"><p>本站已运行:<span id="site-runtime">计算中...</span></p><p><a href="https://fastly.com/" target="_blank" rel="noreferrer">Fastly</a><span aria-hidden="true">|</span><a href="https://astro.build/" target="_blank" rel="noreferrer">ASTRO</a></p></div></section></div></footer><aside class="hitokoto-card is-collapsed" aria-label="一言" data-hitokoto-card data-astro-cid-fo5bt3gf><div class="hitokoto-card__head" data-astro-cid-fo5bt3gf><button class="hitokoto-card__toggle" type="button" aria-label="展开一言" aria-expanded="false" title="一言" data-hitokoto-toggle data-astro-cid-fo5bt3gf><i class="fa-solid fa-quote-left" aria-hidden="true" data-astro-cid-fo5bt3gf></i><span data-astro-cid-fo5bt3gf>一言</span></button><div class="hitokoto-card__actions" data-astro-cid-fo5bt3gf><button class="hitokoto-card__refresh" type="button" aria-label="换一句" title="换一句" data-hitokoto-refresh data-astro-cid-fo5bt3gf><i class="fa-solid fa-rotate" aria-hidden="true" data-astro-cid-fo5bt3gf></i></button><button class="hitokoto-card__collapse" type="button" aria-label="收起一言" title="收起" data-hitokoto-collapse data-astro-cid-fo5bt3gf><i class="fa-solid fa-chevron-down" aria-hidden="true" data-astro-cid-fo5bt3gf></i></button></div></div><a class="hitokoto-card__text" href="https://hitokoto.cn/" target="_blank" rel="noreferrer" data-hitokoto-text data-astro-cid-fo5bt3gf>获取中...</a><p class="hitokoto-card__from" data-hitokoto-from data-astro-cid-fo5bt3gf>来自 Hitokoto</p></aside><script type="module">(()=>{let e=document.querySelector(`[data-hitokoto-card]`),t=e?.querySelector(`[data-hitokoto-toggle]`),n=e?.querySelector(`[data-hitokoto-text]`),r=e?.querySelector(`[data-hitokoto-from]`),i=e?.querySelector(`[data-hitokoto-refresh]`),a=e?.querySelector(`[data-hitokoto-collapse]`);if(!(e instanceof HTMLElement)||!(t instanceof HTMLButtonElement)||!(n instanceof HTMLAnchorElement)||!(r instanceof HTMLElement))return;let o=`hitokoto-card-cache`,s=`hitokoto-card-expanded`,c={sentence:`生活明朗,万物可爱。`,source:`本地缓存`,url:`https://hitokoto.cn/`},l=[`/`,`/index.html`].includes(window.location.pathname),u=window.matchMedia(`(max-width: 720px)`);function d(){try{let e=localStorage.getItem(s);if(e===`true`)return!0;if(e===`false`)return!1}catch{}return null}function f(e){try{localStorage.setItem(s,String(e))}catch{}}function p(n,{persist:r=!1}={}){e.classList.toggle(`is-collapsed`,!n),t.setAttribute(`aria-expanded`,String(n)),t.setAttribute(`aria-label`,n?`收起一言`:`展开一言`),r&&f(n)}function m(){try{let e=localStorage.getItem(o);if(!e)return null;let t=JSON.parse(e);return!t||typeof t.expiresAt!=`number`||t.expiresAt<=Date.now()?null:t.data}catch{return null}}function h(e){try{localStorage.setItem(o,JSON.stringify({data:e,expiresAt:Date.now()+216e5}))}catch{}}function g(e){n.textContent=e.sentence,n.href=e.url||`https://hitokoto.cn/`,r.textContent=e.source?`出自 ${e.source}`:`来自 Hitokoto`}async function _({force:t=!1}={}){if(!t){let e=m();if(e){g(e);return}}e.classList.add(`is-loading`),n.textContent=`获取中...`;try{let e=await fetch(`https://yiyan.biss.click/api?encode=json`);if(!e.ok)throw Error(`Hitokoto request failed: ${e.status}`);let t=await e.json(),n=t.hitokoto||t.content||t.sentence||t.text,r={sentence:typeof n==`string`&&n.trim()?n.trim():c.sentence,source:typeof t.from==`string`&&t.from.trim()?t.from.trim():`Hitokoto`,url:t.uuid?`https://hitokoto.cn/?uuid=${encodeURIComponent(t.uuid)}`:`https://hitokoto.cn/`};h(r),g(r)}catch(e){console.error(e),g(m()||c)}finally{e.classList.remove(`is-loading`)}}p(d()??(l&&!u.matches)),t.addEventListener(`click`,()=>{p(e.classList.contains(`is-collapsed`),{persist:!0})}),i?.addEventListener(`click`,e=>{e.stopPropagation(),p(!0,{persist:!0}),_({force:!0})}),a?.addEventListener(`click`,e=>{e.stopPropagation(),p(!1,{persist:!0})}),e.addEventListener(`click`,t=>{e.classList.contains(`is-collapsed`)&&(t.target instanceof Element&&t.target.closest(`a, button`)||p(!0,{persist:!0}))}),_()})();</script><div class="custom-context-menu" data-context-menu role="menu" aria-hidden="true"><div class="context-menu-nav" aria-label="页面导航"><button type="button" data-context-action="back" aria-label="后退上一页" title="后退上一页"><i class="fa-solid fa-arrow-left" aria-hidden="true"></i></button><button type="button" data-context-action="forward" aria-label="前进下一页" title="前进下一页"><i class="fa-solid fa-arrow-right" aria-hidden="true"></i></button><button type="button" data-context-action="reload" aria-label="刷新页面" title="刷新页面"><i class="fa-solid fa-rotate-right" aria-hidden="true"></i></button><a href="/" aria-label="返回首页" title="返回首页"><i class="fa-solid fa-house" aria-hidden="true"></i></a></div><div class="context-menu-group" data-selection-group hidden><button type="button" data-context-action="copy-selection" data-selection-item><i class="fa-regular fa-copy" aria-hidden="true"></i><span>复制选中文字</span></button><button type="button" data-context-action="search-selection" data-selection-item><i class="fa-brands fa-microsoft" aria-hidden="true"></i><span>用 Bing 搜索</span></button><button type="button" data-context-action="quote-selection" data-selection-item data-comments-item><i class="fa-regular fa-comment-dots" aria-hidden="true"></i><span>引用到评论区</span></button></div><div class="context-menu-group" data-image-group hidden><button type="button" data-context-action="copy-image"><i class="fa-regular fa-image" aria-hidden="true"></i><span>复制图片</span></button><button type="button" data-context-action="open-image"><i class="fa-solid fa-up-right-from-square" aria-hidden="true"></i><span>新页面打开图片</span></button><button type="button" data-context-action="copy-image-url"><i class="fa-solid fa-link" aria-hidden="true"></i><span>复制图片地址</span></button></div><div class="context-menu-group"><a href="/archives/"><i class="fa-solid fa-box-archive" aria-hidden="true"></i><span>时间线</span></a><a href="/categories/"><i class="fa-solid fa-folder" aria-hidden="true"></i><span>分类</span></a><a href="/tags/"><i class="fa-solid fa-hashtag" aria-hidden="true"></i><span>标签</span></a><button type="button" data-context-action="random-post"><i class="fa-solid fa-shuffle" aria-hidden="true"></i><span>&#x968F;&#x673A;&#x6587;&#x7AE0;</span></button><button type="button" data-context-action="comments" data-comments-item><i class="fa-regular fa-comment-dots" aria-hidden="true"></i><span>跳转评论区</span></button><button type="button" data-context-action="print"><i class="fa-solid fa-print" aria-hidden="true"></i><span>打印页面</span></button><a href="/cc/"><i class="fa-solid fa-circle-info" aria-hidden="true"></i><span>网站版权</span></a></div></div><div class="context-menu-native-hint" data-context-native-hint role="note" aria-label="Ctrl 右键提示"><kbd>Ctrl</kbd> + &#x53F3;&#x952E;&#xFF1A;&#x6D4F;&#x89C8;&#x5668;&#x539F;&#x751F;&#x83DC;&#x5355;</div><script>
(() => {
const menu = document.querySelector('[data-context-menu]');
if (!menu) return;
const nativeHint = document.querySelector('[data-context-native-hint]');
const selectionItems = [...menu.querySelectorAll('[data-selection-item]')];
const selectionGroup = menu.querySelector('[data-selection-group]');
const commentsItems = [...menu.querySelectorAll('[data-comments-item]')];
const imageGroup = menu.querySelector('[data-image-group]');
const focusableSelector = 'a[href], button:not([disabled])';
let lastSelectionText = '';
let lastImage = null;
let nativeHintTimer = 0;
const isNativeContextTarget = (target) =>
target instanceof Element &&
Boolean(target.closest('input, textarea, select, [contenteditable="true"], [contenteditable=""]'));
const getCommentsTarget = () =>
document.querySelector('.twikoo-comments, #twikoo-wrap, #twikoo, .tk-comments-container');
const getSelectionText = () => String(window.getSelection?.() || '').trim();
const getImageTarget = (target) => {
if (!(target instanceof Element)) return null;
const image = target.closest('img');
return image instanceof HTMLImageElement ? image : null;
};
const getImageUrl = () => {
if (!lastImage) return '';
return lastImage.currentSrc || lastImage.src || lastImage.getAttribute('src') || '';
};
const copyText = async (text) => {
if (navigator.clipboard?.writeText) {
await navigator.clipboard.writeText(text);
return;
}
const textarea = document.createElement('textarea');
textarea.value = text;
textarea.setAttribute('readonly', '');
textarea.style.position = 'fixed';
textarea.style.inset = '0 auto auto -9999px';
document.body.appendChild(textarea);
textarea.select();
document.execCommand('copy');
textarea.remove();
};
const setMenuState = () => {
const hasSelection = lastSelectionText.length > 0;
const hasComments = Boolean(getCommentsTarget());
const hasImage = Boolean(getImageUrl());
selectionItems.forEach((item) => {
item.hidden = !hasSelection;
});
if (selectionGroup) selectionGroup.hidden = !hasSelection;
commentsItems.forEach((item) => {
item.hidden = !hasComments || (item.hasAttribute('data-selection-item') && !hasSelection);
});
if (imageGroup) imageGroup.hidden = !hasImage;
};
const closeMenu = () => {
menu.classList.remove('is-open');
menu.setAttribute('aria-hidden', 'true');
};
const openMenu = (x, y) => {
setMenuState();
menu.classList.add('is-open');
menu.setAttribute('aria-hidden', 'false');
const rect = menu.getBoundingClientRect();
const gap = 10;
const left = Math.min(Math.max(gap, x), window.innerWidth - rect.width - gap);
const top = Math.min(Math.max(gap, y), window.innerHeight - rect.height - gap);
menu.style.left = `${left}px`;
menu.style.top = `${top}px`;
};
const showNativeHint = () => {
if (!nativeHint) return;
window.clearTimeout(nativeHintTimer);
nativeHint.classList.add('is-visible');
nativeHintTimer = window.setTimeout(() => {
nativeHint.classList.remove('is-visible');
}, 2600);
};
const jumpToComments = () => {
const target = getCommentsTarget();
target?.scrollIntoView({ behavior: 'smooth', block: 'start' });
};
const quoteToComments = () => {
jumpToComments();
window.setTimeout(() => {
const textarea = document.querySelector('#twikoo textarea, .twikoo-comments textarea, .tk-input textarea');
if (!(textarea instanceof HTMLTextAreaElement) || !lastSelectionText) return;
const quote = lastSelectionText
.split(/\r?\n/)
.map((line) => `> ${line}`)
.join('\n');
const current = textarea.value.trim();
textarea.value = current ? `${current}\n\n${quote}\n` : `${quote}\n`;
textarea.dispatchEvent(new Event('input', { bubbles: true }));
textarea.focus();
}, 500);
};
const searchSelection = () => {
if (!lastSelectionText) return;
const url = `https://www.bing.com/search?q=${encodeURIComponent(lastSelectionText)}`;
window.open(url, '_blank', 'noopener,noreferrer');
};
const copyImage = async () => {
const imageUrl = getImageUrl();
if (!imageUrl) return;
try {
if (!navigator.clipboard?.write || typeof ClipboardItem === 'undefined') {
throw new Error('Image clipboard is not available.');
}
const response = await fetch(imageUrl, { mode: 'cors' });
const blob = await response.blob();
await navigator.clipboard.write([
new ClipboardItem({ [blob.type || 'image/png']: blob }),
]);
} catch {
await copyText(new URL(imageUrl, window.location.href).toString());
}
};
const openImage = () => {
const imageUrl = getImageUrl();
if (!imageUrl) return;
window.open(new URL(imageUrl, window.location.href).toString(), '_blank', 'noopener,noreferrer');
};
document.addEventListener('contextmenu', (event) => {
if (event.ctrlKey) {
closeMenu();
nativeHint?.classList.remove('is-visible');
return;
}
if (isNativeContextTarget(event.target)) return;
lastSelectionText = getSelectionText();
lastImage = getImageTarget(event.target);
event.preventDefault();
openMenu(event.clientX, event.clientY);
showNativeHint();
});
document.addEventListener('click', (event) => {
const actionTarget = event.target instanceof Element ? event.target.closest('[data-context-action]') : null;
if (!actionTarget || !menu.contains(actionTarget)) {
closeMenu();
return;
}
const action = actionTarget.dataset.contextAction;
closeMenu();
if (action === 'back') history.back();
if (action === 'forward') history.forward();
if (action === 'reload') location.reload();
if (action === 'copy-selection' && lastSelectionText) copyText(lastSelectionText);
if (action === 'search-selection') searchSelection();
if (action === 'quote-selection') quoteToComments();
if (action === 'copy-image') copyImage();
if (action === 'open-image') openImage();
if (action === 'copy-image-url') copyText(new URL(getImageUrl(), window.location.href).toString());
if (action === 'random-post' && typeof window.randomPost === 'function') window.randomPost(actionTarget);
if (action === 'comments') jumpToComments();
if (action === 'print') window.print();
});
document.addEventListener('keydown', (event) => {
if (event.key === 'Escape') closeMenu();
if (event.key === 'Tab' && menu.classList.contains('is-open')) {
const items = [...menu.querySelectorAll(focusableSelector)].filter((item) => !item.closest('[hidden]'));
if (items.length === 0) return;
const first = items[0];
const last = items[items.length - 1];
if (event.shiftKey && document.activeElement === first) {
event.preventDefault();
last.focus();
} else if (!event.shiftKey && document.activeElement === last) {
event.preventDefault();
first.focus();
}
}
});
window.addEventListener('scroll', closeMenu, { passive: true });
window.addEventListener('resize', closeMenu);
})();
</script><aside class="pwa-toast" data-pwa-toast hidden role="status" aria-live="polite"><div class="pwa-toast-icon" aria-hidden="true"><i class="fa-solid fa-download"></i></div><div class="pwa-toast-copy"><strong data-pwa-title>PWA 提示</strong><p data-pwa-message></p></div><div class="pwa-toast-actions"><button class="pwa-toast-primary" type="button" data-pwa-primary>确定</button><button class="pwa-toast-close" type="button" data-pwa-close aria-label="关闭提示">稍后</button></div></aside><script src="https://cdn.jsdmirror.com/npm/instantsearch.js@4.56.0"></script><script src="https://cdn.jsdmirror.com/npm/typesense-instantsearch-adapter@2.7.0/dist/typesense-instantsearch-adapter.min.js"></script><script src="https://cdn.jsdmirror.com/npm/@fancyapps/ui@5.0/dist/fancybox/fancybox.umd.js"></script><script src="/js/random.js"></script><script src="/js/search/typesense-search.js"></script><script src="/js/external-links.js"></script><script src="/js/pwa.js"></script><script>
(() => {
const nav = document.querySelector('.nav');
const toggle = document.querySelector('[data-nav-toggle]');
const menu = document.querySelector('[data-nav-menu]');
const backdrop = document.querySelector('[data-nav-backdrop]');
if (!nav || !toggle || !menu) return;
function setMenu(open) {
nav.classList.toggle('is-open', open);
toggle.setAttribute('aria-expanded', String(open));
toggle.setAttribute('aria-label', open ? '关闭菜单' : '打开菜单');
menu.setAttribute('aria-hidden', String(!open && window.innerWidth <= 720));
document.body.classList.toggle('has-nav-drawer', open);
}
toggle.addEventListener('click', () => {
setMenu(!nav.classList.contains('is-open'));
});
backdrop?.addEventListener('click', () => setMenu(false));
menu.addEventListener('click', (event) => {
if (event.target instanceof Element && event.target.closest('a')) setMenu(false);
});
document.addEventListener('click', (event) => {
if (!nav.classList.contains('is-open')) return;
if (event.target instanceof Node && nav.contains(event.target)) return;
setMenu(false);
});
document.addEventListener('keydown', (event) => {
if (event.key === 'Escape' && nav.classList.contains('is-open')) setMenu(false);
});
window.addEventListener('resize', () => {
if (window.innerWidth > 720) setMenu(false);
else menu.setAttribute('aria-hidden', String(!nav.classList.contains('is-open')));
});
menu.setAttribute('aria-hidden', String(window.innerWidth <= 720));
})();
(() => {
const modal = document.querySelector('[data-console-modal]');
const panel = modal?.querySelector('.control-console-panel');
const openButtons = document.querySelectorAll('[data-console-open]');
const closeButtons = modal?.querySelectorAll('[data-console-close]') || [];
if (!modal || !panel || openButtons.length === 0) return;
function setConsole(open) {
modal.classList.toggle('is-open', open);
modal.setAttribute('aria-hidden', String(!open));
document.body.classList.toggle('has-control-console', open);
if (open) panel.focus();
}
openButtons.forEach((button) => {
button.addEventListener('click', () => setConsole(true));
});
closeButtons.forEach((button) => {
button.addEventListener('click', () => setConsole(false));
});
document.addEventListener('keydown', (event) => {
if (event.key === 'Escape' && modal.classList.contains('is-open')) setConsole(false);
});
})();
(() => {
const storageKey = 'site-theme';
const root = document.documentElement;
const button = document.querySelector('[data-theme-toggle]');
const media = window.matchMedia('(prefers-color-scheme: dark)');
const getSystemTheme = () => (media.matches ? 'dark' : 'light');
const getSavedTheme = () => {
try {
const theme = localStorage.getItem(storageKey);
return theme === 'dark' || theme === 'light' ? theme : null;
} catch {
return null;
}
};
const setSavedTheme = (theme) => {
try {
if (theme === getSystemTheme()) localStorage.removeItem(storageKey);
else localStorage.setItem(storageKey, theme);
} catch {
// localStorage can be unavailable in strict privacy modes.
}
};
const getTheme = () => getSavedTheme() || getSystemTheme();
function applyTheme(theme) {
root.dataset.theme = theme;
root.dataset.themeMode = getSavedTheme() ? 'manual' : 'auto';
button?.setAttribute('aria-label', theme === 'dark' ? '切换到日间模式' : '切换到夜间模式');
button?.setAttribute(
'title',
getSavedTheme()
? (theme === 'dark' ? '切换到日间模式' : '切换到夜间模式')
: `跟随系统:${theme === 'dark' ? '夜间' : '日间'}模式`
);
}
applyTheme(getTheme());
button?.addEventListener('click', () => {
const nextTheme = root.dataset.theme === 'dark' ? 'light' : 'dark';
setSavedTheme(nextTheme);
applyTheme(nextTheme);
});
const handleSystemThemeChange = () => {
if (!getSavedTheme()) applyTheme(getSystemTheme());
};
if (typeof media.addEventListener === 'function') {
media.addEventListener('change', handleSystemThemeChange);
} else if (typeof media.addListener === 'function') {
media.addListener(handleSystemThemeChange);
}
})();
(() => {
const runtime = document.getElementById('site-runtime');
if (!runtime) return;
const start = new Date(window.SITE_CONFIG.site.startTime).getTime();
const pad = (value) => String(value).padStart(2, '0');
function updateRuntime() {
const diff = Math.max(0, Date.now() - start);
const days = Math.floor(diff / 86400000);
const hours = Math.floor((diff / 3600000) % 24);
const minutes = Math.floor((diff / 60000) % 60);
const seconds = Math.floor((diff / 1000) % 60);
runtime.textContent = `${days} 天 ${pad(hours)} 时 ${pad(minutes)} 分 ${pad(seconds)} 秒`;
}
updateRuntime();
window.setInterval(updateRuntime, 1000);
})();
</script></body></html>