Files
blog/posts/41b9aff7/index.html
2026-02-23 08:41:34 +08:00

665 lines
113 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html><html lang="zh-CN" data-theme="light"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0,viewport-fit=cover"><title>博客添加AI总结 | Bi's Blog</title><meta name="author" content="biss"><meta name="copyright" content="biss"><meta name="format-detection" content="telephone=no"><meta name="theme-color" content="#ffffff"><meta name="description" content="之前在wordpress中看到过ai插件现在使用hexo好像有洪墨AI但是收费有点负担不了于是寻找代替品真的找到了 🪧引用站外地址,不保证站点的可用性和安全性 liushen开发的插件 ai-summary 首先,安装插件:">
<meta property="og:type" content="article">
<meta property="og:title" content="博客添加AI总结">
<meta property="og:url" content="https://blog.biss.click/posts/41b9aff7/index.html">
<meta property="og:site_name" content="Bi's Blog">
<meta property="og:description" content="之前在wordpress中看到过ai插件现在使用hexo好像有洪墨AI但是收费有点负担不了于是寻找代替品真的找到了 🪧引用站外地址,不保证站点的可用性和安全性 liushen开发的插件 ai-summary 首先,安装插件:">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://pic.biss.click/image/0d2f2a46-8aa9-42b6-a853-4794222a1492.webp">
<meta property="article:published_time" content="2025-08-12T01:46:25.000Z">
<meta property="article:modified_time" content="2026-02-23T00:41:17.224Z">
<meta property="article:author" content="biss">
<meta property="article:tag" content="网站">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://pic.biss.click/image/0d2f2a46-8aa9-42b6-a853-4794222a1492.webp"><script type="application/ld+json">{
"@context": "https://schema.org",
"@type": "BlogPosting",
"headline": "博客添加AI总结",
"url": "https://blog.biss.click/posts/41b9aff7/",
"image": "https://pic.biss.click/image/0d2f2a46-8aa9-42b6-a853-4794222a1492.webp",
"datePublished": "2025-08-12T01:46:25.000Z",
"dateModified": "2026-02-23T00:41:17.224Z",
"author": [
{
"@type": "Person",
"name": "biss",
"url": "https://blog.biss.click"
}
]
}</script><link rel="shortcut icon" href="/images/Bi.ico"><link rel="canonical" href="https://blog.biss.click/posts/41b9aff7/index.html"><link rel="preconnect" href="//unpkg.com"><link rel="preconnect" href="//busuanzi.ibruce.info"><link rel="stylesheet" href="/css/index.css"><link rel="stylesheet" href="https://unpkg.com/@fortawesome/fontawesome-free/css/all.min.css"><link rel="stylesheet" href="https://unpkg.com/node-snackbar/dist/snackbar.min.css" media="print" onload="this.media='all'"><link rel="stylesheet" href="https://unpkg.com/@fancyapps/ui/dist/fancybox/fancybox.css" media="print" onload="this.media='all'"><script>
(() => {
const saveToLocal = {
set: (key, value, ttl) => {
if (!ttl) return
const expiry = Date.now() + ttl * 86400000
localStorage.setItem(key, JSON.stringify({ value, expiry }))
},
get: key => {
const itemStr = localStorage.getItem(key)
if (!itemStr) return undefined
const { value, expiry } = JSON.parse(itemStr)
if (Date.now() > expiry) {
localStorage.removeItem(key)
return undefined
}
return value
}
}
window.btf = {
saveToLocal,
getScript: (url, attr = {}) => new Promise((resolve, reject) => {
const script = document.createElement('script')
script.src = url
script.async = true
Object.entries(attr).forEach(([key, val]) => script.setAttribute(key, val))
script.onload = script.onreadystatechange = () => {
if (!script.readyState || /loaded|complete/.test(script.readyState)) resolve()
}
script.onerror = reject
document.head.appendChild(script)
}),
getCSS: (url, id) => new Promise((resolve, reject) => {
const link = document.createElement('link')
link.rel = 'stylesheet'
link.href = url
if (id) link.id = id
link.onload = link.onreadystatechange = () => {
if (!link.readyState || /loaded|complete/.test(link.readyState)) resolve()
}
link.onerror = reject
document.head.appendChild(link)
}),
addGlobalFn: (key, fn, name = false, parent = window) => {
if (!true && key.startsWith('pjax')) return
const globalFn = parent.globalFn || {}
globalFn[key] = globalFn[key] || {}
globalFn[key][name || Object.keys(globalFn[key]).length] = fn
parent.globalFn = globalFn
}
}
const activateDarkMode = () => {
document.documentElement.setAttribute('data-theme', 'dark')
if (document.querySelector('meta[name="theme-color"]') !== null) {
document.querySelector('meta[name="theme-color"]').setAttribute('content', '#0d0d0d')
}
}
const activateLightMode = () => {
document.documentElement.setAttribute('data-theme', 'light')
if (document.querySelector('meta[name="theme-color"]') !== null) {
document.querySelector('meta[name="theme-color"]').setAttribute('content', '#ffffff')
}
}
btf.activateDarkMode = activateDarkMode
btf.activateLightMode = activateLightMode
const theme = saveToLocal.get('theme')
theme === 'dark' ? activateDarkMode() : theme === 'light' ? activateLightMode() : null
const asideStatus = saveToLocal.get('aside-status')
if (asideStatus !== undefined) {
document.documentElement.classList.toggle('hide-aside', asideStatus === 'hide')
}
const detectApple = () => {
if (/iPad|iPhone|iPod|Macintosh/.test(navigator.userAgent)) {
document.documentElement.classList.add('apple')
}
}
detectApple()
})()
</script><script>const GLOBAL_CONFIG = {
root: '/',
algolia: undefined,
localSearch: undefined,
translate: {"defaultEncoding":2,"translateDelay":0,"msgToTraditionalChinese":"繁","msgToSimplifiedChinese":"簡"},
highlight: {"plugin":"highlight.js","highlightCopy":true,"highlightLang":true,"highlightHeightLimit":200,"highlightFullpage":true,"highlightMacStyle":false},
copy: {
success: '复制成功',
error: '复制失败',
noSupport: '浏览器不支持'
},
relativeDate: {
homepage: false,
post: false
},
runtime: '',
dateSuffix: {
just: '刚刚',
min: '分钟前',
hour: '小时前',
day: '天前',
month: '个月前'
},
copyright: undefined,
lightbox: 'fancybox',
Snackbar: {"chs_to_cht":"已切换为繁体中文","cht_to_chs":"已切换为简体中文","day_to_night":"已切换为深色模式","night_to_day":"已切换为浅色模式","bgLight":"#49b1f5","bgDark":"#1f1f1f","position":"bottom-left"},
infinitegrid: {
js: 'https://unpkg.com/@egjs/infinitegrid/dist/infinitegrid.min.js',
buttonText: '加载更多'
},
isPhotoFigcaption: false,
islazyloadPlugin: false,
isAnchor: false,
percent: {
toc: true,
rightside: false,
},
autoDarkmode: false
}</script><script id="config-diff">var GLOBAL_CONFIG_SITE = {
title: '博客添加AI总结',
isHighlightShrink: false,
isToc: true,
pageType: 'post'
}</script><link rel="stylesheet" href="/css/shuoshuo.css"><link rel="stylesheet" href="/css/shuoshuoshouye.css"><link rel="stylesheet" href="/css/nav.css"><link rel="stylesheet" href="/css/style.css"><link rel="stylesheet" href="/css/poem.css"><link rel="stylesheet" href="/css/swiper.css"><link rel="stylesheet" href="https://cdn.jsdmirror.com/npm/instantsearch.css/themes/reset-min.css"><link rel="stylesheet" href="https://cdn.jsdmirror.com/gh/bishshi/welcomemessage/welcome.css"><link rel="stylesheet" href="https://cdn.jsdmirror.com/gh/bishshi/sidecalendar/calendar.css"><link rel="stylesheet" href="https://cdn.jsdmirror.com/gh/bishshi/rightmenu/rightmenu.css"><link rel="stylesheet" href="https://cdn.jsdmirror.com/gh/bishshi/webfont/font.css"><link rel="stylesheet" href="https://cdn.jsdmirror.com/npm/aplayer/dist/APlayer.min.css" media="all" onload="this.media=&quot;all&quot;"><!-- hexo injector head_end start --><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Swiper/5.4.5/css/swiper.min.css" media="print" onload="this.media='all'"><link rel="stylesheet" href="https://cdn1.tianli0.top/npm/hexo-butterfly-swiper/lib/swiperstyle.css" media="print" onload="this.media='all'"><!-- hexo injector head_end end --><style type="text/css">
.spoiler {
display: inline;
}
p.spoiler {
display: flex;
}
.spoiler a {
pointer-events: none;
}
.spoiler-blur, .spoiler-blur > * {
transition: text-shadow .5s ease;
}
.spoiler .spoiler-blur, .spoiler .spoiler-blur > * {
color: rgba(0, 0, 0, 0);
background-color: rgba(0, 0, 0, 0);
text-shadow: 0 0 10px grey;
cursor: pointer;
}
.spoiler .spoiler-blur:hover, .spoiler .spoiler-blur:hover > * {
text-shadow: 0 0 5px grey;
}
.spoiler-box, .spoiler-box > * {
transition: color .5s ease,
background-color .5s ease;
}
.spoiler .spoiler-box, .spoiler .spoiler-box > * {
color: black;
background-color: black;
text-shadow: none;
}</style><meta name="generator" content="Hexo 8.1.1"><link rel="alternate" href="/atom.xml" title="Bi's Blog" type="application/atom+xml">
</head><body><div class="bg-animation" id="web_bg" style="background-image: url(/images/background.png);"></div><div id="sidebar"><div id="menu-mask"></div><div id="sidebar-menus"><div class="avatar-img text-center"><img src="https://free.picui.cn/free/2025/08/10/689845496a283.png" onerror="this.onerror=null;this.src='/img/friend_404.gif'" alt="avatar"></div><div class="site-data text-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">30</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">10</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">5</div></a></div><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> 首页</span></a></div><div class="menus_item"><a class="site-page" href="/archives/"><i class="fa-fw fas fa-archive"></i><span> 存档</span></a></div><div class="menus_item"><a class="site-page" href="/tags/"><i class="fa-fw fas fa-tags"></i><span> 标签</span></a></div><div class="menus_item"><a class="site-page" href="/categories/"><i class="fa-fw fas fa-folder-open"></i><span> 分类</span></a></div><div class="menus_item"><a class="site-page" href="/shuoshuo/"><i class="fa-fw fa-regular fa-comment"></i><span> 说说</span></a></div><div class="menus_item"><a class="site-page" href="/link/"><i class="fa-fw fas fa-link"></i><span> 友链</span></a></div><div class="menus_item"><a class="site-page" href="/about/"><i class="fa-fw fas fa-heart"></i><span> 关于</span></a></div></div></div></div><div class="post" id="body-wrap"><header class="post-bg fixed" id="page-header" style="background-image: url(https://pic.biss.click/image/0d2f2a46-8aa9-42b6-a853-4794222a1492.webp);"><nav id="nav"><span id="blog-info"><div id="ls-menu-container"><i class="fas fa-fingerprint"></i><div id="ls-menu-panel"><div class="ls-section"><div class="ls-title">😀 个人网站</div><div class="ls-grid"><a href="/"><i class="fas fa-rss"></i> 个人博客</a><a target="_blank" rel="noopener" href="https://github.com/bishshi"><i class="fab fa-github"></i> Github</a></div></div><div class="ls-section"><div class="ls-title">😎 常用服务</div><div class="ls-grid"><a target="_blank" rel="noopener" href="https://git.biss.click/biss"><i class="fas fa-code"></i> 代码仓库</a><a target="_blank" rel="noopener" href="https://mm.biss.click"><i class="fas fa-pen-nib"></i> 日常yy</a><a target="_blank" rel="noopener" href="https://statstic.biss.click"><i class="fas fa-users"></i> 访客统计</a><a target="_blank" rel="noopener" href="https://pic.biss.click"><i class="fas fa-image"></i> 图床</a><a target="_blank" rel="noopener" href="https://chat.biss.click"><i class="fas fa-robot"></i> AI网站</a><a target="_blank" rel="noopener" href="https://git.biss.click"><i class="fas fa-code-branch"></i> 代码仓库</a></div></div><div class="ls-section"><div class="ls-title">🛸 实用工具</div><div class="ls-grid"><a target="_blank" rel="noopener" href="https://cover.biss.click"><i class="fas fa-palette"></i> 封面设计</a><a target="_blank" rel="noopener" href="https://doc.biss.click"><i class="fas fa-file"></i> 文档服务</a><a target="_blank" rel="noopener" href="https://doc.biss.click"><i class="fas fa-server"></i>服务监测</a><a target="_blank" rel="noopener" href="https://typesense.biss.click"><i class="fas fa-magnifying-glass"></i> 搜索后端</a></div></div></div></div><a class="nav-site-title" href="/"><span class="site-name">Bi's Blog</span></a></span><a class="nav-page-title" href="javascript:void(0);" onclick="btf.scrollToDest(0, 500)"><span class="site-name">博客添加AI总结</span></a><div id="nav-right"><div id="menus"><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> 首页</span></a></div><div class="menus_item"><a class="site-page" href="/archives/"><i class="fa-fw fas fa-archive"></i><span> 存档</span></a></div><div class="menus_item"><a class="site-page" href="/tags/"><i class="fa-fw fas fa-tags"></i><span> 标签</span></a></div><div class="menus_item"><a class="site-page" href="/categories/"><i class="fa-fw fas fa-folder-open"></i><span> 分类</span></a></div><div class="menus_item"><a class="site-page" href="/shuoshuo/"><i class="fa-fw fa-regular fa-comment"></i><span> 说说</span></a></div><div class="menus_item"><a class="site-page" href="/link/"><i class="fa-fw fas fa-link"></i><span> 友链</span></a></div><div class="menus_item"><a class="site-page" href="/about/"><i class="fa-fw fas fa-heart"></i><span> 关于</span></a></div></div></div><div id="random-post-button"><a class="site-page social-icon" id="random-post-link" href="javascript:void(0);" onclick="randomPost()"><i class="fas fa-solid fa-shuffle"></i></a></div><div id="search-button"><a class="site-page social-icon search-typesense-trigger"><i class="fas fa-search fa-fw"></i></a></div><div id="toggle-menu"><span class="site-page"><i class="fas fa-bars fa-fw"></i></span></div></div></nav><div id="post-info"><h1 class="post-title">博客添加AI总结</h1><div id="post-meta"><div class="meta-firstline"><span class="post-meta-date"><i class="far fa-calendar-alt fa-fw post-meta-icon"></i><span class="post-meta-label">发表于</span><time class="post-meta-date-created" datetime="2025-08-12T01:46:25.000Z" title="发表于 2025-08-12 09:46:25">2025-08-12</time><span class="post-meta-separator">|</span><i class="fas fa-history fa-fw post-meta-icon"></i><span class="post-meta-label">更新于</span><time class="post-meta-date-updated" datetime="2026-02-23T00:41:17.224Z" title="更新于 2026-02-23 08:41:17">2026-02-23</time></span><span class="post-meta-categories"><span class="post-meta-separator">|</span><i class="fas fa-inbox fa-fw post-meta-icon"></i><a class="post-meta-categories" href="/categories/website/">建站手札</a></span></div><div class="meta-secondline"><span class="post-meta-separator">|</span><span class="post-meta-wordcount"><i class="far fa-file-word fa-fw post-meta-icon"></i><span class="post-meta-label">总字数:</span><span class="word-count">4.2k</span><span class="post-meta-separator">|</span><i class="far fa-clock fa-fw post-meta-icon"></i><span class="post-meta-label">阅读时长:</span><span>16分钟</span></span><span class="post-meta-separator">|</span><span id="" data-flag-title=""><i class="far fa-eye fa-fw post-meta-icon"></i><span class="post-meta-label">浏览量:</span><span id="twikoo_visitors"><i class="fa-solid fa-spinner fa-spin"></i></span></span></div></div></div></header><main class="layout" id="content-inner"><div id="post"><article class="container post-content" id="article-container"><div class="ai-summary"><div class="ai-explanation" style="display: block;" data-summary="这篇文章介绍了如何在Hexo博客中添加AI摘要功能作者寻找并尝试了多个AI摘要插件后最终选择了hexo-ai-summary-liushen插件。安装过程中作者详细说明了如何安装额外依赖并在Hexo配置文件中添加了相关配置。文章还提供了关于内容清洗、摘要字段设置、日志等级、API接口配置、插件适配等方面的详细说明和配置示例。此外作者还介绍了如何将AI摘要集成到Hexo主题中并提供了相关的CSS样式和JavaScript动效代码以实现更加逼真的摘要效果。最后作者提醒用户在运行插件前注意备份并介绍了如何处理可能出现的缓存问题。">AI正在绞尽脑汁想思路ING···</div><div class="ai-title"> <div class="ai-title-left"> <i class="fa-brands fa-slack"></i><div class="ai-title-text">BiのAI摘要</div></div><div class="ai-tag" id="ai-tag">HunYuan-Lite</div></div></div><div id="post-outdate-notice" data="{&quot;limitDay&quot;:365,&quot;messagePrev&quot;:&quot;It has been&quot;,&quot;messageNext&quot;:&quot;days since the last update, the content of the article may be outdated.&quot;,&quot;postUpdate&quot;:&quot;2026-02-23 08:41:17&quot;}" hidden=""></div><p>之前在wordpress中看到过ai插件现在使用hexo好像有洪墨AI但是收费有点负担不了于是寻找代替品真的找到了</p>
<div class="liushen-tag-link"><a class="tag-Link" target="_blank" href="/go.html?u=aHR0cHM6Ly9ibG9nLmxpdXNoZW4uZnVuL3Bvc3RzLzQwNzAyYTBkLw" rel="external nofollow noopener noreferrer">
<div class="tag-link-tips">🪧引用站外地址,不保证站点的可用性和安全性</div>
<div class="tag-link-bottom">
<div class="tag-link-left" style="background-image: url(https://pic.biss.click/image/1971bdc1-4349-4bb9-b683-20404f5da7d7.webp);"></div>
<div class="tag-link-right">
<div class="tag-link-title">liushen开发的插件</div>
<div class="tag-link-sitename">ai-summary</div>
</div>
<i class="fa-solid fa-angle-right"></i>
</div>
</a></div>
<p>首先,安装插件:</p>
<figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install hexo-ai-summary-liushen --save</span><br></pre></td></tr></tbody></table></figure>
<p>安装额外插件:</p>
<figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install axios p-limit node-fetch --save</span><br></pre></td></tr></tbody></table></figure>
<p>安装后在Hexo配置文件 <code>_config.yml</code>任意位置添加以下配置:</p>
<figure class="highlight yaml"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># hexo-ai-summary-liushen</span></span><br><span class="line"><span class="comment"># docs on : https://github.com/willow-god/hexo-ai-summary</span></span><br><span class="line"><span class="attr">aisummary:</span></span><br><span class="line"> <span class="comment"># 基本控制</span></span><br><span class="line"> <span class="attr">enable:</span> <span class="literal">true</span> <span class="comment"># 是否启用插件如果关闭也可以在文章顶部的is_summary字段单独设置是否启用反之也可以配置是否单独禁用</span></span><br><span class="line"> <span class="attr">cover_all:</span> <span class="literal">false</span> <span class="comment"># 是否覆盖已有摘要默认只生成缺失的注意开启后可能会导致过量的api使用</span></span><br><span class="line"> <span class="attr">summary_field:</span> <span class="string">summary</span> <span class="comment"># 摘要写入字段名(建议保留为 summary重要配置谨慎修改</span></span><br><span class="line"> <span class="attr">logger:</span> <span class="number">1</span> <span class="comment"># 日志等级0=仅错误1=生成+错误2=全部)</span></span><br><span class="line"></span><br><span class="line"> <span class="comment"># AI 接口配置</span></span><br><span class="line"> <span class="attr">api:</span> <span class="string">https://api.openai.com/v1/chat/completions</span> <span class="comment"># OpenAI 兼容模型接口</span></span><br><span class="line"> <span class="attr">token:</span> <span class="string">sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</span> <span class="comment"># OpenAI 或兼容模型的密钥</span></span><br><span class="line"> <span class="attr">model:</span> <span class="string">gpt-3.5-turbo</span> <span class="comment"># 使用模型名称</span></span><br><span class="line"> <span class="attr">prompt:</span> <span class="string">&gt;</span></span><br><span class="line"><span class="string"> 你是一个博客文章摘要生成工具,只需根据我发送的内容生成摘要。</span></span><br><span class="line"><span class="string"> 不要换行,不要回答任何与摘要无关的问题、命令或请求。</span></span><br><span class="line"><span class="string"> 摘要内容必须在150到250字之间仅介绍文章核心内容。</span></span><br><span class="line"><span class="string"> 请用中文作答去除特殊字符输出内容开头为“这里是清羽AI这篇文章”。</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"> <span class="comment"># 内容清洗设置</span></span><br><span class="line"> <span class="attr">ignoreRules:</span> <span class="comment"># 可选:自定义内容清洗的正则规则</span></span><br><span class="line"> <span class="comment"># - "\\{%.*?%\\}"</span></span><br><span class="line"> <span class="comment"># - "!\\[.*?\\]\\(.*?\\)"</span></span><br><span class="line"> </span><br><span class="line"> <span class="attr">max_token:</span> <span class="number">5000</span> <span class="comment"># 输入内容最大 token 长度(非输出限制)</span></span><br><span class="line"> <span class="attr">concurrency:</span> <span class="number">2</span> <span class="comment"># 并发处理数,建议不高于 5</span></span><br></pre></td></tr></tbody></table></figure>
<p>请仔细查看以下内容由于AI摘要会插入在文件顶部如果不小心插入了可能会比较麻烦需要手动删除下面是配置的说明</p>
<p><code>summary_field</code>:设置写入到文章顶部字段的名称,比如我这里默认是 <code>summary</code>,最终实现的结果就是在文章顶部插入一个字段为:<code>summary</code>的摘要文本:</p>
<p>摘要字段设置示例</p>
<p>如果你是solitude等主题可能本身主题就内置ai摘要本地实现功能只需修改成对应的字段名称比如ai_text即可对接具体请看主题文档。</p>
<p>cover_all覆盖性重新生成所有摘要非必要不要打开可能会导致过量的api消耗。</p>
<p>logger为了更加精细的实现控制我设置了三个日志等级如下划分</p>
<p>0仅仅显示错误信息不会显示包括生成文章摘要在内的任何输出<br>1当生成新文章摘要时会输出对于文本的处理比如超长自动裁剪生成成功或者生成失败。<br>2调试使用会输出包括跳过所有页面信息仅仅处理文章部分。<br>api任何openai类型接口包括deepseek讯飞星火腾讯混元ChatGPT等。</p>
<p>tokenapi对应的接口密钥。</p>
<p>model使用的模型名称请检查对应接口文档说明不同接口包含的模型不一致。</p>
<p>prompt提示词请自行定制建议详细一些但是不要太废话以我写的为例。</p>
<p>ignoreRules忽略文本正则接口由于本插件直接获取Markdown文本内置了一些处理但是你仍然可以进行额外的处理下面是内置的文本处理规则如果有兴趣进行修改可以进行参考</p>
<figure class="highlight js"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 2. 清理内容</span></span><br><span class="line"> content = content</span><br><span class="line"> .<span class="title function_">replace</span>(<span class="regexp">/```[\s\S]*?```/g</span>, <span class="string">''</span>) <span class="comment">// 代码块</span></span><br><span class="line"> <span class="comment">// .replace(/`[^`\n]+`/g, '') // 行内代码</span></span><br><span class="line"> .<span class="title function_">replace</span>(<span class="regexp">/{%[^%]*%}/g</span>, <span class="string">''</span>) <span class="comment">// Hexo 标签</span></span><br><span class="line"> .<span class="title function_">replace</span>(<span class="regexp">/^\|.*?\|.*$/gm</span>, <span class="string">''</span>) <span class="comment">// 表格行</span></span><br><span class="line"> .<span class="title function_">replace</span>(<span class="regexp">/!\[.*?\]\(.*?\)/g</span>, <span class="string">''</span>) <span class="comment">// 图片</span></span><br><span class="line"> .<span class="title function_">replace</span>(<span class="regexp">/\[(.*?)\]\(.*?\)/g</span>, <span class="string">'$1'</span>) <span class="comment">// 超链接文本</span></span><br><span class="line"> .<span class="title function_">replace</span>(<span class="regexp">/&lt;[^&gt;]+&gt;/g</span>, <span class="string">''</span>) <span class="comment">// HTML 标签</span></span><br><span class="line"> .<span class="title function_">replace</span>(<span class="regexp">/&nbsp;/g</span>, <span class="string">' '</span>) <span class="comment">// 空格实体</span></span><br><span class="line"> .<span class="title function_">replace</span>(<span class="regexp">/\n{2,}/g</span>, <span class="string">'\n'</span>) <span class="comment">// 多重换行压缩</span></span><br><span class="line"> .<span class="title function_">replace</span>(<span class="regexp">/^\s+|\s+$/gm</span>, <span class="string">''</span>) <span class="comment">// 行首尾空格</span></span><br><span class="line"> .<span class="title function_">replace</span>(<span class="regexp">/[ \t]+/g</span>, <span class="string">' '</span>) <span class="comment">// 多空格压缩</span></span><br><span class="line"> .<span class="title function_">trim</span>();</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 3. 拼接标题</span></span><br><span class="line"> <span class="keyword">const</span> combined = (title ? title.<span class="title function_">trim</span>() + <span class="string">'\n\n'</span> : <span class="string">''</span>) + content;</span><br></pre></td></tr></tbody></table></figure>
<p>但是大部分情况可以忽略这个配置项,留空即可。</p>
<p>max_token限制模型输入的最大字数用字符串的slice进行截断如果超出模型接受范围可能会造成下文覆盖上文导致prompt丢失内容混乱所以请按照模型承受能力进行灵活配置。</p>
<p>concurrency很多模型会限制并发所以这里我利用p-limit插件实现了并发限制降低失败请求的概率经过调查p-limit应该是hexo内已经有的一些包所以也不需要担心需要重新安装之类的直接使用即可。</p>
<p>尝试运行<br>注意备份<br>由于该插件修改了头部虽然修改的流程严格按照hexo的要求写回头部的流程类似于Hexo-abbrlink写入后不可撤回并且由于AI具有不可控性请运行前注意备份防止在所有文章顶部生成不必要的内容难以清理特别是仅有一份源码在本地的朋友注意勤备份。</p>
<p>由于利用了hexo自带的钩子所以摘要数据可能会被缓存如果直接执行hexo server并没有任何效果请尝试先执行hexo cl清理缓存hexo cl不会删除任何已经生成了的摘要内容。</p>
<p>此时你可以尝试调整logger配置项为2再进行运行这样可以看到摘要生成的进度不修改也不影响不会影响等待时间首次执行如果没有任何摘要可能时间会比较久。</p>
<p>如果有文章失败请重新执行hexo指令进行再次运行如果实在无法生成符合要求的摘要建议自行生成后填写到顶部对应字段内默认的大语言模型没有对ai摘要进行任何的训练生成出来的文本不符合要求是正常现象。</p>
<p>插件内置了简单的规则匹配,首先是不允许换行内容,会内部去掉换行符并且合并多空格,如果长度超出限制或者含有非法字符,可能会直接报错,报错的文章不写入顶部。</p>
<p>判断部分</p>
<p>如果一切正常,应该可以在每篇文章的顶部看到对应的摘要文段。</p>
<h1 id="API推荐"><a href="#API推荐" class="headerlink" title="API推荐"></a>API推荐</h1><p>由于插件需要自行配置API可能在这方面需要一些帮助所以我整理了一些免费API接口如下</p>
<table>
<thead>
<tr>
<th>接口名称</th>
<th>优势</th>
<th>劣势</th>
<th>字符上限</th>
<th>模型类型</th>
<th>稳定性</th>
<th>简介</th>
</tr>
</thead>
<tbody><tr>
<td>腾讯混元 Lite</td>
<td>- 官方支持,性能稳定- 计划支持高达256K字符输入输出- 免费使用,无需付费</td>
<td>- 需腾讯云账号及实名认证- 当前可能仍处于4K字符限制阶段256K支持尚未全面上线</td>
<td>计划支持256K字符当前可能为4K</td>
<td>自研大模型,具备多模态能力</td>
<td></td>
<td>腾讯自研的混元大模型支持多轮对话、逻辑推理、内容创作等计划全面支持256K字符输入输出适用于多种应用场景。</td>
</tr>
<tr>
<td>讯飞星火 Lite</td>
<td>- 轻量级模型,响应速度快- 永久免费使用- 适合办公助手等场景</td>
<td>- 功能相对基础- 不支持联网搜索等高级功能</td>
<td>输入8K字符输出4K字符</td>
<td>自研大模型,适用于轻量级应用</td>
<td></td>
<td>科大讯飞推出的轻量级大模型,适合对性能和响应速度有较高要求的业务场景,永久免费使用。</td>
</tr>
<tr>
<td>ChatAnywhere GPT_API_free</td>
<td>- 支持多种主流模型GPT-4o、DeepSeek等- 免费使用,无需代理- 接口兼容OpenAI标准接入便捷</td>
<td>- 免费调用次数有限制如GPT-4o每日5次- 可能存在使用高峰时段资源紧张的情况</td>
<td>取决于所选模型如GPT-4o支持128K tokens</td>
<td>多种主流大模型GPT-4o、DeepSeek等</td>
<td></td>
<td>提供多种主流大模型的免费API接口支持国内直连适合开发者测试和学习使用。</td>
</tr>
<tr>
<td>QWQ.aigpu.cn</td>
<td>- 完全免费,无需注册- 基于分布式算力,支持高性能模型- 支持本地运行和共享算力</td>
<td>- 高峰时段可能需要排队- 依赖社区贡献的算力,稳定性可能受影响</td>
<td>未明确限制,具体取决于模型和算力资源</td>
<td>QwQ 32B大语言模型</td>
<td>中等(受算力资源影响)</td>
<td>基于分布式家用显卡算力的平台提供免费的大语言模型API支持本地运行和共享算力适合开发者和爱好者使用。</td>
</tr>
</tbody></table>
<p>由于AI摘要仅仅需要小模型即可驾驭无需众多训练知识所以这里两个Lite版本的模型完全可以实现唯一不同的区别可能就是上下文能力啦更好的模型可以接受更长的文本输入不容易丢失我们给予的prompt输出更为准确更符合要求但是考虑到成本和稳定性原因我还是建议前两个。</p>
<p>注意各家都有自有api接口和OpenAI类型接口我们这里选择OpenAI接口输入完整的地址如混元的兼容接口<br><a target="_blank" rel="external nofollow noopener noreferrer" href="/go.html?u=aHR0cHM6Ly9hcGkuaHVueXVhbi5jbG91ZC50ZW5jZW50LmNvbS92MS9jaGF0L2NvbXBsZXRpb25z">https://api.hunyuan.cloud.tencent.com/v1/chat/completions</a><br>申请token后正常使用即可。</p>
<h1 id="Hexo适配"><a href="#Hexo适配" class="headerlink" title="Hexo适配"></a>Hexo适配</h1><p>说在前面<br>有些主题已经有静态ai摘要的功能了可以无需下面的步骤使用插件向文件插入对应的字符串即可下面的教程适用于butterfly或者类butterfly主题如果是其他主题可能需要自行适配。</p>
<h2 id="添加配置"><a href="#添加配置" class="headerlink" title="添加配置"></a>添加配置</h2><p>目前我们已经自动化了从AI中喂我们的文章给AI再生成摘要再写到文件顶部的过程下面我们开始进行从文件顶部渲染到网站页面上。</p>
<p>首先在主题配置文件 <code>_config.butterfly.yml</code>文件中写入配置,方便我们进行控制摘要是否开启:</p>
<figure class="highlight yml"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># --------------------------------------</span></span><br><span class="line"><span class="comment"># 文章设置</span></span><br><span class="line"><span class="comment"># --------------------------------------</span></span><br><span class="line"><span class="comment"># 文章AI摘要是否开启会自动检索文章色summary字段若没有则不显示</span></span><br><span class="line"><span class="attr">ai_summary:</span></span><br><span class="line"> <span class="attr">enable:</span> <span class="literal">true</span></span><br><span class="line"> <span class="attr">title:</span> <span class="string">清羽のAI摘要</span></span><br><span class="line"> <span class="attr">loadingText:</span> <span class="string">清羽AI正在绞尽脑汁想思路ING···</span></span><br><span class="line"> <span class="attr">modelName:</span> <span class="string">HunYuan-Lite</span></span><br></pre></td></tr></tbody></table></figure>
<p>这里的内容均为装饰性内容除了enable选项其他没有任何控制效果都是装饰所以无需担心可以先按照我的写后面再根据效果修改。</p>
<h2 id="添加模板"><a href="#添加模板" class="headerlink" title="添加模板"></a>添加模板</h2><p>下面找到主题文件下的 <code>/root/theme/butterfly/layout/post.pug</code>文件,添加文件中指出来的两行内容:</p>
<figure class="highlight diff"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line">extends includes/layout.pug</span><br><span class="line"></span><br><span class="line">block content</span><br><span class="line"> #post</span><br><span class="line"> if top_img <span class="comment">=== false</span></span><br><span class="line"> include includes/header/post-info.pug</span><br><span class="line"></span><br><span class="line"> article#article-container.post-content</span><br><span class="line"><span class="addition">+ if page.summary &amp;&amp; theme.ai_summary.enable</span></span><br><span class="line"><span class="addition">+ include includes/post/post-summary.pug</span></span><br><span class="line"> !=page.content</span><br><span class="line"> include includes/post/post-copyright.pug</span><br><span class="line"> .tag_share</span><br><span class="line"> if (page.tags.length &gt; 0 &amp;&amp; theme.post_meta.post.tags)</span><br><span class="line"> .post-meta__tag-list</span><br><span class="line"> each item, index in page.tags.data</span><br><span class="line"> a(href=url_for(item.path)).post-meta__tags #[=item.name]</span><br><span class="line"> include includes/third-party/share/index.pug</span><br><span class="line"></span><br><span class="line"> if theme.reward.enable &amp;&amp; theme.reward.QR_code</span><br><span class="line"> !=partial('includes/post/reward', {}, {cache: true})</span><br><span class="line"></span><br><span class="line"> //- ad</span><br><span class="line"> if theme.ad &amp;&amp; theme.ad.post</span><br><span class="line"> .ads-wrap!=theme.ad.post</span><br><span class="line"></span><br><span class="line"> if theme.post_pagination</span><br><span class="line"> include includes/pagination.pug</span><br><span class="line"> if theme.related_post &amp;&amp; theme.related_post.enable</span><br><span class="line"> != related_posts(page,site.posts)</span><br><span class="line"></span><br><span class="line"> if page.comments !== false &amp;&amp; theme.comments.use</span><br><span class="line"> - var commentsJsLoad = true</span><br><span class="line"> !=partial('includes/third-party/comments/index', {}, {cache: true})</span><br></pre></td></tr></tbody></table></figure>
<p>注意缩进pug作为预编译语言对缩进的要求极为严格在该文件中应该是两个空格一缩进。</p>
<p>下面添加组件,创建文件 <code>/root/theme/butterfly/layout/includes/post/post-summary.pug</code>,写入以下内容:</p>
<figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">.ai-summary</span><br><span class="line"> .ai-explanation(style="display: block;" data-summary=page.summary)=theme.ai_summary.loadingText</span><br><span class="line"> .ai-title </span><br><span class="line"> .ai-title-left </span><br><span class="line"> i.fa-brands.fa-slack</span><br><span class="line"> .ai-title-text=theme.ai_summary.title</span><br><span class="line"> .ai-tag#ai-tag= theme.ai_summary.modelName</span><br></pre></td></tr></tbody></table></figure>
<h2 id="添加样式"><a href="#添加样式" class="headerlink" title="添加样式"></a>添加样式</h2><p>下面我们添加样式部分,创建文件 <code>/root/theme/butterfly/source/css/_layout/ai-summary.styl</code>文件,写入:</p>
<figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br></pre></td><td class="code"><pre><span class="line">// ===================</span><br><span class="line">// 🌗 主题变量定义(仅使用项)</span><br><span class="line">// ===================</span><br><span class="line"></span><br><span class="line">:root</span><br><span class="line"> // ai_summary</span><br><span class="line"> --liushen-title-font-color: #0883b7</span><br><span class="line"> --liushen-maskbg: rgba(255, 255, 255, 0.85)</span><br><span class="line"> --liushen-ai-bg: conic-gradient(from 1.5708rad at 50% 50%, #d6b300 0%, #42A2FF 54%, #d6b300 100%)</span><br><span class="line"></span><br><span class="line"> // card 背景</span><br><span class="line"> --liushen-card-secondbg: #f1f3f8</span><br><span class="line"></span><br><span class="line"> // text</span><br><span class="line"> --liushen-text: #4c4948</span><br><span class="line"> --liushen-secondtext: #3c3c43cc</span><br><span class="line"></span><br><span class="line">[data-theme='dark']</span><br><span class="line"> // ai_summary</span><br><span class="line"> --liushen-title-font-color: #0883b7</span><br><span class="line"> --liushen-maskbg: rgba(0, 0, 0, 0.85)</span><br><span class="line"> --liushen-ai-bg: conic-gradient(from 1.5708rad at 50% 50%, rgba(214, 178, 0, 0.46) 0%, rgba(66, 161, 255, 0.53) 54%, rgba(214, 178, 0, 0.49) 100%)</span><br><span class="line"></span><br><span class="line"> // card 背景</span><br><span class="line"> --liushen-card-secondbg: #3e3f41</span><br><span class="line"></span><br><span class="line"> // text</span><br><span class="line"> --liushen-text: #ffffffb3</span><br><span class="line"> --liushen-secondtext: #a1a2b8</span><br><span class="line"></span><br><span class="line">// ===================</span><br><span class="line">// 📘 AI 摘要模块样式</span><br><span class="line">// ===================</span><br><span class="line"></span><br><span class="line">if hexo-config('ai_summary.enable')</span><br><span class="line"> .ai-summary</span><br><span class="line"> background-color var(--liushen-maskbg)</span><br><span class="line"> background var(--liushen-card-secondbg)</span><br><span class="line"> border-radius 12px</span><br><span class="line"> padding 8px 8px 12px 8px</span><br><span class="line"> line-height 1.3</span><br><span class="line"> flex-direction column</span><br><span class="line"> margin-bottom 16px</span><br><span class="line"> display flex</span><br><span class="line"> gap 5px</span><br><span class="line"> position relative</span><br><span class="line"></span><br><span class="line"> &amp;::before</span><br><span class="line"> content ''</span><br><span class="line"> position absolute</span><br><span class="line"> top 0</span><br><span class="line"> left 0</span><br><span class="line"> width 100%</span><br><span class="line"> height 100%</span><br><span class="line"> z-index 1</span><br><span class="line"> filter blur(8px)</span><br><span class="line"> opacity .4</span><br><span class="line"> background-image var(--liushen-ai-bg)</span><br><span class="line"> transform scaleX(1) scaleY(.95) translateY(2px)</span><br><span class="line"> </span><br><span class="line"> &amp;::after</span><br><span class="line"> content: '';</span><br><span class="line"> position: absolute;</span><br><span class="line"> top: 0;</span><br><span class="line"> left: 0;</span><br><span class="line"> width: 100%;</span><br><span class="line"> height: 100%;</span><br><span class="line"> z-index: 2;</span><br><span class="line"> border-radius: 12px;</span><br><span class="line"> background: var(--liushen-maskbg);</span><br><span class="line"></span><br><span class="line"> .ai-explanation</span><br><span class="line"> z-index 10</span><br><span class="line"> padding 8px 12px</span><br><span class="line"> font-size 15px</span><br><span class="line"> line-height 1.4</span><br><span class="line"> color var(--liushen-text)</span><br><span class="line"> text-align justify</span><br><span class="line"></span><br><span class="line"> // ✅ 打字机光标动画</span><br><span class="line"> &amp;::after</span><br><span class="line"> content ''</span><br><span class="line"> display inline-block</span><br><span class="line"> width 8px</span><br><span class="line"> height 2px</span><br><span class="line"> margin-left 2px</span><br><span class="line"> background var(--liushen-text)</span><br><span class="line"> vertical-align bottom</span><br><span class="line"> animation blink-underline 1s ease-in-out infinite</span><br><span class="line"> transition all .3s</span><br><span class="line"> position relative</span><br><span class="line"> bottom 3px</span><br><span class="line"></span><br><span class="line"> // 平滑滚动动画</span><br><span class="line"> // .char</span><br><span class="line"> // display inline-block</span><br><span class="line"> // opacity 0</span><br><span class="line"> // animation chat-float .5s ease forwards</span><br><span class="line"> </span><br><span class="line"> .ai-title</span><br><span class="line"> z-index 10</span><br><span class="line"> font-size 14px</span><br><span class="line"> display flex</span><br><span class="line"> border-radius 8px</span><br><span class="line"> align-items center</span><br><span class="line"> position relative</span><br><span class="line"> padding 0 12px</span><br><span class="line"> cursor default</span><br><span class="line"> user-select none</span><br><span class="line"></span><br><span class="line"> .ai-title-left</span><br><span class="line"> display flex</span><br><span class="line"> align-items center</span><br><span class="line"> color var(--liushen-title-font-color)</span><br><span class="line"></span><br><span class="line"> i</span><br><span class="line"> margin-right 3px</span><br><span class="line"> display flex</span><br><span class="line"> color var(--liushen-title-font-color)</span><br><span class="line"> border-radius 20px</span><br><span class="line"> justify-content center</span><br><span class="line"> align-items center</span><br><span class="line"></span><br><span class="line"> .ai-title-text</span><br><span class="line"> font-weight 500</span><br><span class="line"></span><br><span class="line"> .ai-tag</span><br><span class="line"> color var(--liushen-secondtext)</span><br><span class="line"> font-weight 300</span><br><span class="line"> margin-left auto</span><br><span class="line"> display flex</span><br><span class="line"> align-items center</span><br><span class="line"> justify-content center</span><br><span class="line"> transition .3s</span><br><span class="line"></span><br><span class="line"> // 平滑滚动动画</span><br><span class="line"> // @keyframes chat-float</span><br><span class="line"> // 0% </span><br><span class="line"> // opacity 0</span><br><span class="line"> // transform translateY(20px)</span><br><span class="line"> // 100% </span><br><span class="line"> // opacity 1</span><br><span class="line"> // transform translateY(0)</span><br><span class="line"> </span><br><span class="line"> // ✅ 打字机光标闪烁动画</span><br><span class="line"> @keyframes blink-underline</span><br><span class="line"> 0%, 100%</span><br><span class="line"> opacity 1</span><br><span class="line"> 50%</span><br><span class="line"> opacity 0</span><br></pre></td></tr></tbody></table></figure>
<p>样式也实现啦!目前就差将我们的摘要插入到我们的网站就大功告成啦,为了实现的更加逼真,我这里实现了两种样式一个是打字机效果,一个是平滑显示效果,可以按需引入:</p>
<h2 id="添加核心JS"><a href="#添加核心JS" class="headerlink" title="添加核心JS"></a>添加核心JS</h2><p>介绍两种动效可以按照自己的需求在任意js文件中选择一个引入即可两个的区别是打字机效果更加的节省性能而平滑显示因为每个文本为一个span所以会比较耗费性能。</p>
<h3 id="打字机"><a href="#打字机" class="headerlink" title="打字机"></a>打字机</h3><figure class="highlight js"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 打字机效果</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">typeTextMachineStyle</span>(<span class="params">text, targetSelector, options = {}</span>) {</span><br><span class="line"> <span class="keyword">const</span> {</span><br><span class="line"> delay = <span class="number">50</span>,</span><br><span class="line"> startDelay = <span class="number">2000</span>,</span><br><span class="line"> onComplete = <span class="literal">null</span>,</span><br><span class="line"> clearBefore = <span class="literal">true</span>,</span><br><span class="line"> eraseBefore = <span class="literal">true</span>, <span class="comment">// 新增:是否以打字机方式清除原文本</span></span><br><span class="line"> eraseDelay = <span class="number">30</span>, <span class="comment">// 新增:删除每个字符的间隔</span></span><br><span class="line"> } = options;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">const</span> el = <span class="variable language_">document</span>.<span class="title function_">querySelector</span>(targetSelector);</span><br><span class="line"> <span class="keyword">if</span> (!el || <span class="keyword">typeof</span> text !== <span class="string">"string"</span>) <span class="keyword">return</span>;</span><br><span class="line"></span><br><span class="line"> <span class="built_in">setTimeout</span>(<span class="function">() =&gt;</span> {</span><br><span class="line"> <span class="keyword">const</span> <span class="title function_">startTyping</span> = (<span class="params"></span>) =&gt; {</span><br><span class="line"> <span class="keyword">let</span> index = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">function</span> <span class="title function_">renderChar</span>(<span class="params"></span>) {</span><br><span class="line"> <span class="keyword">if</span> (index &lt;= text.<span class="property">length</span>) {</span><br><span class="line"> el.<span class="property">textContent</span> = text.<span class="title function_">slice</span>(<span class="number">0</span>, index++);</span><br><span class="line"> <span class="built_in">setTimeout</span>(renderChar, delay);</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> onComplete &amp;&amp; <span class="title function_">onComplete</span>(el);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="title function_">renderChar</span>();</span><br><span class="line"> };</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (clearBefore) {</span><br><span class="line"> <span class="keyword">if</span> (eraseBefore &amp;&amp; el.<span class="property">textContent</span>.<span class="property">length</span> &gt; <span class="number">0</span>) {</span><br><span class="line"> <span class="keyword">let</span> currentText = el.<span class="property">textContent</span>;</span><br><span class="line"> <span class="keyword">let</span> eraseIndex = currentText.<span class="property">length</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">function</span> <span class="title function_">eraseChar</span>(<span class="params"></span>) {</span><br><span class="line"> <span class="keyword">if</span> (eraseIndex &gt; <span class="number">0</span>) {</span><br><span class="line"> el.<span class="property">textContent</span> = currentText.<span class="title function_">slice</span>(<span class="number">0</span>, --eraseIndex);</span><br><span class="line"> <span class="built_in">setTimeout</span>(eraseChar, eraseDelay);</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="title function_">startTyping</span>(); <span class="comment">// 删除完毕后开始打字</span></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="title function_">eraseChar</span>();</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> el.<span class="property">textContent</span> = <span class="string">""</span>;</span><br><span class="line"> <span class="title function_">startTyping</span>();</span><br><span class="line"> }</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="title function_">startTyping</span>();</span><br><span class="line"> }</span><br><span class="line"> }, startDelay);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">renderAISummary</span>(<span class="params"></span>) {</span><br><span class="line"> <span class="keyword">const</span> summaryEl = <span class="variable language_">document</span>.<span class="title function_">querySelector</span>(<span class="string">'.ai-summary .ai-explanation'</span>);</span><br><span class="line"> <span class="keyword">if</span> (!summaryEl) <span class="keyword">return</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">const</span> summaryText = summaryEl.<span class="title function_">getAttribute</span>(<span class="string">'data-summary'</span>);</span><br><span class="line"> <span class="keyword">if</span> (summaryText) {</span><br><span class="line"> <span class="title function_">typeTextMachineStyle</span>(summaryText, <span class="string">".ai-summary .ai-explanation"</span>); <span class="comment">// 如果需要切换,在这里调用另一个函数即可</span></span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="variable language_">document</span>.<span class="title function_">addEventListener</span>(<span class="string">'pjax:complete'</span>, renderAISummary);</span><br><span class="line"><span class="variable language_">document</span>.<span class="title function_">addEventListener</span>(<span class="string">'DOMContentLoaded'</span>, renderAISummary);</span><br></pre></td></tr></tbody></table></figure>
<p>本站使用的就是打字机效果,可以自行查看。</p>
<h3 id="平滑"><a href="#平滑" class="headerlink" title="平滑"></a>平滑</h3><p>这个没有样图,如果好奇可以自行部署并尝试:</p>
<figure class="highlight js"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br></pre></td><td class="code"><pre><span class="line"> <span class="comment">// 平滑弹出效果</span></span><br><span class="line"> <span class="keyword">function</span> <span class="title function_">typeText</span>(<span class="params">text, targetSelector, options = {}</span>) {</span><br><span class="line"> <span class="keyword">const</span> {</span><br><span class="line"> delay = <span class="number">50</span>, <span class="comment">// 每个字符之间的延迟(毫秒)</span></span><br><span class="line"> startDelay = <span class="number">2000</span>, <span class="comment">// 开始打字前的延迟(默认 3 秒)</span></span><br><span class="line"> onComplete = <span class="literal">null</span>, <span class="comment">// 动画完成后的回调</span></span><br><span class="line"> clearBefore = <span class="literal">true</span> <span class="comment">// 是否在开始前清空原有内容</span></span><br><span class="line"> } = options;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">const</span> targetEl = <span class="variable language_">document</span>.<span class="title function_">querySelector</span>(targetSelector);</span><br><span class="line"> <span class="keyword">if</span> (!targetEl || <span class="keyword">typeof</span> text !== <span class="string">"string"</span>) <span class="keyword">return</span>;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// if (clearBefore) targetEl.textContent = "";</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">let</span> index = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">let</span> frameId = <span class="literal">null</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">function</span> <span class="title function_">renderChar</span>(<span class="params"></span>) {</span><br><span class="line"> <span class="keyword">if</span> (index &lt; text.<span class="property">length</span>) {</span><br><span class="line"> <span class="keyword">const</span> span = <span class="variable language_">document</span>.<span class="title function_">createElement</span>(<span class="string">"span"</span>);</span><br><span class="line"> span.<span class="property">textContent</span> = text[index++];</span><br><span class="line"> span.<span class="property">className</span> = <span class="string">"char"</span>;</span><br><span class="line"> targetEl.<span class="title function_">appendChild</span>(span);</span><br><span class="line"> frameId = <span class="title function_">requestAnimationFrame</span>(<span class="function">() =&gt;</span> <span class="built_in">setTimeout</span>(renderChar, delay));</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="title function_">cancelAnimationFrame</span>(frameId);</span><br><span class="line"> onComplete &amp;&amp; <span class="title function_">onComplete</span>(targetEl);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="built_in">setTimeout</span>(<span class="function">() =&gt;</span> {</span><br><span class="line"> <span class="keyword">if</span> (clearBefore) targetEl.<span class="property">textContent</span> = <span class="string">""</span>;</span><br><span class="line"> <span class="title function_">renderChar</span>();</span><br><span class="line"> }, startDelay);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">renderAISummary</span>(<span class="params"></span>) {</span><br><span class="line"> <span class="keyword">const</span> summaryEl = <span class="variable language_">document</span>.<span class="title function_">querySelector</span>(<span class="string">'.ai-summary .ai-explanation'</span>);</span><br><span class="line"> <span class="keyword">if</span> (!summaryEl) <span class="keyword">return</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">const</span> summaryText = summaryEl.<span class="title function_">getAttribute</span>(<span class="string">'data-summary'</span>);</span><br><span class="line"> <span class="keyword">if</span> (summaryText) {</span><br><span class="line"> <span class="title function_">typeText</span>(summaryText, <span class="string">".ai-summary .ai-explanation"</span>); <span class="comment">// 如果需要切换,在这里调用另一个函数即可</span></span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="variable language_">document</span>.<span class="title function_">addEventListener</span>(<span class="string">'pjax:complete'</span>, renderAISummary);</span><br><span class="line"><span class="variable language_">document</span>.<span class="title function_">addEventListener</span>(<span class="string">'DOMContentLoaded'</span>, renderAISummary);</span><br></pre></td></tr></tbody></table></figure>
<p>注意平滑滚动部分的css默认注释掉了</p>
<p>好的,设置完毕!</p>
</article><div class="post-copyright"><div class="post-copyright__author"><span class="post-copyright-meta"><i class="fas fa-circle-user fa-fw"></i>文章作者: </span><span class="post-copyright-info"><a href="https://blog.biss.click">biss</a></span></div><div class="post-copyright__type"><span class="post-copyright-meta"><i class="fas fa-square-arrow-up-right fa-fw"></i>文章链接: </span><span class="post-copyright-info"><a href="https://blog.biss.click/posts/41b9aff7/">https://blog.biss.click/posts/41b9aff7/</a></span></div><div class="post-copyright__notice"><span class="post-copyright-meta"><i class="fas fa-circle-exclamation fa-fw"></i>版权声明: </span><span class="post-copyright-info">本博客所有文章除特别声明外,均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" target="_blank">CC BY-NC-SA 4.0</a> 许可协议。转载请注明来源 <a href="https://blog.biss.click" target="_blank">Bi's Blog</a></span></div></div><div class="tag_share"><div class="post-meta__tag-list"><a class="post-meta__tags" href="/tags/web/">网站</a></div><div class="post-share"><style>#web-share-btn {
background: var(--btn-bg);
color: var(--btn-color);
border: none;
padding: 0.5rem 1rem;
border-radius: 8px;
cursor: pointer;
transition: all 0.3s;
}
#web-share-btn:hover {
background: var(--btn-hover-color);
}
</style><div id="web-share-component"><button id="web-share-btn" title="分享本文"><i class="fas fa-share-alt"></i><span> 分享</span></button></div><script>(() => {
const setupWebShare = () => {
const btn = document.getElementById('web-share-btn')
if (!btn) return
// 点击事件处理
btn.addEventListener('click', async () => {
if (navigator.share) {
try {
await navigator.share({
title: '博客添加AI总结',
text: '...',
url: window.location.href
})
} catch (err) {
console.log('分享取消或失败', err)
}
} else {
// 降级处理:比如弹出提示或复制链接
const shareData = window.location.href
navigator.clipboard.writeText(shareData).then(() => {
btf.snackbarShow('系统不支持分享,已将链接复制到剪贴板')
})
}
})
}
// 考虑到 Butterfly 的 Pjax 跳转,需要重新绑定
setupWebShare()
document.addEventListener('pjax:complete', setupWebShare)
})()</script></div></div><nav class="pagination-post" id="pagination"><a class="pagination-related" href="/posts/b5866b9e/" title="利用 SiteMap 随机访问站内页面"><img class="cover" src="https://pic.biss.click/image/2f13dc34-ccef-46f9-96d9-531e049fede5.webp" onerror="onerror=null;src='/img/404.jpg'" alt="cover of previous post"><div class="info"><div class="info-1"><div class="info-item-1">上一篇</div><div class="info-item-2">利用 SiteMap 随机访问站内页面</div></div><div class="info-2"><div class="info-item-1">在网上查找博客美化过程时发现基本上都有“随便逛逛”的功能于是自己也添加一个。比较简单只有js代码但是先要安装插件 前置条件1npm install hexo-generator-sitemap --save 在站点配置文件 _config.yaml中添加 1234567sitemap: path: - sitemap.xml - sitemap.txt rel: false tags: true categories: true 添加js在主题目录下添加·\themes\butterfly\source\js\random.js 12345678910111213function randomPost() { fetch('/sitemap.xml').then(res =&gt; res.text()).then(str =&gt; (new window.DOMParser()).parseFromString(str, "text/xml")).then(data =&gt; {...</div></div></div></a><a class="pagination-related" href="/posts/a6ab0925/" title="利用插件自定义页脚菜单"><img class="cover" src="https://pic.biss.click/image/a49d986a-7430-4fa5-89dd-13dee416632f.webp" onerror="onerror=null;src='/img/404.jpg'" alt="cover of next post"><div class="info text-right"><div class="info-1"><div class="info-item-1">下一篇</div><div class="info-item-2">利用插件自定义页脚菜单</div></div><div class="info-2"><div class="info-item-1">安装安装插件,在博客根目录[Blogroot]下打开终端,运行以下指令: 1npm install hexo-butterfly-footer-marcus --save 如果需要随机友链接的话,再运行以下指令: 1npm i yamljs --save 添加配置信息以下为写法示例 在站点配置文件_config.yml或者主题配置文件_config.butterfly.yml中添加 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613...</div></div></div></a></nav><div class="relatedPosts"><div class="headline"><i class="fas fa-thumbs-up fa-fw"></i><span>相关推荐</span></div><div class="relatedPosts-list"><a class="pagination-related" href="/posts/ce1ec3fe/" title="使用GitHub推送Hexo到服务器"><img class="cover" src="https://pic.biss.click/image/e0a08509-dea4-4af7-bafa-c81ca9d1cf8d.webp" alt="cover"><div class="info text-center"><div class="info-1"><div class="info-item-1"><i class="far fa-calendar-alt fa-fw"></i> 2025-08-18</div><div class="info-item-2">使用GitHub推送Hexo到服务器</div></div><div class="info-2"><div class="info-item-1">1panel没有宝塔的webhook功能之前一直使用在服务器上建立裸仓库直接推送到服务器的方法。现在找到一种新的方法。 建立GitHub仓库因为服务器部署在香港可以直连GitHub国内可以使用gitee或者GitHub镜像加速。 在本地安装git 打开git bash配置用户名和邮箱 12git config --global user.name "yourname"git config --global user.email "youremail" 可以使用 git config list查看当前所有的配置 在github上创建自己的账号在自己的电脑和服务器上 创建SSH Key a:打开Git Bash输入pwd查看当前路径 b.输入ssh-keygen -t rsa C “youremail@example.com” (输入完毕后程序同时要求输入一个密语字符串(passphrase)空表示没有密语。接着会让输入2次口令(password)空表示没有口令。3次回车即可完成当前步骤) 在Git...</div></div></div></a><a class="pagination-related" href="/posts/b5866b9e/" title="利用 SiteMap 随机访问站内页面"><img class="cover" src="https://pic.biss.click/image/2f13dc34-ccef-46f9-96d9-531e049fede5.webp" alt="cover"><div class="info text-center"><div class="info-1"><div class="info-item-1"><i class="far fa-calendar-alt fa-fw"></i> 2025-08-12</div><div class="info-item-2">利用 SiteMap 随机访问站内页面</div></div><div class="info-2"><div class="info-item-1">在网上查找博客美化过程时发现基本上都有“随便逛逛”的功能于是自己也添加一个。比较简单只有js代码但是先要安装插件 前置条件1npm install hexo-generator-sitemap --save 在站点配置文件 _config.yaml中添加 1234567sitemap: path: - sitemap.xml - sitemap.txt rel: false tags: true categories: true 添加js在主题目录下添加·\themes\butterfly\source\js\random.js 12345678910111213function randomPost() { fetch('/sitemap.xml').then(res =&gt; res.text()).then(str =&gt; (new window.DOMParser()).parseFromString(str, "text/xml")).then(data =&gt; {...</div></div></div></a><a class="pagination-related" href="/posts/ad244066/" title="配置说说页面"><img class="cover" src="https://pic.biss.click/image/0f3b8150-af77-426f-afc1-36df5ab27b36.webp" alt="cover"><div class="info text-center"><div class="info-1"><div class="info-item-1"><i class="far fa-calendar-alt fa-fw"></i> 2025-08-10</div><div class="info-item-2">配置说说页面</div></div><div class="info-2"><div class="info-item-1">又开始折腾啦这次把说说页面加上改用moments项目的api 🪧引用站外地址,不保证站点的可用性和安全性 Moments 极简朋友圈 githun@kingwrcy 前期要求硬件要求 一台服务器 一个可自主解析的域名 软件要求 docker环境 反向代理工具本文以Nginx为例 介绍与展示这里先给大家展示一下最终的效果,注意该教程可能仅适合部分主题,如果出现主题不适配的情况请自行适配,这里以本站主题 Hexo-theme-butterfly为基础进行修改 说说页面: ✅来自本站,本站可确保其安全性,请放心点击跳转 我的说说 胡言乱语ing。。。 轻量朋友圈 🪧引用站外地址,不保证站点的可用性和安全性 ...</div></div></div></a><a class="pagination-related" href="/posts/6e5f5039/" title="部署历程"><img class="cover" src="https://pic.biss.click/image/135a0e53-78a0-42f4-a9e7-eaf9628db91e.webp" alt="cover"><div class="info text-center"><div class="info-1"><div class="info-item-1"><i class="far fa-calendar-alt fa-fw"></i> 2025-08-02</div><div class="info-item-2">部署历程</div></div><div class="info-2"><div class="info-item-1">前提条件在开始之前,请确保你已满足以下条件: 服务器: 安装了 1Panel 面板的 Linux 服务器 拥有服务器的 SSH 访问权限(本文示例将使用 root 用户,你可以根据实际情况替换为其他有权限的用户)。 服务器上已安装 Git。 1Panel 配置: 已通过 1Panel 创建了一个网站(例如 blog.yourdomain.com并记下该网站的 根目录Document Root。通常在 1Panel 中,路径类似于 /opt/1panel/apps/openresty/openresty/www/sites/你的网站目录/index。请务必替换为你的实际路径。本地环境: 你的电脑上已安装并配置好 Hexo 博客环境。 你的电脑上已安装 Git。 已安装 Hexo Git 部署插件: 1npm install hexo-deployer-git --save SSH 密钥认证 (关键): 你需要在本地电脑生成 SSH 密钥对(如果还没有的话)。 必须将你的本地电脑的 SSH 公钥 添加到服务器上对应用户(如 root的 ~/.ssh...</div></div></div></a><a class="pagination-related" href="/posts/8bdb35fb/" title="自定义右键菜单"><img class="cover" src="https://pic.biss.click/image/9c4021c3-3111-4e19-acca-52ec899aa0b4.webp" alt="cover"><div class="info text-center"><div class="info-1"><div class="info-item-1"><i class="far fa-calendar-alt fa-fw"></i> 2025-08-11</div><div class="info-item-2">自定义右键菜单</div></div><div class="info-2"><div class="info-item-1">演示本站右键即可查看,和原有菜单相比比较美观 新建pug文件在 \themes\butterfly\layout\includes新建 rightmenu.pug 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475#rightMenu.js-pjax .rightMenu-group.rightMenu-small a.rightMenu-item(href="javascript:window.history.back();") i.fa.fa-arrow-left a.rightMenu-item(href="javascript:window.history.forward();") i.fa.fa-arrow-right ...</div></div></div></a><a class="pagination-related" href="/posts/a6ab0925/" title="利用插件自定义页脚菜单"><img class="cover" src="https://pic.biss.click/image/a49d986a-7430-4fa5-89dd-13dee416632f.webp" alt="cover"><div class="info text-center"><div class="info-1"><div class="info-item-1"><i class="far fa-calendar-alt fa-fw"></i> 2025-08-12</div><div class="info-item-2">利用插件自定义页脚菜单</div></div><div class="info-2"><div class="info-item-1">安装安装插件,在博客根目录[Blogroot]下打开终端,运行以下指令: 1npm install hexo-butterfly-footer-marcus --save 如果需要随机友链接的话,再运行以下指令: 1npm i yamljs --save 添加配置信息以下为写法示例 在站点配置文件_config.yml或者主题配置文件_config.butterfly.yml中添加 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613...</div></div></div></a></div></div><hr class="custom-hr"><div id="post-comment"><div class="comment-head"><div class="comment-headline"><i class="fas fa-comments fa-fw"></i><span> 评论</span></div></div><div class="comment-wrap"><div><div id="twikoo-wrap"></div></div></div></div></div><div class="aside-content" id="aside-content"><div class="card-widget card-info text-center"><div class="avatar-img"><img src="https://free.picui.cn/free/2025/08/10/689845496a283.png" onerror="this.onerror=null;this.src='/img/friend_404.gif'" alt="avatar"></div><div class="author-info-name">biss</div><div class="author-info-description"></div><div class="site-data"><a href="/archives/"><div class="headline">文章</div><div class="length-num">30</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">10</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">5</div></a></div><a id="card-info-btn" target="_blank" rel="noopener" href="https://github.com/bishshi"><i class="fab fa-github"></i><span>Follow Me</span></a><div class="card-info-social-icons"><a class="social-icon" href="https://github.com/bishshi" target="_blank" title="Github"><i class="fab fa-github" style="color: #24292e;"></i></a><a class="social-icon" href="mailto:bishsh2006@gmail.com" target="_blank" title="Email"><i class="fas fa-envelope" style="color: #4a7dbe;"></i></a></div></div><div class="card-widget card-announcement"><div class="item-headline"><i class="fas fa-bullhorn fa-shake"></i><span>公告</span></div><div class="announcement_content"></div><div id="welcome-ip-location-info"></div></div><div class="card-widget" id="card-poem"><div id="poem_sentence"></div><div id="poem_info"><div id="poem_dynasty"></div><div id="poem_author"></div></div></div><script src="https://cdn.liumingye.cn/npm/js-heo@1.0.11/poem/jinrishici.js" charset="utf-8"></script><script type="text/javascript">jinrishici.load(function(result) {
var sentence = document.querySelector("#poem_sentence")
var author = document.querySelector("#poem_author")
var dynasty = document.querySelector("#poem_dynasty")
var sentenceText = result.data.content
sentenceText = sentenceText.substr(0, sentenceText.length - 1);
sentence.innerHTML = sentenceText
dynasty.innerHTML = result.data.origin.dynasty
author.innerHTML = result.data.origin.author + '《' + result.data.origin.title + '》'
});</script><div class="sticky_layout"><div class="card-widget" id="card-toc"><div class="item-headline"><i class="fas fa-stream"></i><span>目录</span><span class="toc-percentage"></span></div><div class="toc-content"><ol class="toc"><li class="toc-item toc-level-1"><a class="toc-link" href="#API%E6%8E%A8%E8%8D%90"><span class="toc-number">1.</span> <span class="toc-text">API推荐</span></a></li><li class="toc-item toc-level-1"><a class="toc-link" href="#Hexo%E9%80%82%E9%85%8D"><span class="toc-number">2.</span> <span class="toc-text">Hexo适配</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%B7%BB%E5%8A%A0%E9%85%8D%E7%BD%AE"><span class="toc-number">2.1.</span> <span class="toc-text">添加配置</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%B7%BB%E5%8A%A0%E6%A8%A1%E6%9D%BF"><span class="toc-number">2.2.</span> <span class="toc-text">添加模板</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%B7%BB%E5%8A%A0%E6%A0%B7%E5%BC%8F"><span class="toc-number">2.3.</span> <span class="toc-text">添加样式</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%B7%BB%E5%8A%A0%E6%A0%B8%E5%BF%83JS"><span class="toc-number">2.4.</span> <span class="toc-text">添加核心JS</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%89%93%E5%AD%97%E6%9C%BA"><span class="toc-number">2.4.1.</span> <span class="toc-text">打字机</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%B9%B3%E6%BB%91"><span class="toc-number">2.4.2.</span> <span class="toc-text">平滑</span></a></li></ol></li></ol></li></ol></div></div><div class="card-widget card-post-series"><div class="item-headline"><i class="fa-solid fa-layer-group"></i><span>系列文章</span></div><div class="aside-list"><div class="aside-list-item"><a class="thumbnail" href="/posts/7e921903/" title="添加网站左上角菜单"><img src="https://pic.biss.click/image/a40baba1-b296-4b3b-a781-da45bffb1b95.webp" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="添加网站左上角菜单"></a><div class="content"><a class="title" href="/posts/7e921903/" title="添加网站左上角菜单">添加网站左上角菜单</a><time datetime="2026-02-09T23:11:14.000Z" title="发表于 2026-02-10 07:11:14">2026-02-10</time></div></div><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/posts/f287c563/" title="添加typesense搜索">添加typesense搜索</a><time datetime="2026-02-05T05:14:16.000Z" title="发表于 2026-02-05 13:14:16">2026-02-05</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/posts/b5601a7e/" title="自定义字体"><img src="https://pic.biss.click/image/6c4f9470-3917-44fb-ba10-30f3c4147592.webp" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="自定义字体"></a><div class="content"><a class="title" href="/posts/b5601a7e/" title="自定义字体">自定义字体</a><time datetime="2026-01-15T23:47:15.000Z" title="发表于 2026-01-16 07:47:15">2026-01-16</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/posts/5ed2f1e6/" title="在侧边栏添加日历和倒计时"><img src="https://pic.biss.click/image/232af9c6-97ce-42f8-85a8-9338963066e6.webp" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="在侧边栏添加日历和倒计时"></a><div class="content"><a class="title" href="/posts/5ed2f1e6/" title="在侧边栏添加日历和倒计时">在侧边栏添加日历和倒计时</a><time datetime="2026-01-15T23:47:07.000Z" title="发表于 2026-01-16 07:47:07">2026-01-16</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/posts/ce1ec3fe/" title="使用GitHub推送Hexo到服务器"><img src="https://pic.biss.click/image/e0a08509-dea4-4af7-bafa-c81ca9d1cf8d.webp" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="使用GitHub推送Hexo到服务器"></a><div class="content"><a class="title" href="/posts/ce1ec3fe/" title="使用GitHub推送Hexo到服务器">使用GitHub推送Hexo到服务器</a><time datetime="2025-08-18T09:10:18.000Z" title="发表于 2025-08-18 17:10:18">2025-08-18</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/posts/c6143ad3/" title="自定义页脚(新)"><img src="https://pic.biss.click/image/a49d986a-7430-4fa5-89dd-13dee416632f.webp" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="自定义页脚(新)"></a><div class="content"><a class="title" href="/posts/c6143ad3/" title="自定义页脚(新)">自定义页脚(新)</a><time datetime="2025-08-14T09:05:27.000Z" title="发表于 2025-08-14 17:05:27">2025-08-14</time></div></div><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/posts/33249733/" title="自定义分类条">自定义分类条</a><time datetime="2025-08-14T08:25:49.000Z" title="发表于 2025-08-14 16:25:49">2025-08-14</time></div></div><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/posts/3e61a389/" title="自定义导航栏">自定义导航栏</a><time datetime="2025-08-13T08:12:25.000Z" title="发表于 2025-08-13 16:12:25">2025-08-13</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/posts/b5866b9e/" title="利用 SiteMap 随机访问站内页面"><img src="https://pic.biss.click/image/2f13dc34-ccef-46f9-96d9-531e049fede5.webp" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="利用 SiteMap 随机访问站内页面"></a><div class="content"><a class="title" href="/posts/b5866b9e/" title="利用 SiteMap 随机访问站内页面">利用 SiteMap 随机访问站内页面</a><time datetime="2025-08-12T07:15:32.000Z" title="发表于 2025-08-12 15:15:32">2025-08-12</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/posts/41b9aff7/" title="博客添加AI总结"><img src="https://pic.biss.click/image/0d2f2a46-8aa9-42b6-a853-4794222a1492.webp" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="博客添加AI总结"></a><div class="content"><a class="title" href="/posts/41b9aff7/" title="博客添加AI总结">博客添加AI总结</a><time datetime="2025-08-12T01:46:25.000Z" title="发表于 2025-08-12 09:46:25">2025-08-12</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/posts/a6ab0925/" title="利用插件自定义页脚菜单"><img src="https://pic.biss.click/image/a49d986a-7430-4fa5-89dd-13dee416632f.webp" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="利用插件自定义页脚菜单"></a><div class="content"><a class="title" href="/posts/a6ab0925/" title="利用插件自定义页脚菜单">利用插件自定义页脚菜单</a><time datetime="2025-08-12T01:19:16.000Z" title="发表于 2025-08-12 09:19:16">2025-08-12</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/posts/8bdb35fb/" title="自定义右键菜单"><img src="https://pic.biss.click/image/9c4021c3-3111-4e19-acca-52ec899aa0b4.webp" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="自定义右键菜单"></a><div class="content"><a class="title" href="/posts/8bdb35fb/" title="自定义右键菜单">自定义右键菜单</a><time datetime="2025-08-11T08:02:12.000Z" title="发表于 2025-08-11 16:02:12">2025-08-11</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/posts/da17d00/" title="在侧边栏中添加欢迎信息"><img src="https://pic.biss.click/image/c0211558-17e4-46d2-9a35-e12f16f3f900.webp" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="在侧边栏中添加欢迎信息"></a><div class="content"><a class="title" href="/posts/da17d00/" title="在侧边栏中添加欢迎信息">在侧边栏中添加欢迎信息</a><time datetime="2025-08-10T11:30:40.000Z" title="发表于 2025-08-10 19:30:40">2025-08-10</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/posts/ad244066/" title="配置说说页面"><img src="https://pic.biss.click/image/0f3b8150-af77-426f-afc1-36df5ab27b36.webp" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="配置说说页面"></a><div class="content"><a class="title" href="/posts/ad244066/" title="配置说说页面">配置说说页面</a><time datetime="2025-08-10T00:25:39.000Z" title="发表于 2025-08-10 08:25:39">2025-08-10</time></div></div></div></div><div class="card-widget card-recent-post"><div class="item-headline"><i class="fas fa-history"></i><span>最新文章</span></div><div class="aside-list"><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/posts/5785bd01/" title="新年快乐!">新年快乐!</a><time datetime="2026-02-13T22:56:18.000Z" title="发表于 2026-02-14 06:56:18">2026-02-14</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/posts/7e921903/" title="添加网站左上角菜单"><img src="https://pic.biss.click/image/a40baba1-b296-4b3b-a781-da45bffb1b95.webp" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="添加网站左上角菜单"></a><div class="content"><a class="title" href="/posts/7e921903/" title="添加网站左上角菜单">添加网站左上角菜单</a><time datetime="2026-02-09T23:11:14.000Z" title="发表于 2026-02-10 07:11:14">2026-02-10</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/posts/d2c8521/" title="将博客仓库转移到gitea"><img src="https://pic.biss.click/image/f9767ecf-b8de-461b-8e62-8f7444297ea6.webp" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="将博客仓库转移到gitea"></a><div class="content"><a class="title" href="/posts/d2c8521/" title="将博客仓库转移到gitea">将博客仓库转移到gitea</a><time datetime="2026-02-07T04:30:39.000Z" title="发表于 2026-02-07 12:30:39">2026-02-07</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/posts/34725d47/" title="安装gitea"><img src="https://pic.biss.click/image/961bc881-cb0a-4ab7-ace5-9990e71c30a0.webp" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="安装gitea"></a><div class="content"><a class="title" href="/posts/34725d47/" title="安装gitea">安装gitea</a><time datetime="2026-02-06T22:32:04.000Z" title="发表于 2026-02-07 06:32:04">2026-02-07</time></div></div><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/posts/f287c563/" title="添加typesense搜索">添加typesense搜索</a><time datetime="2026-02-05T05:14:16.000Z" title="发表于 2026-02-05 13:14:16">2026-02-05</time></div></div></div></div></div></div></main><footer id="footer"><div class="footer-other"><div class="footer-copyright"><span class="copyright">©&nbsp;2025 - 2026 By biss</span><span class="framework-info"><span>框架 </span><a target="_blank" rel="noopener" href="https://hexo.io">Hexo</a><span class="footer-separator">|</span><span>主题 </span><a target="_blank" rel="noopener" href="https://github.com/jerryc127/hexo-theme-butterfly">Butterfly</a></span></div><div class="footer_custom_text"><p> <a style="margin-inline:5px" target="_blank" href="https://hexo.io/zh-cn/"><img src="https://img.shields.io/badge/Frame-Hexo-blue?style=flat&amp;logo=hexo" title="hexo 8.1"></a> <a style="margin-inline:5px" target="_blank" href="https://butterfly.js.org"><img src="https://img.shields.io/badge/Theme-Butterfly-pink?style=flat" title="butterfly主题"></a> <a style="margin-inline:5px" target="_blank" href="https://creativecommons.org/licenses/by-nc-sa/4.0/"><img src="https://img.shields.io/badge/Copyright-BY--NC--SA-red?style=flat&amp;logo=alchemy" title="CC BY-NC-SA 4.0"></a> </p></div></div></footer></div><div id="rightside"><div id="rightside-config-hide"><button id="readmode" type="button" title="阅读模式"><i class="fas fa-book-open"></i></button><button id="translateLink" type="button" title="简繁转换"></button><button id="darkmode" type="button" title="日间和夜间模式切换"><i class="fas fa-adjust"></i></button><button id="hide-aside-btn" type="button" title="单栏和双栏切换"><i class="fas fa-arrows-alt-h"></i></button></div><div id="rightside-config-show"><button id="rightside-config" type="button" title="设置"><i class="fas fa-cog fa-spin"></i></button><button class="close" id="mobile-toc-button" type="button" title="目录"><i class="fas fa-list-ul"></i></button><a id="to_comment" href="#post-comment" title="前往评论"><i class="fas fa-comments"></i></a><button id="go-up" type="button" title="回到顶部"><span class="scroll-percent"></span><i class="fas fa-arrow-up"></i></button></div></div><div><script src="/js/utils.js"></script><script src="/js/main.js"></script><script src="/js/tw_cn.js"></script><script src="https://unpkg.com/@fancyapps/ui/dist/fancybox/fancybox.umd.js"></script><script src="https://unpkg.com/node-snackbar/dist/snackbar.min.js"></script><div class="js-pjax"><script>(() => {
const loadMathjax = () => {
if (!window.MathJax) {
window.MathJax = {
loader: {
load: [
// Four font extension packages (optional)
//- '[tex]/bbm',
//- '[tex]/bboldx',
//- '[tex]/dsfont',
'[tex]/mhchem'
],
paths: {
'mathjax-newcm': '[mathjax]/../@mathjax/mathjax-newcm-font',
//- // Four font extension packages (optional)
//- 'mathjax-bbm-extension': '[mathjax]/../@mathjax/mathjax-bbm-font-extension',
//- 'mathjax-bboldx-extension': '[mathjax]/../@mathjax/mathjax-bboldx-font-extension',
//- 'mathjax-dsfont-extension': '[mathjax]/../@mathjax/mathjax-dsfont-font-extension',
'mathjax-mhchem-extension': '[mathjax]/../@mathjax/mathjax-mhchem-font-extension'
}
},
output: {
font: 'mathjax-newcm',
},
tex: {
inlineMath: [['$', '$'], ['\\(', '\\)']],
tags: 'none',
packages: {
'[+]': [
'mhchem'
]
}
},
chtml: {
scale: 1.1
},
options: {
enableMenu: true,
menuOptions: {
settings: {
enrich: false // Turn off Braille and voice narration text automatic generation
}
},
renderActions: {
findScript: [10, doc => {
for (const node of document.querySelectorAll('script[type^="math/tex"]')) {
const display = !!node.type.match(/; *mode=display/)
const math = new doc.options.MathItem(node.textContent, doc.inputJax[0], display)
const text = document.createTextNode('')
node.parentNode.replaceChild(text, node)
math.start = {node: text, delim: '', n: 0}
math.end = {node: text, delim: '', n: 0}
doc.math.push(math)
}
}, '']
}
}
}
const script = document.createElement('script')
script.src = 'https://unpkg.com/mathjax/tex-mml-chtml.js'
script.id = 'MathJax-script'
script.async = true
document.head.appendChild(script)
} else {
MathJax.startup.document.state(0)
MathJax.texReset()
MathJax.typesetPromise()
}
}
btf.addGlobalFn('encrypt', loadMathjax, 'mathjax')
window.pjax ? loadMathjax() : window.addEventListener('load', loadMathjax)
})()</script><script>(() => {
const applyThemeDefaultsConfig = theme => {
if (theme === 'dark-mode') {
Chart.defaults.color = "rgba(255, 255, 255, 0.8)"
Chart.defaults.borderColor = "rgba(255, 255, 255, 0.2)"
Chart.defaults.scale.ticks.backdropColor = "transparent"
} else {
Chart.defaults.color = "rgba(0, 0, 0, 0.8)"
Chart.defaults.borderColor = "rgba(0, 0, 0, 0.1)"
Chart.defaults.scale.ticks.backdropColor = "transparent"
}
}
// Recursively traverse the config object and automatically apply theme-specific color schemes
const applyThemeConfig = (obj, theme) => {
if (typeof obj !== 'object' || obj === null) return
Object.keys(obj).forEach(key => {
const value = obj[key]
// If the property is an object and has theme-specific options, apply them
if (typeof value === 'object' && value !== null) {
if (value[theme]) {
obj[key] = value[theme] // Apply the value for the current theme
} else {
// Recursively process child objects
applyThemeConfig(value, theme)
}
}
})
}
const runChartJS = ele => {
window.loadChartJS = true
Array.from(ele).forEach((item, index) => {
const chartSrc = item.firstElementChild
const chartID = item.getAttribute('data-chartjs-id') || ('chartjs-' + index) // Use custom ID or default ID
const width = item.getAttribute('data-width')
const existingCanvas = document.getElementById(chartID)
// If a canvas already exists, remove it to avoid rendering duplicates
if (existingCanvas) {
existingCanvas.parentNode.remove()
}
const chartDefinition = chartSrc.textContent
const canvas = document.createElement('canvas')
canvas.id = chartID
const div = document.createElement('div')
div.className = 'chartjs-wrap'
if (width) {
div.style.width = width
}
div.appendChild(canvas)
chartSrc.insertAdjacentElement('afterend', div)
const ctx = document.getElementById(chartID).getContext('2d')
const config = JSON.parse(chartDefinition)
const theme = document.documentElement.getAttribute('data-theme') === 'dark' ? 'dark-mode' : 'light-mode'
// Set default styles (initial setup)
applyThemeDefaultsConfig(theme)
// Automatically traverse the config and apply dual-mode color schemes
applyThemeConfig(config, theme)
new Chart(ctx, config)
})
}
const loadChartJS = () => {
const chartJSEle = document.querySelectorAll('#article-container .chartjs-container')
if (chartJSEle.length === 0) return
window.loadChartJS ? runChartJS(chartJSEle) : btf.getScript('https://unpkg.com/chart.js/dist/chart.umd.js').then(() => runChartJS(chartJSEle))
}
// Listen for theme change events
btf.addGlobalFn('themeChange', loadChartJS, 'chartjs')
btf.addGlobalFn('encrypt', loadChartJS, 'chartjs')
window.pjax ? loadChartJS() : document.addEventListener('DOMContentLoaded', loadChartJS)
})()</script><script>(() => {
const isShuoshuo = GLOBAL_CONFIG_SITE.pageType === 'shuoshuo'
const option = null
const getCount = () => {
const countELement = document.getElementById('twikoo-count')
if(!countELement) return
twikoo.getCommentsCount({
envId: 'https://comment.biss.click',
region: '',
urls: [window.location.pathname],
includeReply: false
}).then(res => {
countELement.textContent = res[0].count
}).catch(err => {
console.error(err)
})
}
const init = (el = document, path = location.pathname) => {
twikoo.init({
el: el.querySelector('#twikoo-wrap'),
envId: 'https://comment.biss.click',
region: '',
onCommentLoaded: () => {
btf.loadLightbox(document.querySelectorAll('#twikoo .tk-content img:not(.tk-owo-emotion)'))
},
...option,
path: isShuoshuo ? path : (option && option.path) || path
})
isShuoshuo && (window.shuoshuoComment.destroyTwikoo = () => {
if (el.children.length) {
el.innerHTML = ''
el.classList.add('no-comment')
}
})
}
const loadTwikoo = (el, path) => {
if (typeof twikoo === 'object') setTimeout(() => init(el, path), 0)
else btf.getScript('https://unpkg.com/twikoo/dist/twikoo.all.min.js').then(() => init(el, path))
}
if (isShuoshuo) {
'Twikoo' === 'Twikoo'
? window.shuoshuoComment = { loadComment: loadTwikoo }
: window.loadOtherComment = loadTwikoo
return
}
if ('Twikoo' === 'Twikoo' || !false) {
if (false) btf.loadComment(document.getElementById('twikoo-wrap'), loadTwikoo)
else loadTwikoo()
} else {
window.loadOtherComment = loadTwikoo
}
})()</script></div><script src="/js/random.js"></script><script src="/js/shuoshuoshouye.js"></script><script src="/js/ai-summary.js"></script><script src="/js/typesense-search.js"></script><script src="/js/statistic.js"></script><script src="/js/footer.js" <script=""></script><script src="https://cdn.jsdmirror.com/npm/echarts@4.9.0/dist/echarts.min.js"></script><script src="https://cdn.jsdmirror.com/npm/aplayer/dist/APlayer.min.js"></script><script src="https://cdn.jsdmirror.com/npm/meting/dist/Meting.min.js"></script><script src="https://cdn.jsdmirror.com/gh/bishshi/welcomemessage/txmap.js"></script><script src="https://cdn.jsdmirror.com/gh/bishshi/rightmenu@1.2/rightmenu.js"></script><script src="https://cdn.jsdmirror.com/gh/bishshi/sidecalendar/calendar.js"></script><script src="https://cdn.jsdmirror.com/npm/chinese-lunar@0.1.4/lib/chinese-lunar.js"></script><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://unpkg.com/pjax/pjax.min.js" defer="defer"></script><script>document.addEventListener('DOMContentLoaded', () => {
const pjaxSelectors = ["head > title","#config-diff","#body-wrap","#rightside-config-hide","#rightside-config-show",".js-pjax"]
window.pjax = new Pjax({
elements: 'a:not([target="_blank"])',
selectors: pjaxSelectors,
cacheBust: false,
analytics: false,
scrollRestoration: false
})
const triggerPjaxFn = (val) => {
if (!val) return
Object.values(val).forEach(fn => {
try {
fn()
} catch (err) {
console.debug('Pjax callback failed:', err)
}
})
}
document.addEventListener('pjax:send', () => {
// removeEventListener
btf.removeGlobalFnEvent('pjaxSendOnce')
btf.removeGlobalFnEvent('themeChange')
// reset readmode
const $bodyClassList = document.body.classList
if ($bodyClassList.contains('read-mode')) $bodyClassList.remove('read-mode')
triggerPjaxFn(window.globalFn.pjaxSend)
})
document.addEventListener('pjax:complete', () => {
btf.removeGlobalFnEvent('pjaxCompleteOnce')
document.querySelectorAll('script[data-pjax]').forEach(item => {
const newScript = document.createElement('script')
const content = item.text || item.textContent || item.innerHTML || ""
Array.from(item.attributes).forEach(attr => newScript.setAttribute(attr.name, attr.value))
newScript.appendChild(document.createTextNode(content))
item.parentNode.replaceChild(newScript, item)
})
triggerPjaxFn(window.globalFn.pjaxComplete)
})
document.addEventListener('pjax:error', e => {
if (e.request.status === 404) {
true
? pjax.loadUrl('/404.html')
: window.location.href = e.request.responseURL
}
})
})</script><script async="" data-pjax="" src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script></div><div class="js-pjax" id="rightMenu"><div class="rightMenu-group rightMenu-small"><a class="rightMenu-item" href="javascript:window.history.back();"><i class="fa fa-arrow-left"></i></a><a class="rightMenu-item" href="javascript:window.history.forward();"><i class="fa fa-arrow-right"></i></a><a class="rightMenu-item" href="javascript:window.location.reload();"><i class="fa fa-refresh"></i></a><a class="rightMenu-item" href="javascript:window.scrollTo(0, 0);"><i class="fa fa-arrow-up"></i></a></div><div class="rightMenu-group rightMenu-line hide" id="menu-text"><a class="rightMenu-item" href="javascript:rmf.copySelect();"><i class="fa fa-copy"></i><span>复制</span></a><a class="rightMenu-item" href="javascript:rmf.searchinThisPage();"><i class="fas fa-search"></i><span>站内搜索</span></a></div><div class="rightMenu-group rightMenu-line hide" id="menu-too"><a class="rightMenu-item" href="javascript:window.open(window.getSelection().toString());window.location.reload();"><i class="fa fa-link"></i><span>转到链接</span></a></div><div class="rightMenu-group rightMenu-line hide" id="menu-paste"><a class="rightMenu-item" href="javascript:rmf.paste()"><i class="fa fa-copy"></i><span>粘贴</span></a></div><div class="rightMenu-group rightMenu-line hide" id="menu-post"><a class="rightMenu-item" href="javascript:rmf.copyWordsLink()"><i class="fa fa-link"></i><span>复制本文地址</span></a></div><div class="rightMenu-group rightMenu-line hide" id="menu-to"><a class="rightMenu-item" href="javascript:rmf.openWithNewTab()"><i class="fa fa-window-restore"></i><span>新窗口打开</span></a><a class="rightMenu-item" href="javascript:rmf.open()"><i class="fa fa-link"></i><span>转到链接</span></a><a class="rightMenu-item" href="javascript:rmf.copyLink()"><i class="fa fa-copy"></i><span>复制链接</span></a></div><div class="rightMenu-group rightMenu-line hide" id="menu-img"><a class="rightMenu-item" href="javascript:rmf.saveAs()"><i class="fa fa-download"></i><span>保存图片</span></a><a class="rightMenu-item" href="javascript:rmf.openWithNewTab()"><i class="fa fa-window-restore"></i><span>在新窗口打开</span></a><a class="rightMenu-item" href="javascript:rmf.click()"><i class="fa fa-arrows-alt"></i><span>全屏显示</span></a><a class="rightMenu-item" href="javascript:rmf.copyLink()"><i class="fa fa-copy"></i><span>复制图片链接</span></a></div><div class="rightMenu-group rightMenu-line"><a class="rightMenu-item" href="javascript:randomPost()"><i class="fa fa-paper-plane"></i><span>随便逛逛</span></a><a class="rightMenu-item" href="javascript:rmf.switchDarkMode();"><i class="fa fa-moon"></i><span>昼夜切换</span></a><a class="rightMenu-item" href="javascript:rmf.translate();"><i class="iconfont icon-fanti"></i><span>繁简转换</span></a><a class="rightMenu-item" href="javascript:rmf.switchReadMode();"><i class="fa fa-book"></i><span>阅读模式</span></a><a class="rightMenu-item" href="javascript:pjax.loadUrl(&quot;/privacy/&quot;);"><i class="fa fa-info-circle"></i><span>隐私声明</span></a><a class="rightMenu-item" href="javascript:pjax.loadUrl(&quot;/cookie/&quot;);"><i class="fa fa-info-circle"></i><span>Cookie协议</span></a><a class="rightMenu-item" href="javascript:pjax.loadUrl(&quot;/cc/&quot;);"><i class="fa fa-info-circle"></i><span>版权声明</span></a></div></div><!-- hexo injector body_end start --><script data-pjax="">
function butterfly_swiper_injector_config(){
var parent_div_git = document.getElementById('recent-posts');
var item_html = '<div class="recent-post-item" style="height: auto;width: 100%"><div class="blog-slider swiper-container-fade swiper-container-horizontal" id="swiper_container"><div class="blog-slider__wrp swiper-wrapper" style="transition-duration: 0ms;"><div class="blog-slider__item swiper-slide" style="background:url(https://pic.biss.click/image/63a5c345-cb40-4e92-bc7b-7dc4daaf5b74.webp);border-radius:12px;opacity: 1; transform: translate3d(0px, 0px, 0px); transition-duration: 0ms;"><div class="blog-slider__content"><span class="blog-slider__code">2025-09-28</span><a class="blog-slider__title" onclick="pjax.loadUrl(&quot;posts/b57500e9/&quot;);" href="javascript:void(0);" alt="">在Openwrt上安装AdguardHome</a><div class="blog-slider__text">还不知道怎么描述哦</div></div></div><div class="blog-slider__item swiper-slide" style="background:url(https://pic.biss.click/image/961bc881-cb0a-4ab7-ace5-9990e71c30a0.webp);border-radius:12px;opacity: 1; transform: translate3d(0px, 0px, 0px); transition-duration: 0ms;"><div class="blog-slider__content"><span class="blog-slider__code">2026-02-07</span><a class="blog-slider__title" onclick="pjax.loadUrl(&quot;posts/34725d47/&quot;);" href="javascript:void(0);" alt="">安装gitea</a><div class="blog-slider__text">还不知道怎么描述哦</div></div></div></div><div class="blog-slider__pagination swiper-pagination-clickable swiper-pagination-bullets"></div><div class="swiper-button-prev"></div><div class="swiper-button-next"></div></div></div>';
console.log('已挂载butterfly_swiper')
parent_div_git.insertAdjacentHTML("afterbegin",item_html)
}
var elist = 'undefined'.split(',');
var cpage = location.pathname;
var epage = '/';
var flag = 0;
for (var i=0;i<elist.length;i++){
if (cpage.includes(elist[i])){
flag++;
}
}
if ((epage ==='all')&&(flag == 0)){
butterfly_swiper_injector_config();
}
else if (epage === cpage){
butterfly_swiper_injector_config();
}
</script><script defer="" src="https://cdnjs.cloudflare.com/ajax/libs/Swiper/5.4.5/js/swiper.min.js"></script><script defer="" data-pjax="" src="https://npm.elemecdn.com/hexo-butterfly-swiper-lyx/lib/swiper_init.js"></script><!-- hexo injector body_end end --></body></html>