本文介绍了在宝塔系统上基于 MySQL,采用 Docker部署 Waline 的方法,并提供 Github 社交登陆,渐变彩色邮件通知模板!

准备工作

创建waline 数据库

以 mysql 数据库为例

创建mysql数据库

MySQL 数据库初始化

https://waline.js.org/guide/database.html#mysql

https://github.com/walinejs/waline/blob/main/assets/waline.sql

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
SET NAMES utf8mb4;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;


# Dump of table wl_Comment
# ------------------------------------------------------------

CREATE TABLE `wl_Comment` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `user_id` int(11) DEFAULT NULL,
  `comment` text,
  `insertedAt` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
  `ip` varchar(100) DEFAULT '',
  `link` varchar(255) DEFAULT NULL,
  `mail` varchar(255) DEFAULT NULL,
  `nick` varchar(255) DEFAULT NULL,
  `pid` int(11) DEFAULT NULL,
  `rid` int(11) DEFAULT NULL,
  `sticky` boolean DEFAULT NULL,
  `status` varchar(50) NOT NULL DEFAULT '',
  `like` int(11) DEFAULT NULL,
  `ua` text,
  `url` varchar(255) DEFAULT NULL,
  `createdAt` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
  `updatedAt` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;



# Dump of table wl_Counter
# ------------------------------------------------------------

CREATE TABLE `wl_Counter` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `time` int(11) DEFAULT NULL,
  `reaction0` int(11) DEFAULT NULL,
  `reaction1` int(11) DEFAULT NULL,
  `reaction2` int(11) DEFAULT NULL,
  `reaction3` int(11) DEFAULT NULL,
  `reaction4` int(11) DEFAULT NULL,
  `reaction5` int(11) DEFAULT NULL,
  `reaction6` int(11) DEFAULT NULL,
  `reaction7` int(11) DEFAULT NULL,
  `reaction8` int(11) DEFAULT NULL,
  `url` varchar(255) NOT NULL DEFAULT '',
  `createdAt` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
  `updatedAt` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;



# Dump of table wl_Users
# ------------------------------------------------------------

CREATE TABLE `wl_Users` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `display_name` varchar(255) NOT NULL DEFAULT '',
  `email` varchar(255) NOT NULL DEFAULT '',
  `password` varchar(255) NOT NULL DEFAULT '',
  `type` varchar(50) NOT NULL DEFAULT '',
  `label` varchar(255) DEFAULT NULL,
  `url` varchar(255) DEFAULT NULL,
  `avatar` varchar(255) DEFAULT NULL,
  `github` varchar(255) DEFAULT NULL,
  `twitter` varchar(255) DEFAULT NULL,
  `facebook` varchar(255) DEFAULT NULL,
  `google` varchar(255) DEFAULT NULL,
  `weibo` varchar(255) DEFAULT NULL,
  `qq` varchar(255) DEFAULT NULL,
  `2fa` varchar(32) DEFAULT NULL,
  `createdAt` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
  `updatedAt` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;




/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;

管理数据库

导入sql初始化文件

执行sql初始化文件

docker 安装 waline

vps.yml 文件

# docker compose文件 

version: "3"
services:
  waline:
    container_name: waline
    image: lizheming/waline:latest
    hostname: waline
    restart: always
    volumes:
      - /www/docker/waline/data:/app/data
    network_mode: host
    env_file:
      - .env # 由于单引号和双引号过多,邮件通知模板只能放在这里面
    environment:
      TZ: 'Asia/Shanghai'
      
      MYSQL_DB: 'waline'
      MYSQL_USER: 'waline'
      MYSQL_PASSWORD: '[随机密码]' # 前面创建数据库时生成的随机密码
      
      SITE_NAME: '夜法之书'
      SITE_URL: 'https://blog.17lai.site'
      SECURE_DOMAINS: 'blog.17lai.site,blog.17lai.fun'
      AUTHOR_EMAIL: 'xxx@gmail.com'
      
      # 电报通知
      TG_BOT_TOKEN: 'xxxxx'
      TG_CHAT_ID: 'xxxxx'
      
      # 邮件通知
      SMTP_SERVICE: '126'
      SMTP_HOST: 'smtp.126.com'
      SMTP_PORT: '465'
      SMTP_USER: 'xxxxx@126.com'
      SMTP_PASS: 'xxxxx'
      SENDER_NAME: '夜法之书'
      SENDER_EMAIL: 'xxxxx@126.com'	# 注意这里需要和 SMTP_USER 一致
      
      AKISMET_KEY: xxxxx	# 反垃圾邮件
      
      LEVELS: '0,10,20,50,100,200'
      DISABLE_REGION: 'true'
      
      # google RECAPTCHA
      RECAPTCHA_V3_KEY: xxxx
      RECAPTCHA_V3_SECRET: xxxx
      
      # github 社交登录
      GITHUB_ID: xxxx
      GITHUB_SECRET: xxxx

注意这里的端口地址,并使用host模式,以方便连接主机的 MySQL 数据库

.env文件

MAIL_SUBJECT='{{parent.nick | safe}},『{{site.name | safe}}』上的评论收到了回复'
MAIL_TEMPLATE='<div style="border-radius: 10px 10px 10px 10px;font-size:14px;color:#555555;width: 666px;font-family:"Century Gothic","Trebuchet MS","Hiragino Sans GB",微软雅黑,"Microsoft Yahei",Tahoma,Helvetica,Arial,"SimSun",sans-serif;margin:50px auto;border:1px solid #eee;max-width:100%;background: #ffffff repeating-linear-gradient(-45deg,#fff,#fff 1.125rem,transparent 1.125rem,transparent 2.25rem);box-shadow: 0 1px 5px rgba(0, 0, 0, 0.15);"><div style="width:100%;background:#49BDAD;color:#ffffff;border-radius: 10px 10px 0 0;background-image: -moz-linear-gradient(0deg, rgb(67, 198, 184), rgb(255, 209, 244));background-image: -webkit-linear-gradient(0deg, rgb(67, 198, 184), rgb(255, 209, 244));height: 66px;"><p style="font-size:15px;word-break:break-all;padding: 23px 32px;margin:0;background-color: hsla(0,0%,100%,.4);border-radius: 10px 10px 0 0;">您在<a style="text-decoration:none;color: #ffffff;" href="{{site.url}}" target="_blank">{{site.name}}</a>上的留言有新回复啦!</p></div><div style="margin:40px auto;width:90%"><p>Hi, {{parent.nick}},您曾在文章上发表评论:</p><div style="background: #fafafa repeating-linear-gradient(-45deg,#fff,#fff 1.125rem,transparent 1.125rem,transparent 2.25rem);box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15);margin:20px 0px;padding:15px;border-radius:5px;font-size:14px;color:#555555;">{{self.comment | safe}}</div><p><strong>{{self.nick}}</strong> 给您的回复如下:</p><div style="background:#fafafa repeating-linear-gradient(-45deg,#fff,#fff 1.125rem,transparent 1.125rem,transparent 2.25rem);box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15);margin:20px 0px;padding:15px;border-radius:5px;font-size:14px;color:#555555;">{{self.comment | safe}}</div><p>您可以点击<a style="text-decoration:none; color:#12addb" href="{{site.postUrl}}" target="_blank">查看回复的完整內容</a>,欢迎再次光临<a style="text-decoration:none; color:#12addb" href="{{site.url}}" target="_blank">{{site.name}}</a>。<hr /><p style="font-size:12px;color:#b7adad">本邮件为系统自动发送,请勿直接回复邮件哦,可到博文内容回复。</p></p><style type="text/css">a:link{text-decoration:none}a:visited{text-decoration:none}a:hover{text-decoration:none}a:active{text-decoration:none}</style></div></div>'
MAIL_SUBJECT_ADMIN='{{site.name | safe}} 上有新评论了'
MAIL_TEMPLATE_ADMIN='<div style="border-radius: 10px 10px 10px 10px;font-size:14px;color:#555555;width: 666px;font-family:"Century Gothic","Trebuchet MS","Hiragino Sans GB",微软雅黑,"Microsoft Yahei",Tahoma,Helvetica,Arial,"SimSun",sans-serif;margin:50px auto;border:1px solid #eee;max-width:100%;background: #ffffff repeating-linear-gradient(-45deg,#fff,#fff 1.125rem,transparent 1.125rem,transparent 2.25rem);box-shadow: 0 1px 5px rgba(0, 0, 0, 0.15);"><div style="width:100%;background:#49BDAD;color:#ffffff;border-radius: 10px 10px 0 0;background-image: -moz-linear-gradient(0deg, rgb(67, 198, 184), rgb(255, 209, 244));background-image: -webkit-linear-gradient(0deg, rgb(67, 198, 184), rgb(255, 209, 244));height: 66px;"><p style="font-size:15px;word-break:break-all;padding: 23px 32px;margin:0;background-color: hsla(0,0%,100%,.4);border-radius: 10px 10px 0 0;">您在<a style="text-decoration:none;color: #ffffff;"href="{{site.url}}"target="_blank">{{site.name}}</a>上的留言有新评论啦!</p></div><div style="margin:40px auto;width:90%"><p>{{self.nick}}回复说:</p><div style="background: #fafafa repeating-linear-gradient(-45deg,#fff,#fff 1.125rem,transparent 1.125rem,transparent 2.25rem);box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15);margin:20px 0px;padding:15px;border-radius:5px;font-size:14px;color:#555555;">{{self.comment | safe}}</div><p>您可以点击<a style="text-decoration:none; color:#12addb"href="{{site.postUrl}}"target="_blank">查看回复的完整內容</a>。<hr/></p><style type="text/css">a:link{text-decoration:none}a:visited{text-decoration:none}a:hover{text-decoration:none}a:active{text-decoration:none}</style></div></div>'

由于单引号和双引号过多,邮件通知模板只能放在env文件里面

这个邮件通知模板效果如下

Waline 邮件通知

安装waline

docker-compose -p "container" -f ./vps.yml up -d --build

域名配置

域名设置

waline 域名配置

设置反向代理

宝塔设置反向代理方法如下

waline 反向代理配置

DNS 配置

这里以DNSPod 为例

直接使用ip就是如下示例

DNSpod 配置

如果使用vercel ,那么域名配置方法如下

cname-china.vercel-dns.com

vercel 部署 waline dns 配置

添加 GitHub 社交登录

  1. 开启 GitHub 账号登录功能需要配置 GitHub OAuth 密钥。点击 Register a new OAuth application 进入 GitHub OAuth 应用申请页面。

配置注意事项如下:

  • Application name: 应用名称,会在用户授权时显示,推荐使用博客名称。
  • Homepage URL: 应用主页地址,会在用户授权时显示,推荐使用博客地址。
  • Appcation description: 应用描述,会在用户授权时显示,非必填项。
  • Authorization callback URL: 应用的回调地址,登录时需要使用。填入 <serverURL>/oauth/github 其中 <serverURL> 是你的 Waline 服务端地址。
  1. 填写完成后点击 Register application 即可成功创建。页面中会显示 Client ID。点击 Client secrets 栏右边的 Generate a new client secret 按钮则可以获取到该应用的 Client secrets。

显示在 GitHub的 Settings -> Developer settings -> OAuth Apps -> 又见苍岚

github 社交登录配置

  1. 使用以上信息配置环境变量,重新部署。
环境变量名称备注
GITHUB_ID对应 GitHub OAuth App 中的 Client ID
GITHUB_SECRET对应 GitHub OAuth App 中的 Client secrets
  1. 之后即可使用 GitHub 登录

github waline 登录

添加邮件通知

上文中已经在 docker compose 文件中添加了邮件通知功能,下面介绍另一个邮件通知模板

紫罗兰永恒花园信笺模板

这个模板测试还存在一些bug, css 需要一些调整

紫罗兰永恒花园信笺模板

.env

MAIL_SUBJECT='{{parent.nick | safe}},『{{site.name | safe}}』上的评论收到了回复'
MAIL_TEMPLATE='<div style="background: url(https://npm.elemecdn.com/sarakale-assets@v1/Article/email/bg2.png);padding:20px 0px 20px;margin:0px;background-color:#d6d6d6;width:100%;"><style type="text/css">@media screen and (max-width:600px){.afterimg,.beforeimg{display:none!important}}</style><div style="border-radius: 10px 10px 10px 10px;font-size:14px;color: #555555;width: 530px;font-family:"Century Gothic","Trebuchet MS","Hiragino Sans GB",微软雅黑,"Microsoft Yahei",Tahoma,Helvetica,Arial,"SimSun",sans-serif;margin:50px auto;max-width:100%;background: ##ffffff;"><img class="beforeimg" style="margin-top: -30px;margin-bottom: -120px;width:530px;height:317px;z-index:-100;pointer-events:none" src="https://npm.elemecdn.com/hexo-butterfly-envelope/lib/before.png"><img src="https://npm.elemecdn.com/hexo-butterfly-envelope/lib/violet.jpg" style="width:100%;overflow:hidden;pointer-events:none"><div style="width:100%;background:#f8d1ce;color:#9d2850;border-radius: 10px 10px 0 0;background-image: -moz-linear-gradient(0deg, rgb(67, 198, 184), rgb(255, 209, 244));height: 66px;background: url(https://npm.elemecdn.com/sarakale-assets@v1/Article/email/line034_666x66.png) left top no-repeat;"><p style="font-size:16px;font-weight: bold;text-align:center;word-break:break-all;padding: 23px 32px;margin:0;">您在<a style="text-decoration:none;color: #9d2850;" href="{{site.url}}">『{{site.name | safe}}』</a>上的留言有新回复啦!</p></div><div class="formmain" style="background:#fff;width:96%;max-width:800px;margin:auto auto;border-radius:5px;border: 1px solid #564f4f59;overflow:hidden;pointer-events:none"><div style="margin:40px auto;width:90%;"><p>Hi,{{parent.nick}},您曾在文章上发表评论:</p><div style="background: #eee;margin:20px 0px;padding:15px;border-radius:5px;font-size:15px;color:#555555;">{{parent.comment | safe}}</div><p><strong>{{self.nick}}</strong> 给您的回复如下:</p><div style="background: #eee;margin:20px 0px;padding:15px;border-radius:5px;font-size:15px;color:#555555;">{{self.comment | safe}}</div><p>您可以点击<a style="text-decoration:none; color:#cf5c83" href="{{site.postUrl}}" target="_blank"> 查看回复的完整內容 </a>,欢迎再次光临<a style="text-decoration:none; color:#cf5c83" href="{{site.url}}" target="_blank"> {{site.name}} </a>。<hr /><p style="font-size:14px;color:#b7adad;text-align:center">本邮件为系统自动发送,请勿直接回复邮件哦,可到博文内容回复。<br />https://example.com</p></p><img src="https://npm.elemecdn.com/hexo-butterfly-envelope/lib/line.png" style="width:100%;margin:25px auto 5px auto;display:block;pointer-events:none"><p class="bottomhr" style="font-size:12px;text-align:center;color:#999">自动书记人偶竭诚为您服务!</p></div></div><img class="afterimg" style="width:530px;height:317px;margin-top: -155px;z-index:100;"src="https://npm.elemecdn.com/hexo-butterfly-envelope/lib/after.png"></div></div>'
MAIL_SUBJECT_ADMIN='{{site.name | safe}} 上有新评论了'
MAIL_TEMPLATE_ADMIN='<div style="background: url(https://npm.elemecdn.com/sarakale-assets@v1/Article/email/bg2.png);padding:20px 0px 20px;margin:0px;background-color:#d6d6d6;width:100%;"><style type="text/css">@media screen and (max-width:600px){.afterimg,.beforeimg{display:none!important}}</style><div style="border-radius: 10px 10px 10px 10px;font-size:14px;color: #555555;width: 530px;font-family:"Century Gothic","Trebuchet MS","Hiragino Sans GB",微软雅黑,"Microsoft Yahei",Tahoma,Helvetica,Arial,"SimSun",sans-serif;margin:50px auto;max-width:100%;background: ##ffffff;"><img class="beforeimg" style="margin-top: -30px;margin-bottom: -120px;width:530px;height:317px;z-index:-100;pointer-events:none" src="https://npm.elemecdn.com/hexo-butterfly-envelope/lib/before.png"><img src="https://npm.elemecdn.com/hexo-butterfly-envelope/lib/violet.jpg" style="width:100%;overflow:hidden;pointer-events:none"><div style="width:100%;background:#f8d1ce;color:#9d2850;border-radius: 10px 10px 0 0;background-image: -moz-linear-gradient(0deg, rgb(67, 198, 184), rgb(255, 209, 244));height: 66px;background: url(https://npm.elemecdn.com/sarakale-assets@v1/Article/email/line034_666x66.png) left top no-repeat;"><p style="font-size:16px;font-weight: bold;text-align:center;word-break:break-all;padding: 23px 32px;margin:0;">您在<a style="text-decoration:none;color: #9d2850;" href="{{site.url}}"target="_blank">{{site.name}}</a>上的文章有了新的评论</p></div><div class="formmain" style="background:#fff;width:96%;max-width:800px;margin:auto auto;border-radius:5px;border: 1px solid #564f4f59;overflow:hidden;pointer-events:none"><div style="margin:40px auto;width:90%;"><p><strong>{{self.nick}}</strong> 回复说:</p><div style="background: #eee;margin:20px 0px;padding:15px;border-radius:5px;font-size:15px;color:#555555;">{{self.comment | safe}}</div><p style="text-align:center;">您可以点击<a style="text-decoration:none;color:#cf5c83" href="{{site.postUrl}}" target="_blank">查看回复的完整內容</a></p><img src="https://npm.elemecdn.com/hexo-butterfly-envelope/lib/line.png" style="width:100%;margin:25px auto 5px auto;display:block;pointer-events:none"><p class="bottomhr" style="font-size:12px;text-align:center;color:#999">自动书记人偶竭诚为您服务!</p></div></div><img class="afterimg" style="width:530px;height:317px;margin-top: -155px;z-index:100;"src="https://npm.elemecdn.com/hexo-butterfly-envelope/lib/after.png"></div></div>'

如果采用vercel部署,修改部署repo 的 ~/index.js 文件

const Application = require('@waline/vercel');
module.exports = Application({
  async postSave(comment) {
  mailSubjectAdmin: '{{site.name | safe}} 上有新评论了',
  mailTemplateAdmin: `<div style="background: url(https://npm.elemecdn.com/sarakale-assets@v1/Article/email/bg2.png);padding:20px 0px 20px;margin:0px;background-color:#d6d6d6;width:100%;">
	<style type="text/css">@media screen and (max-width:600px){.afterimg,.beforeimg{display:none!important}}</style>
	<div style="border-radius: 10px 10px 10px 10px;font-size:14px;color: #555555;width: 530px;font-family:'Century Gothic','Trebuchet MS','Hiragino Sans GB',微软雅黑,'Microsoft Yahei',Tahoma,Helvetica,Arial,'SimSun',sans-serif;margin:50px auto;max-width:100%;background: ##ffffff;">
	<img class="beforeimg" style="margin-top: -30px;margin-bottom: -120px;width:530px;height:317px;z-index:-100;pointer-events:none" src="https://npm.elemecdn.com/hexo-butterfly-envelope/lib/before.png">
	<img src="https://npm.elemecdn.com/hexo-butterfly-envelope/lib/violet.jpg" style="width:100%;overflow:hidden;pointer-events:none">
		<div style="width:100%;background:#f8d1ce;color:#9d2850;border-radius: 10px 10px 0 0;background-image: -moz-linear-gradient(0deg, rgb(67, 198, 184), rgb(255, 209, 244));height: 66px;background: url(https://npm.elemecdn.com/sarakale-assets@v1/Article/email/line034_666x66.png) left top no-repeat;">
		<p style="font-size:16px;font-weight: bold;text-align:center;word-break:break-all;padding: 23px 32px;margin:0;">
		您在<a style="text-decoration:none;color: #9d2850;" href="{{site.url}}"target="_blank">{{site.name}}</a>上的文章有了新的评论</p>
		</div>
		<div class="formmain" style="background:#fff;width:96%;max-width:800px;margin:auto auto;border-radius:5px;border: 1px solid #564f4f59;overflow:hidden;pointer-events:none">
			<div style="margin:40px auto;width:90%;"><p><strong>{{self.nick}}</strong> 回复说:</p>
			<div style="background: #eee;margin:20px 0px;padding:15px;border-radius:5px;font-size:15px;color:#555555;">{{self.comment | safe}}</div>
			<p style="text-align:center;">您可以点击<a style="text-decoration:none;color:#cf5c83" href="{{site.postUrl}}" target="_blank">查看回复的完整內容</a></p>
			<img src="https://npm.elemecdn.com/hexo-butterfly-envelope/lib/line.png" style="width:100%;margin:25px auto 5px auto;display:block;pointer-events:none">
			<p class="bottomhr" style="font-size:12px;text-align:center;color:#999">自动书记人偶竭诚为您服务!</p>
			</div>
		</div>
		<img class="afterimg" style="width:530px;height:317px;margin-top: -155px;z-index:100;"src="https://npm.elemecdn.com/hexo-butterfly-envelope/lib/after.png">
		</div>
</div>`,
  mailSubject: '{{parent.nick}},您在『{{site.name}}』上发表的评论收到了来自 {{self.nick}} 的回复',
  mailTemplate: `<div style="background: url(https://npm.elemecdn.com/sarakale-assets@v1/Article/email/bg2.png);padding:20px 0px 20px;margin:0px;background-color:#d6d6d6;width:100%;">
	<style type="text/css">@media screen and (max-width:600px){.afterimg,.beforeimg{display:none!important}}</style>
	<div style="border-radius: 10px 10px 10px 10px;font-size:14px;color: #555555;width: 530px;font-family:'Century Gothic','Trebuchet MS','Hiragino Sans GB',微软雅黑,'Microsoft Yahei',Tahoma,Helvetica,Arial,'SimSun',sans-serif;margin:50px auto;max-width:100%;background: ##ffffff;">
	<img class="beforeimg" style="margin-top: -30px;margin-bottom: -120px;width:530px;height:317px;z-index:-100;pointer-events:none" src="https://npm.elemecdn.com/hexo-butterfly-envelope/lib/before.png">
	<img src="https://npm.elemecdn.com/hexo-butterfly-envelope/lib/violet.jpg" style="width:100%;overflow:hidden;pointer-events:none">
		<div style="width:100%;background:#f8d1ce;color:#9d2850;border-radius: 10px 10px 0 0;background-image: -moz-linear-gradient(0deg, rgb(67, 198, 184), rgb(255, 209, 244));height: 66px;background: url(https://npm.elemecdn.com/sarakale-assets@v1/Article/email/line034_666x66.png) left top no-repeat;">
		<p style="font-size:16px;font-weight: bold;text-align:center;word-break:break-all;padding: 23px 32px;margin:0;">
		您在<a style="text-decoration:none;color: #9d2850;" href="{{site.url}}">『{{site.name | safe}}』</a>上的留言有新回复啦!</p>
		</div>
		<div class="formmain" style="background:#fff;width:96%;max-width:800px;margin:auto auto;border-radius:5px;border: 1px solid #564f4f59;overflow:hidden;pointer-events:none">
			<div style="margin:40px auto;width:90%;"><p>Hi,{{parent.nick}},您曾在文章上发表评论:</p>
			<div style="background: #eee;margin:20px 0px;padding:15px;border-radius:5px;font-size:15px;color:#555555;">{{parent.comment | safe}}</div>
			<p><strong>{{self.nick}}</strong> 给您的回复如下:</p>
			<div style="background: #eee;margin:20px 0px;padding:15px;border-radius:5px;font-size:15px;color:#555555;">{{self.comment | safe}}</div>
			<p>您可以点击<a style="text-decoration:none; color:#cf5c83" href="{{site.postUrl}}" target="_blank"> 查看回复的完整內容 </a>,欢迎再次光临<a style="text-decoration:none; color:#cf5c83" href="{{site.url}}" target="_blank"> {{site.name}} </a>。<hr />
			<p style="font-size:14px;color:#b7adad;text-align:center">本邮件为系统自动发送,请勿直接回复邮件哦,可到博文内容回复。<br />https://example.com</p>
			</p>
			<img src="https://npm.elemecdn.com/hexo-butterfly-envelope/lib/line.png" style="width:100%;margin:25px auto 5px auto;display:block;pointer-events:none">
			<p class="bottomhr" style="font-size:12px;text-align:center;color:#999">自动书记人偶竭诚为您服务!</p>
			</div>
		</div>
		<img class="afterimg" style="width:530px;height:317px;margin-top: -155px;z-index:100;"src="https://npm.elemecdn.com/hexo-butterfly-envelope/lib/after.png">
		</div>
</div>`
  },
});

注意事项

  • 默认创建好waline 后,尽快创建第一个登录用户! 默认第一个登录用户为管理员, 默认地址为 [域名]/ui, 例如本文中就是 waline.17lai.site/ui
  • waline 自带数据导入导出,目前测试导入同一份数据2次,会使同一份数据在数据库中出现两次!

Cloudflare 设置

使用了 Cloudflare 时需要注意的配置事项!

如果使用了 CF 的服务,不配置这里,waline 就获取不到正确的地理位置,但 CF 还支持下面功能,官方文档

img

设置方法

IP 地理位置

访问者位置标头

Umami UV / PV 统计显示

Umami 统计了 UV PV 等各种访问数据,比不蒜子详细得多,自建服务也比不蒜子稳定。那么怎么用 Umami 代替不蒜子了? 下文将介绍详细方法

新建 View only 权限的用户

Settings` -> `Users` -> `Create user` -> 填写账号密码,`Role` 选择 `View only` -> `Save

新建用户

Q: 为什么不直接调用 Umami 的 API 获取数据,而是要额外创建一个账户?

A: 博客是 静态开源无服务器 的,所有代码都展示在前端,包括 API 调用。而 Umami 的 admin API 权限太大了,如果使用 admin 权限的 API Token,那么这个 token 可以获取、修改、删除所有网站的数据,会有严重的安全隐患。

所以我们需要创建一个 View only 权限的用户,使用这个 低权限的用户的 API Token 来访问我们的浏览量等数据。

新建 Team 并添加用户和网站

Settings -> Teams -> Create team -> 填写名称 -> Save -> 找到刚刚创建的 Team -> Edit -> 复制 Access code,点击 Websites 中点击 Add website 选中你想共享的网站

换一个浏览器登录 Umami(使用View only 权限的用户) -> Settings -> Teams -> Join team -> 输入 Access code -> Join -> 如果没有出错的话,点击 Dashboard 就可以看到你刚刚添加的网站了

获取 View only 用户的 API Token

根据 Umami 的文档,我们可以通过以下方式获取 API Token:

POST /api/auth/login

例如 你的网站地址为 example.com,那么你需要使用 View only 的账户密码向 https://example.com/api/auth/login 发送一个 POST 请求,请求体为:

{
  "username": "your-username",
  "password": "your-password"
}

如果成功,你应该会得到以下的结果:

{
  "token": "eyTMjU2IiwiY...4Q0JDLUhWxnIjoiUE_A",
  "user": {
    "id": "cd33a605-d785-42a1-9365-d6cad3b7befd",
    "username": "your-username",
    "createdAt": "2020-04-20 01:00:00"
  }
}

保存 token 值,并在所有请求中发送带 Bearer <token> 值的 Authorization 标头。请求标头应该如下所示:

Authorization: Bearer eyTMjU2IiwiY...4Q0JDLUhWxnIjoiUE_A

发送请求获取数据

这里要用到类似于 postman 的 API 测试工具,可以使用的是开源的 hoppscotch,你也可以使用 curl 或者其他工具。

先分析一下官方文档的 API 接口:
GET /api/websites/{websiteId}/stats
API

有两个必填的 查询参数:startAtendAt,都是 Unix 毫秒时间戳,表示开始时间和结束时间

websiteIdstartAt 需要我们自己获取

websiteId 可以在 Dashboard -> View details -> 看浏览器栏的地址 https://example.com/websites/{websiteId} 中找到

startAt 可发送 GET 请求到 https://example.com/api/websites/{websiteId},请求头为

Authorization: Bearer eyTMjU2IiwiY...4Q0JDLUhWxnIjoiUE_A

在返回结果中找到 createdAt 字段,这个字段就是 startAt 的值,也就是你的网站创建时间,数据的开始时间
createdAt

编写页面

页面展示

代码如下,修改你对应的参数即可运行:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <div style="text-align:center;">
        <h1>Umami 网站统计</h1>
        <span>总访问量 <span id="umami-site-pv"></span> 次</span>

        <span>总访客数 <span id="umami-site-uv"></span> 人</span>
    </div>

    <script>
        // 从配置文件中获取 umami 的配置
        const website_id = 'xxx';

        // 拼接请求地址
        const request_url = 'https://xxx.com' + '/api/websites/' + website_id + '/stats';

        const start_time = new Date('2024-01-01').getTime();
        const end_time = new Date().getTime();

        const token = 'xxxxxx';

        // 检查配置是否为空
        if (!website_id) {
            throw new Error("Umami website_id is empty");
        }
        if (!request_url) {
            throw new Error("Umami request_url is empty");
        }
        if (!start_time) {
            throw new Error("Umami start_time is empty");
        }
        if (!token) {
            throw new Error("Umami token is empty");
        }

        const params = new URLSearchParams({
            startAt: start_time,
            endAt: end_time,
        });

        const request_header = {
            method: "GET",
            headers: {
                "Content-Type": "application/json",
                "Authorization": "Bearer " + token,
            },
        };

        async function allStats() {
            try {
                const response = await fetch(`${request_url}?${params}`, request_header);
                const data = await response.json();
                const uniqueVisitors = data.pageviews.value; // 获取独立访客数
                const pageViews = data.pageviews.value; // 获取页面浏览量

                let ele1 = document.querySelector("#umami-site-pv")
                if (ele1) {
                    ele1.textContent = pageViews; // 设置页面浏览量
                }

                let ele2 = document.querySelector("#umami-site-uv")
                if (ele2) {
                    ele2.textContent = uniqueVisitors;
                }

                console.log(uniqueVisitors, pageViews);
                console.log(data);
            } catch (error) {
                console.error(error);
                return "-1";
            }
        }
        allStats();
    </script>
</body>

</html>

参考&致谢

雷打真孝子,财发狠心,麻绳专挑细处断,恶运专找苦命人!

​ ——俗语赏析

系列教程

全部文章RSS订阅

Hexo系列

HexoRSS分类订阅

[三万字教程]基于Hexo的matery主题搭建博客并深度优化完全一站式教程

  • markdown 各种其它语法插件,latex公式支持,mermaid图表,plant uml图表,URL卡片,bilibili卡片,github卡片,豆瓣卡片,插入音乐和视频,插入脑图,插入PDF,嵌入iframe

Docker系列

Docker 分类 RSS 订阅

笔记系列

Note分类RSS订阅

Gitbook使用系列

Gitbook分类RSS订阅

Gitlab 使用系列

Gitlab RSS 分类订阅


作者: 夜法之书
版权声明: 本博客所有文章除特別声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 夜法之书 !
评论
数据加载中 ...
 上一篇

阅读全文

如何做一个完整的硬件项目的项目管理之简明教程
如何做一个完整的硬件项目的项目管理之简明教程 如何做一个完整的硬件项目的项目管理之简明教程
以一个硬件项目开发为例,介绍现代公司项目管理的一些基本工具和方法,给行业内外朋友一个初步印象,为广大从业者入门相关管理打下一个初步的,全局的基础!最后给出一个IPD端到端管理项目示例
2023-03-08
下一篇 

阅读全文

生活中的那些有趣的不可能三角介绍与解析
生活中的那些有趣的不可能三角介绍与解析 生活中的那些有趣的不可能三角介绍与解析
成年人的世界充满了自嘲,嘴上挂着“小孩子才做选择,成年人全都要”,现实却是“小孩子才做选择,成年人根本没得选”。背后的种种无奈,通常表现为“不可能三角”
2023-02-14