<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Neon on 小景</title>
        <link>https://jingyuan-zheng.github.io/zh/tags/neon/</link>
        <description>Recent content in Neon on 小景</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>zh-Hans</language>
        <copyright>Jingyuan Zheng</copyright>
        <lastBuildDate>Tue, 28 Jul 2026 21:20:00 +0200</lastBuildDate><atom:link href="https://jingyuan-zheng.github.io/zh/tags/neon/index.xml" rel="self" type="application/rss+xml" /><item>
            <title>本站评论系统迁移到 Waline：访客评论、邮件通知与浏览量整合</title>
            <link>https://jingyuan-zheng.github.io/zh/p/waline-comment-system-migration/</link>
            <pubDate>Tue, 28 Jul 2026 21:20:00 +0200</pubDate>
            <guid>https://jingyuan-zheng.github.io/zh/p/waline-comment-system-migration/</guid>
            <description>&lt;img src=&#34;https://jingyuan-zheng.github.io/img/waline-comment-system-migration/featured.png&#34; alt=&#34;Featured image of post 本站评论系统迁移到 Waline：访客评论、邮件通知与浏览量整合&#34; /&gt;&lt;p&gt;本文介绍本站从 Giscus 迁移到 Waline 的原因、现在的评论与浏览量架构、历史数据迁移方法，以及访客评论和双语邮件通知的配置方式。&lt;/p&gt;&#xA;&lt;p&gt;现在打开任意文章，评论区已经换成了新的 Waline 界面。读者不需要 GitHub 账户，可以直接以访客身份参与讨论；如果希望在评论收到回复时得到通知，还可以选择填写邮箱。&lt;/p&gt;&#xA;&lt;p&gt;&lt;img alt=&#34;本站迁移后的 Waline 评论区，包括文章反应、访客评论输入框与评论列表&#34; loading=&#34;lazy&#34; sizes=&#34;(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px&#34; src=&#34;https://jingyuan-zheng.github.io/img/waline-comment-system-migration/featured.png&#34;&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;为什么从-giscus-迁移&#34;&gt;为什么从 Giscus 迁移&#xA;&lt;/h2&gt;&lt;p&gt;Giscus 是一个很适合技术博客的评论方案：它把评论保存在 GitHub Discussions，维护成本低，也很符合开源社区的使用习惯。问题是，发表评论需要登录 GitHub。&lt;/p&gt;&#xA;&lt;p&gt;本站的内容已经不只面向开发者。工具介绍、马耳他生活信息、旅行内容和网站更新会吸引不同背景的读者。要求每位读者先拥有并登录 GitHub，实际上为一次普通留言设置了不必要的门槛。&lt;/p&gt;&#xA;&lt;p&gt;迁移到 Waline 主要是为了获得以下能力：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;支持访客评论，不强制注册或登录；&lt;/li&gt;&#xA;&lt;li&gt;邮箱选填，并可在评论收到回复时发送通知；&lt;/li&gt;&#xA;&lt;li&gt;支持评论点赞、文章反应和评论数量统计；&lt;/li&gt;&#xA;&lt;li&gt;将文章浏览量与评论系统放在同一套计数接口中；&lt;/li&gt;&#xA;&lt;li&gt;提供独立的评论管理后台，不必进入 GitHub Discussions 处理内容；&lt;/li&gt;&#xA;&lt;li&gt;保留中英文界面，并让通知邮件跟随文章语言。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;访客可以不登录，但评论服务仍会为了限流、安全防护和管理处理必要的技术信息。昵称和评论内容会公开显示，邮箱则不会显示在评论区。&lt;/p&gt;&#xA;&lt;h2 id=&#34;现在的托管结构&#34;&gt;现在的托管结构&#xA;&lt;/h2&gt;&lt;p&gt;博客本身仍然是 Hugo 生成的静态网站，由 GitHub Actions 构建并发布到 GitHub Pages。内容编辑使用 Sveltia CMS，文章和页面最终仍保存到 GitHub 仓库。&lt;/p&gt;&#xA;&lt;p&gt;新的评论系统分成两部分：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Waline Server 部署在 Vercel，负责评论 API、管理界面、邮件通知和计数请求；&lt;/li&gt;&#xA;&lt;li&gt;评论、用户、文章互动和浏览量数据存储在 Neon PostgreSQL。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;这种拆分不会把整个博客变成动态网站。GitHub Pages 继续提供静态页面，只有评论区和计数在浏览器中按需请求 Waline API。即使评论服务暂时不可用，文章正文仍然可以正常访问。&lt;/p&gt;&#xA;&lt;p&gt;仪表盘的管理选单也已经更新：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;内容管理&lt;/strong&gt;进入本站的 Sveltia CMS；&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;评论管理&lt;/strong&gt;进入 Waline 管理界面。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;仪表盘的系统信息现在会同时标明内容系统由 GitHub 托管，评论系统使用 Vercel 与 Neon。&lt;/p&gt;&#xA;&lt;h2 id=&#34;评论区怎样融入现有主题&#34;&gt;评论区怎样融入现有主题&#xA;&lt;/h2&gt;&lt;p&gt;Waline 自带完整的输入框、评论列表、排序、Markdown、图片上传和表情选择功能，但默认视觉需要与 Stack 主题进一步协调。&lt;/p&gt;&#xA;&lt;p&gt;我为评论区增加了一层主题适配，包括：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;使用网站现有的卡片背景、边框、圆角和阴影变量；&lt;/li&gt;&#xA;&lt;li&gt;同时适配浅色与深色模式；&lt;/li&gt;&#xA;&lt;li&gt;把浏览量和评论数放进评论须知卡片；&lt;/li&gt;&#xA;&lt;li&gt;保留移动端布局，避免输入框和用户信息被挤压；&lt;/li&gt;&#xA;&lt;li&gt;根据文章语言切换界面文案；&lt;/li&gt;&#xA;&lt;li&gt;使用 Twitter Emoji 风格的表情资源，保持不同系统上的显示一致。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;文章反应目前提供“喜欢、好笑、思考、惊讶、难过”五种选择。它们使用 Waline 的 Twitter Emoji 图片资源，而不是读取访客电脑中的本地表情文件，因此不同浏览器会看到一致的图案。&lt;/p&gt;&#xA;&lt;h2 id=&#34;从-cloudflare-迁移浏览量&#34;&gt;从 Cloudflare 迁移浏览量&#xA;&lt;/h2&gt;&lt;p&gt;本站原来的浏览量系统运行在 Cloudflare Workers 与 D1 上，其中还合并了此前的 GA4 历史数据。迁移评论系统时，我没有从零重新计数，而是把已有统计带到 Waline。&lt;/p&gt;&#xA;&lt;p&gt;迁移快照中，Cloudflare D1 有 82 条原始计数键。部分中文路径同时存在百分号编码和 Unicode 两种形式，例如同一页面可能分别以编码后的中文 URL 和直接中文 URL 出现。&lt;/p&gt;&#xA;&lt;p&gt;迁移过程先对路径做规范化，再把相同页面合并，最终得到 76 个唯一 URL。全站累计浏览量在迁移时为 1,607。&lt;/p&gt;&#xA;&lt;p&gt;目标数据库使用 Waline 的 &lt;code&gt;wl_counter&lt;/code&gt; 表。迁移时还处理了一个容易忽略的问题：该表默认只以数字 ID 为主键，没有强制要求 URL 唯一。早期通过公开 API 并发补数时，同一路径可能产生重复记录。&lt;/p&gt;&#xA;&lt;p&gt;最终采用数据库事务完成整理：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;每个 URL 保留一条计数记录；&lt;/li&gt;&#xA;&lt;li&gt;合并并清理重复项；&lt;/li&gt;&#xA;&lt;li&gt;为 URL 增加唯一索引；&lt;/li&gt;&#xA;&lt;li&gt;使用“只增不减”的写入规则补齐历史数据；&lt;/li&gt;&#xA;&lt;li&gt;核对缺失路径、重复路径和低于源数据的计数。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;验证结果为 76 条目标记录、0 个重复 URL、0 个缺失 URL，并且没有任何页面低于 Cloudflare 的迁移快照。使用“只增不减”规则，也避免了迁移期间的新访问被历史数据覆盖。&lt;/p&gt;&#xA;&lt;h2 id=&#34;全站页面怎样计数&#34;&gt;全站页面怎样计数&#xA;&lt;/h2&gt;&lt;p&gt;新的计数并不只出现在文章页。网站页脚会在非 404 页面加载 Waline 的轻量浏览量模块，为当前页面增加一次访问，同时更新一个专门的全站累计计数。&lt;/p&gt;&#xA;&lt;p&gt;文章评论区显示浏览量时只读取现有数字，不会再次递增，这样可以避免同一次页面加载被页脚和评论组件重复计算。&lt;/p&gt;&#xA;&lt;p&gt;主页、归档、分类、标签、图片墙、链接页、仪表盘和中英文页面都使用同一套新计数系统。旧的 Cloudflare 浏览量接口不再负责前端统计。&lt;/p&gt;&#xA;&lt;h2 id=&#34;邮件通知与双语模板&#34;&gt;邮件通知与双语模板&#xA;&lt;/h2&gt;&lt;p&gt;邮件通知通过 Vercel 环境变量配置。SMTP 账户、应用专用密码和数据库连接信息都保存在托管平台的敏感变量中，不会写入 Hugo 仓库、文章或前端代码。&lt;/p&gt;&#xA;&lt;p&gt;配置项包括：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;SMTP 服务、发件账户和应用专用密码；&lt;/li&gt;&#xA;&lt;li&gt;网站名称、网站地址和站长通知邮箱；&lt;/li&gt;&#xA;&lt;li&gt;发件人名称与地址；&lt;/li&gt;&#xA;&lt;li&gt;评论回复邮件与新评论通知邮件的标题和正文。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Waline 的邮件模板可以读取评论所属页面路径。本站中文文章都位于 &lt;code&gt;/zh/&lt;/code&gt; 下，因此模板会检查评论 URL：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;&#xA;&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;{% if self.url and &amp;#39;/zh/&amp;#39; in self.url %}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  中文通知内容&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;{% else %}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  English notification content&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;{% endif %}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;中文文章下的评论会收到中文邮件，其他页面使用英文邮件。模板只引用评论者昵称、评论正文和文章链接，不会在邮件正文中暴露数据库凭据或其他系统密钥。&lt;/p&gt;&#xA;&lt;p&gt;为了保护账户安全，SMTP 使用的是单独生成的应用专用密码，而不是邮箱账户的日常登录密码。密码更新后必须重新部署 Waline，新的环境变量才会进入生产函数。&lt;/p&gt;&#xA;&lt;h2 id=&#34;评论数据是怎样迁移的&#34;&gt;评论数据是怎样迁移的&#xA;&lt;/h2&gt;&lt;p&gt;旧评论先导出为 Waline JSON 格式，再导入新数据库。迁移时保留了评论正文、文章路径、回复关系、发布时间和审核状态。&lt;/p&gt;&#xA;&lt;p&gt;部分由站长发布的旧评论在导出时缺少用户关联信息。处理时只补齐管理员用户 ID、昵称、邮箱标识、主页和客户端信息，不修改原评论内容、页面、回复关系或时间。&lt;/p&gt;&#xA;&lt;p&gt;这类修复很重要。如果只搬运文字而没有恢复用户关联，旧评论可能会被显示成普通访客留言，头像、站长标记和后续管理权限也会不一致。&lt;/p&gt;&#xA;&lt;h2 id=&#34;隐私与评论须知&#34;&gt;隐私与评论须知&#xA;&lt;/h2&gt;&lt;p&gt;评论区现在使用以下提示：&lt;/p&gt;&#xA;&#xA;    &lt;blockquote&gt;&#xA;        &lt;p&gt;本站支持访客评论。如果您希望获得评论回复通知，可以填写您的邮箱；收到回复时，系统将自动发送通知给您。&lt;/p&gt;&#xA;&#xA;    &lt;/blockquote&gt;&#xA;&lt;p&gt;邮箱不是发表评论的强制条件。填写邮箱的主要用途是回复通知和头像匹配，不会在评论列表中公开显示。&lt;/p&gt;&#xA;&lt;p&gt;由于评论系统会处理评论内容、可选邮箱以及必要的技术信息，本站的&lt;a class=&#34;link&#34; href=&#34;https://jingyuan-zheng.github.io/zh/privacy-policy/&#34; &gt;隐私政策&lt;/a&gt;也已经同步更新，说明 GitHub Pages、Vercel、Neon 和 Waline 在当前架构中的作用。&lt;/p&gt;&#xA;&lt;h2 id=&#34;接下来&#34;&gt;接下来&#xA;&lt;/h2&gt;&lt;p&gt;评论系统迁移已经完成，但它仍需要在真实使用中继续观察。我会关注邮件送达、移动端输入体验、反垃圾策略、数据库计数和不同语言页面的通知效果。&lt;/p&gt;&#xA;&lt;p&gt;如果你在评论时遇到加载失败、通知未送达、路径计数不一致或界面问题，欢迎直接在本文下方以访客身份留言。&lt;/p&gt;&#xA;</description>
        </item></channel>
</rss>
