1799 字
9 分钟Add commentMore actions
Fuwari添加评论功能
示例
---title: Fuwari添加评论功能published: 2025-02-22description: "静态博客养成计划"image: ""tags: ["Fuwari", "教程"]category: Guidesdraft: falsecomments: true---
Waline 评论
Waline 是一款简洁、安全的评论系统。优点:布置简单,功能强大。 官方地址: Waline官方
动手之前先去按照Waline官网教程创建一个账号,并部署好数据库与服务端
安装 Waline 依赖
终端界面输入:
pnpm add -D @waline/client
如果报错缺少 @waline/api
、recaptcha-v3
pnpm i -D @waline/api recaptcha-v3
添加 Waline 评论
- 通过在原有astro组件上修改
- 添加新astro组件以在需要时调用
通过在原有astro组件上修改
NOTE该方式仅单独对文章启用 Waline 评论
- 在
src/config.ts
中的walineConfig
配置项里添入自己部署的 Waline 项目的域名。
export const walineConfig = { //填入你的域名 serverURL: "", login: "force",};
- 在
src/content/config.ts
中添加comments
关键词:
schema: z.object({ title: z.string(), published: z.date(), updated: z.date().optional(), draft: z.boolean().optional().default(false), description: z.string().optional().default(""), image: z.string().optional().default(""), tags: z.array(z.string()).optional().default([]), category: z.string().optional().default(""), lang: z.string().optional().default(""), comments: z.boolean().optional().default(false),
/* For internal use */ prevTitle: z.string().default(""), prevSlug: z.string().default(""), nextTitle: z.string().default(""), nextSlug: z.string().default(""),}),
- 在
src\pages\posts\[...slug].astro
添加 Waline 组件:
修改导包:
import { licenseConfig, walineConfig } from "src/config";
将 Waline 嵌入页脚的两个 </div>
标签后:
如图:
<!-- Waline --> {entry.data.comments !== false && ( <div class="card-base z-10 px-6 md:px-9 pt-6 pb-4 relative w-full mb-4"> <div id="waline" /> <script type="module" is:inline define:vars={{ walineConfig }}> import { init } from 'https://unpkg.com/@waline/client@v3/dist/waline.js'; function loadWaline() { init({ el: '#waline', serverURL: walineConfig.serverURL, login: walineConfig.login, path: location.pathname, wordLimit: ["2", "1000"], dark: '.dark', }); } loadWaline(); </script> </div> )}
在 src\layouts\Layout.astro
约 149 行 </head>
标签前添加
<link rel="stylesheet" href="https://unpkg.com/@waline/client@v3/dist/waline.css" />
TIP如若使用了我后面写到的优化后的waline组件,则
src\pages\posts\[...slug].astro
这样写(Layout.astro无需再添加css样式):
---//在开头处导入组件import Waline from "@components/Waline/Waline.astro";---<!-- Waline -->{entry.data.comments !== false && <Waline client:visible/>}
- 在
src/types/config.ts
声称 comments 类型:
export type BlogPostData = { body: string; title: string; published: Date; description: string; tags: string[]; draft?: boolean; image?: string; category?: string; prevTitle?: string; prevSlug?: string; nextTitle?: string; nextSlug?: string; comments?: boolean;};
添加新astro组件以在需要时调用(TODO)
- 在
src\components
目录下创建Waline.astro
:
并添加内容:
<!-- 引入Waline评论 --><link rel="stylesheet" href="https://unpkg.com/@waline/client@v3/dist/waline.css" /><div id="waline"></div><script type="module"> import { init } from 'https://unpkg.com/@waline/client@v3/dist/waline.js'; // 监听主题变化 function initWaline() { const isDark = document.documentElement.classList.contains('dark');
init({ el: '#waline', serverURL: 'your serverURL', dark: isDark ? 'html.dark' : false, // 关键配置 comment: true, // 评论数统计 reaction: [ // 反馈表情,使用默认的也可以 'https://gcore.jsdelivr.net/gh/norevi/waline-blobcatemojis@1.0/blobs/ablobcatheart.png',//比心 'https://gcore.jsdelivr.net/gh/norevi/waline-blobcatemojis@1.0/blobs/blobcatalt.png', //可爱 'https://gcore.jsdelivr.net/gh/norevi/waline-blobcatemojis@1.0/blobs/ablobcatwave.png',//打招呼 'https://gcore.jsdelivr.net/gh/norevi/waline-blobcatemojis@1.0/blobs/blobcatthink.png',//思考 'https://gcore.jsdelivr.net/gh/norevi/waline-blobcatemojis@1.0/blobs/ablobcatheartbroken.png',//心碎 'https://gcore.jsdelivr.net/gh/norevi/waline-blobcatemojis@1.0/blobs/blobcatgay.png',//难平 ], emoji: [ // 必须使用有效的CDN地址 'https://gcore.jsdelivr.net/gh/norevi/waline-blobcatemojis@1.0/blobs', 'https://cdn.jsdelivr.net/npm/@waline/emojis@1.3.0/qq',
],
}); } // 初始化 initWaline();
// 监听主题切换(根据你的主题实现方式调整) const observer = new MutationObserver(() => { const container = document.getElementById('waline'); if (container && container.innerHTML) { container.innerHTML = ''; // 清空重新初始化 initWaline(); } }); observer.observe(document.documentElement, { attributes: true, attributeFilter: ['class'] });</script>
TODO
并未采用异步策略,可能会增加相关性能开销,后续还要优化已更新
这里暂时使用别人做的优化版astro组件
原主如果看到可以留言嗷
<!-- 1. 先静态显示阅读量/评论数的骨架屏 --><!-- 可选,不需要可以直接删掉下面的--><div id="waline-info"> <div style="display: flex; align-items: center;"> 阅读量: <span class="waline-pageview-count" style="margin-left: 5px;">--</span> </div> <div style="display: flex; align-items: center;"> 评论数:<span class="waline-comment-count" style="margin-left: 5px;">--</span> </div></div>
<!-- 2. 评论容器(初始为空) --><div id="waline"></div>
<!-- 3. 异步加载逻辑 --><script is:inline> (async () => { const loadCSS = () => { const link = document.createElement('link'); link.rel = 'stylesheet'; link.href = 'https://unpkg.com/@waline/client@v3/dist/waline.css'; document.head.appendChild(link); };
const { init } = await import('https://unpkg.com/@waline/client@v3/dist/waline.js');
const initWaline = () => { const isDark = document.documentElement.classList.contains('dark'); init({ el: '#waline', serverURL: 'your serverURL', dark: isDark ? 'html.dark' : false, pageview: true, comment: true, emoji: [ 'https://gcore.jsdelivr.net/gh/norevi/waline-blobcatemojis@1.0/blobs', 'https://cdn.jsdelivr.net/npm/@waline/emojis@1.3.0/qq', ], }); };
// 并行加载资源 loadCSS(); initWaline();
new MutationObserver(() => { const container = document.getElementById('waline'); if (container?.innerHTML) { container.innerHTML = ''; initWaline(); } }).observe(document.documentElement, { attributes: true, attributeFilter: ['class'] }); })();</script>
<style> #waline-info { display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; } #waline { clear: both; }
.waline-pageview-count::before, .waline-comment-count::before { content: ''; display: inline-block; width: 1em; height: 1em; background: #eee; animation: pulse 1.5s infinite; vertical-align: middle; margin-right: 0.3em; } @keyframes pulse { 0%, 100% { opacity: 0.5; } 50% { opacity: 1; } }</style>
推荐使用优化修改后的代码:
---import { walineConfig } from "src/config";
// 将 Waline 的配置项定义在这里,方便传入到客户端脚本const walineOptions = { serverURL: walineConfig.serverURL, comment: true, // 评论数统计 emoji: [ // 必须使用有效的CDN地址 "https://gcore.jsdelivr.net/gh/norevi/waline-blobcatemojis@1.0/blobs", "https://cdn.jsdelivr.net/npm/@waline/emojis@1.3.0/qq", ], reaction: [ // 反馈表情,使用默认的也可以 "https://gcore.jsdelivr.net/gh/norevi/waline-blobcatemojis@1.0/blobs/ablobcatheart.png", //比心 "https://gcore.jsdelivr.net/gh/norevi/waline-blobcatemojis@1.0/blobs/blobcatalt.png", //可爱 "https://gcore.jsdelivr.net/gh/norevi/waline-blobcatemojis@1.0/blobs/ablobcatwave.png", //打招呼 "https://gcore.jsdelivr.net/gh/norevi/waline-blobcatemojis@1.0/blobs/blobcatthink.png", //思考 "https://gcore.jsdelivr.net/gh/norevi/waline-blobcatemojis@1.0/blobs/ablobcatheartbroken.png", //心碎 "https://gcore.jsdelivr.net/gh/norevi/waline-blobcatemojis@1.0/blobs/blobcatgay.png", //难平 ], // Waline v3 的关键配置:当 'html.dark' 类存在时,Waline 会自动切换到暗色模式 // 无需MutationObserver监听,Waline内部会处理 dark: "html.dark", // 你可以在这里添加更多Waline配置,例如 pageview, locale, path等 // pageview: true, // path: typeof window !== "undefined" ? window.location.pathname : "/", // 在SSR时处理window对象 // locale: { // placeholder: '留下你的评论...' // }};---
<!-- 引入 Waline 评论的 CSS,建议放在 head 中或者组件顶部 --><link rel="stylesheet" href="https://unpkg.com/@waline/client@v3/dist/waline.css"/>
<!-- Waline 评论容器 --><div id="waline"></div>
<!--客户端脚本: - 通过 `data-options` 属性将配置安全地传递给客户端脚本。 - 使用动态 import() 来真正懒加载 Waline 的 JS 库。--><script type="module" is:inline id="waline-init-script" data-options={JSON.stringify(walineOptions)}> // 获取脚本标签上的配置数据 const scriptTag = document.getElementById("waline-init-script"); const options = JSON.parse(scriptTag.dataset.options);
// 动态导入 Waline 客户端库 // 只有当组件进入视口时,才会下载 Waline 的 JS 文件 import("https://unpkg.com/@waline/client@v3/dist/waline.js") .then(({ init }) => { init({ el: "#waline", // Waline 挂载的元素ID path: location.pathname, ...options, // 展开传入的配置项 }); console.log("Waline comments initialized successfully!"); }) .catch((err) => { console.error("Failed to load Waline comments:", err); });</script>
<style> /* 可以在这里添加一些针对Waline容器的样式,例如最小高度,加载提示等 */ #waline { clear: both; }</style>
- 在相关astro界面合适的位置导入 Waline 然后调用即可:
---import Waline from '@/components/Waline.astro';---
<!-- 引入评论组件 --><Waline /><!--TODO:如果要动态加载(在被观测到时加载)--><!--还有不少内容要修改,暂时别用--><Waline client:visible />
NOTE博客以内容输出为主,尽可能都以内容优先,视情况动态加载 ;w;
Waline 相关组件属性
管理员与管理面板
首个注册的账号会是管理员,管理面板在 example.yourdomain.com/ui
Giscus 评论
创建 giscus 仓库
- 创建一个新的GitHub库用来存储博客的那些评论,请确保该仓库是 公开的 ,否则访客将无法正常查看
discussion
。 - 给你的这个
repo
仓库安装giscus app
,否则访客将无法评论和回应。 - 确保 Discussions 功能已在你的仓库中启用。
配置 giscus
打开giscus 官方网站,进行配置:
- 语言:选择你目前正在使用的语言
- 仓库:填写你刚刚创建的仓库(格式为你的用户名/仓库名)
- 页面 ↔️ discussion 映射关系(默认即可)
- Discussion 分类(默认即可)
- 特性(默认即可)
- 主题(默认即可)
按照顺序配置好之后,下方会自动生成:
<!-- giscus评论 --> <!-- 评论区域的间距根据实际情况修改 也可以删除 --><div style="margin-top: 20px;"></div><script src="https://giscus.app/client.js" data-repo="[在此输入仓库]" data-repo-id="[在此输入仓库 ID]" data-category="[在此输入分类名]" data-category-id="[在此输入分类 ID]" data-mapping="pathname" data-strict="0" data-reactions-enabled="1" data-emit-metadata="0" data-input-position="bottom" data-theme="preferred_color_scheme" data-lang="zh-CN" crossorigin="anonymous" async></script>
使用 giscus
- 修改对应的如
about.astro
,posts.astro
,archive.astro
等等
在页尾前添加即可
<!-- giscus评论 --></MainGridLayout>
- 创建giscus.astro组件 ,在需要时导入调用
方法同 waline ,照搬即可
Fuwari添加评论功能
https://p1ume.vercel.app/posts/fuwari/comment/