一、前言

Hexo Boot 博客系统断断续续更新了好几个版本,除了新增后台管理系统的功能外,还对默认主题 UI 进行调整。但众口难调,并不是每次 UI 的修改都符合每个人的审美。故默认主题 UI 此后不再随后端代码进行同步美化和修改,本篇将介绍默认主题美化步骤。

二、目录结构

要美化主题,首先得知道主题目录结构,这样才能针对性对代码进行修改和优化。

主题文件夹位于项目中的resources/templates/theme目录下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
default
├─source # 目录文件夹,存放页面用到的css,javascript,font 等静态资源
├─about.html # 关于页面
├─archives.html # 归档页面
├─categories.html # 分类页面
├─common.html # 公共页面
├─detail.html # 文章详情页面
├─friendLinks.html # 友链页面
├─index.html # 首页页面
├─layout.html # 布局页面(已废除)
├─postList.html # 分类,标签查询页面
├─preview.png # 预览图(1344x768 左右)
├─tags.html # 标签页面
├─theme.json # 主题配置文件

其中,source目录最为重要的文件是css/style.css(现改为 app.css) 和app.js,它们分别影响着 UI 的样式和 UI 动画功能。

三、实战

3.1 让导航图标动起来

首先,打开 common.html 文件,搜索font-awesome.min.css,在其下一行插入如下代码:

1
<link rel="stylesheet" th:href="@{'https://cdn.jsdelivr.net/npm/font-awesome-animation@1.1.1/css/font-awesome-animation.min.css'}" />

font-awesome.min.css 提供了很多对Font Awesome图标起到动画效果的样式。具体资料请点击 font-awesome-animation 查看。

然后,登录博客后台管理系统,打开导航管理菜单,对导航图标进行修改。比如修改首页导航的图标,让其显示抖动效果:

1
2
3
将 fa fa-home 改成 a fa-home faa-ring animated

即添加 faa-ring animated 内容

保存后,打开博客首页,效果如下图:

3.2 滚动条进度

第一步,打开app.js文件,搜索optionEvent函数声明,在$options.append(htmArr.join(""));前一行插入如下代码:

1
htmArr.push('<div class="option-item scroll-progress" title="滚动条进度"><span id="progress-line" class="progress-line"></span><span id="progress-value">0%</span></div> ');

第二步,打开app.css文件,在末尾添加如下代码:

1
2
3
4
5
6
7
8
9
10
11
.options .scroll-progress {
position: relative;
}

.options .scroll-progress .progress-line {
position: absolute;
left: 0;
bottom: 0;
height: 2px;
background: var(--theme-color);
}

第三步,回到app.js文件中定义计算滚动进度的函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const scrollIndicator = function () {
let $window = $(window);
let $progressLine = $("#progress-line");
let $progressValue = $("#progress-value");
let winTop = $window.scrollTop(), docHeight = $(document).height(), winHeight = $(window).height();
calcProcess(winTop, docHeight, winHeight, $progressLine, $progressValue);

$window.on('scroll', function() {
let winTop = $window.scrollTop(), docHeight = $(document).height(), winHeight = $(window).height();
calcProcess(winTop, docHeight, winHeight, $progressLine, $progressValue);
});
};

function calcProcess(winTop, docHeight, winHeight, progressLine, progressValue) {
let scrolled;
let denominator = docHeight - winHeight;
if (denominator > 0) {
scrolled = (winTop / denominator) * 100;
} else {
scrolled = 100;
}
progressValue.html(parseInt(scrolled + "") + '%');
}

最后,添加函数调用代码,需要修改2出地方:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 第一处
$(document).on('pjax:complete', function(e) {
# 添加的代码
scrollIndicator();
...
});


# 第二处
$(function() {
themModeEvent();
optionEvent();
# 添加的代码
scrollIndicator();
...
});

保存文件后,打开博客首页,效果图如下:

3.3 美化表格

打开app.css文件,添加如下代码:

1
2
3
4
5
6
7
8
.postContainer table {
box-shadow: 0 1px 10px 1px var(--shadow-color);
}

.postContainer table th {
background: #4373ca;
color: #fff
}

修改后,效果如如下:

3.4 美化代码块

打开app.css文件,修改和添加如下代码:

修改:

1
2
3
4
5
6
7
8
9
.postContainer .highlight {
...
/*修改代码*/
background-color: #ecf6f7;
/*新加3行代码*/
position: relative;
padding-top: 32px;
box-shadow: 0 1px 10px 3px var(--shadow-color);
}

添加:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
.postContainer figure.highlight::before {
content: " ";
position: absolute;
border-radius: 50%;
background: #fc625d;
width: 12px;
height: 12px;
top: 12px;
left: 12px;
box-shadow: 20px 0 #fdbc40, 40px 0 #35cd4b;
z-index: 2
}

.postContainer figure table {
margin: 0;
width: 100%;
border: none;
box-shadow: none!important;
}

.postContainer .highlight td.code {
width: 100%;
}

保存后,效果如下:

3.5 美化页脚

第一步,打开common.html文件,修改2处地方:

1
2
将 <span class="pull-left" style="left: 10px">❤️[[${#servletContext.getAttribute('configMap')['power_by']}]]</span>
改成 <span class="pull-left" style="left: 10px" th:utext="${#servletContext.getAttribute('configMap')['power_by']}"></span>
1
2
将 <a class="pull-right" href="http://beian.miit.gov.cn/" target="_blank">[[${#servletContext.getAttribute('configMap')['record']}]]</a>
改成 <a class="pull-right" href="http://beian.miit.gov.cn/" target="_blank" th:utext="${#servletContext.getAttribute('configMap')['record']}"></a>

第二步,登录后台管理系统,打开系统配置-基础配置,修改版权信息网站备案号的内容格式,如:

1
2
将 Copyright©2020. Design by MoonlightL 
改成 <span class="badge-subject">Copyright</span><span class="badge-value bg-blue">©2020. Design by MoonlightL </span>
1
2
将 浙ICP备00000000号
改成 <span class="badge-subject">浙ICP备</span><span class="badge-value bg-green">00000000号</span>

第三步,打开app.css文件,修改和添加如下代码:

修改:

1
2
3
4
5
.footer-copyright {
/*...*/
/*修改*/
padding: 30px 10px;
}

添加:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
.footer-copyright .badge-subject {
display: inline-block;
background-color: #4d4d4d;
padding: 4px 4px 4px 6px;
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
color: #fff;
}

.footer-copyright .badge-value {
display: inline-block;
padding: 4px 6px 4px 4px;
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
color: #fff;
}

.footer-copyright .bg-blue {
background-color: #007ec6
}

.footer-copyright .bg-orange {
background-color: #ffa500
}

.footer-copyright .bg-red {
background-color: #f00
}

.footer-copyright .bg-green {
background-color: #3bca6e
}

.footer-copyright .bg-purple {
background-color: #ab34e9
}

保存后,效果图如下:

3.6 复制代码

给代码块添加复制按钮。

第一步,打开common.html文件,在引入 js 文件处添加一行代码:

1
2
3
4
...
<!--添加-->
<script type='text/javascript' th:src="@{'https://cdn.jsdelivr.net/npm/clipboard@2.0.6/dist/clipboard.min.js'}"></script>
<script type='text/javascript' th:src="@{${prefix} + '/source/js/app.js'}"></script>

第二步,打开app.css文件,添加样式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
.highlight .copy-btn {
position: absolute;
top: 8px;
right: 10px;
display: inline-block;
text-align: center;
width: 44px;
height: 22px;
padding: 2px;
color: #e1e1e1;
border-radius: 8px;
cursor: pointer;
opacity: 0;
}

.highlight:hover .copy-btn {
opacity: 1;
}

第三步,打开app.js文件,修改postEvent函数,在分享事件下方添加复制代码事件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 打赏、分享 ...

// 复制代码
let $highlightArr = $(".highlight");
$highlightArr.each(function(index, domEle) {
let $highlight = $(domEle);
let $table = $highlight.find("table");
let copyBtn = $("<span class='copy-btn'>复制</span>");
$highlight.append(copyBtn);
let clipboard = new ClipboardJS(copyBtn.get(0), {
text: function(trigger) {
let html = $table.find("td.code pre").html();
html = html.replace(/<br>/g, "\r\n");
return $(html).text();
}
});

clipboard.on('success', function(e) {
layer.msg("复制成功");
e.clearSelection();
});
});

保存,最后看看效果图:

3.7 站点访问统计

使用第三方插件,统计页面总访问数和用户总访问数。

第一步,打开app.css文件:

修改:

1
2
3
4
5
6
7
.footer-copyright {
position: relative;
background-color: var(--content-color);
box-shadow: 0 0 5px var(--shadow-color);
color: var(--text-color);
padding: 2rem;
}

添加:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
.footer-copyright .power-by {
width: calc(50% - 1px);
height: 3rem;
line-height: 3rem;
display: inline-block;
}

@media screen and (max-width: 768px) {
.footer-copyright {
height: auto;
}

.footer-copyright .power-by {
width: 100%;
}
}

.footer-copyright .pv {
display: inline-block;
float: right;
width: calc(50% - 1px);
height: 3rem;
line-height: 3rem;
text-align: right;
}

@media screen and (max-width: 768px) {
.footer-copyright .pv {
width: 100%;
float: unset;
text-align: center;
}
}

第二步,打开common.html文件,修改id="footer-copyright"处的代码,将代码修改成如下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<footer class="footer-copyright" id="footer-copyright">
<div class="power-by">
<div th:utext="${#servletContext.getAttribute('configMap')['power_by']}"></div>
<div>
<a style="display: block" href="http://beian.miit.gov.cn/" target="_blank" th:utext="${#servletContext.getAttribute('configMap')['record']}"></a>
</div>
</div>
<div class="pv">
<i class="fa fa-eye"></i> <div id="busuanzi_container_site_pv"><span>总访问量:</span> <span id="busuanzi_value_site_pv">1</span>次</div>
<br>
<i class="fa fa-user-o"></i> <div id="busuanzi_container_site_uv"><span>总访问人数:</span> <span id="busuanzi_value_site_uv">1</span>人</div>
</div>
<div style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%)" class="hidden-xs">
<ul class="contract-info">
<li class="wechat" th:if="${#strings.isEmpty(#servletContext.getAttribute('configMap')['wx_account']) != true}">
<a th:title="${#servletContext.getAttribute('configMap')['wx_account']}" class="socialicon" href="javascript:void(0)" target="_blank"><i class="fa fa-weixin fa-lg" aria-hidden="true"></i></a>
</li>
<li th:if="${#strings.isEmpty(#servletContext.getAttribute('configMap')['qq_account']) != true}">
<a th:title="${#servletContext.getAttribute('configMap')['qq_account']}" class="socialicon" href="javascript:void(0)" target="_blank"><i class="fa fa-qq fa-lg" aria-hidden="true"></i></a>
</li>
<li th:if="${#strings.isEmpty(#servletContext.getAttribute('configMap')['git_hub_account']) != true}">
<a title="github" class="socialicon" th:href="@{${#servletContext.getAttribute('configMap')['git_hub_account']}}" target="_blank"><i class="fa fa-github-alt fa-lg" aria-hidden="true"></i></a>
</li>
</ul>
</div>
</footer>

第三步,打开app.js文件,修改loadResource函数,添加一段代码:

1
2
3
4
5
6
7
const loadResource = function() {
let APlayer = APP.plugins.APlayer;
$('head').append('<link href="' + APlayer.css + '" rel="stylesheet" type="text/css" />');
$.getScript(APlayer.js);
// 添加
$.getScript("//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js");
};

效果图如下:

3.8 Twikoo 评论系统

Hexo Boot 本身自带评论系统,同时也支持邮件通知提醒功能。但总体上功能还是有些单薄,而Twikoo作为第三方插件,支持的功能较为丰富(反垃圾,即时通信,邮件通知等),主要还是评论数据无需博客系统维护,减轻了系统请求部分压力。

现在开始整合这个插件吧。

第一步,打开common.html文件,添加代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<div th:fragment="comment">
<div class="comment-panel">
<p><i class="fa fa-comments"></i> 评论</p>
<div id="tcomment"></div>
<script th:src="@{${baseLink} + '/source/js/twikoo.all.min.js'}"></script>
<script th:inline="javascript">
twikoo.init({
envId: [[${#servletContext.getAttribute('configMap')['twikoo_env_id']}]],
el: '#tcomment',
region: 'ap-shanghai',
// path: 'window.location.pathname', // 用于区分不同文章的自定义 js 路径,如果您的文章路径不是 location.pathname,需传此参数
})
</script>
</div>
</div>

第二步,因为只有detail.htmlabout.html有评论功能,因此需要修改这2个页面。

detail.html修改代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!-- 评论 -->

<!--修改-->
<div th:if="${#strings.isEmpty(#servletContext.getAttribute('configMap')['twikoo_env_id']) eq true}">
<div id="detail-comment" class="comment-container"></div>
<script type="text/javascript" th:inline="javascript">
window.postId = [[${post.id}]];
window.canComment = [[${post.comment}]]
</script>
</div>

<!--添加-->
<div th:if="${#strings.isEmpty(#servletContext.getAttribute('configMap')['twikoo_env_id']) eq false}">
<div th:replace="~{theme/default/common :: comment}"></div>
</div>

about.html修改代码如下:

1
2
3
4
5
6
7
8
9
10
<!-- 留言 -->

<!--修改-->
<div th:if="${#strings.isEmpty(#servletContext.getAttribute('configMap')['twikoo_env_id']) eq true}">
<div id="about-comment" class="comment-container"></div>
</div>
<!--添加-->
<div th:if="${#strings.isEmpty(#servletContext.getAttribute('configMap')['twikoo_env_id']) eq false}">
<div th:replace="~{theme/default/common :: comment}"></div>
</div>

第三步,打开app.js文件,修改:

postEvent函数:

1
2
将 let $detailComment = $("#detail-comment");
改成 let $detailComment = $(".blogger-info");

第四步,打开app.css,修改样式:

1
2
3
4
5
6
.comment-panel {
background-color: var(--content-color);
box-shadow: 0 0 5px var(--shadow-color);
padding: 3rem;
margin-bottom: 1.5rem;
}

最后一步,登录后台管理->系统配置->个性配置->Twikoo(评论系统),填写 id 即可(页面有获取 id 的文档链接)。

注意:id 为空时,系统使用默认评论系统,id 填写正确就会使用 Twikoo 评论系统

效果图如下:

Twikoo更多信息请查看:

  1. Twikoo 中文文档
  2. Twikoo 上手视频

3.9 美化通知框

在写作时,我们为了突出或需要重点标注部分内容,因而会用到警告框,如下图:

该样式是参考 Bootstrap V3 中文文档 中的警告框样式。

要实现上图中的效果只需修改app.css文件,添加如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
div.note {
padding: 15px;
margin-bottom: 20px;
border: 1px solid transparent;
border-radius: 4px;
font-family: "FontAwesome";
}

div.note:not(.no-icon) {
padding-left: 3rem;
}

div.note.note-success {
position: relative;
color: #3c763d;
background-color: #dff0d8;
border-color: #d6e9c6;
border-left: 3px solid #3c763d;
box-shadow: 0 1px 3px 1px #d6e9c6;
}

div.note.note-success:not(.no-icon)::before {
position: absolute;
content: "\f058";
top: 1.5rem;
left: 1rem;
width: 32px;
height: 32px;
}

div.note.note-info {
position: relative;
color: #31708f;
background-color: #d9edf7;
border-color: #bce8f1;
border-left: 3px solid #31708f;
box-shadow: 0 1px 3px 1px #bce8f1;
}

div.note.note-info:not(.no-icon)::before {
position: absolute;
content: "\f06c";
top: 1.5rem;
left: 1rem;
width: 32px;
height: 32px;
}

div.note.note-warning {
position: relative;
color: #8a6d3b;
background-color: #fcf8e3;
border-color: #faebcc;
border-left: 3px solid #8a6d3b;
box-shadow: 0 1px 3px 1px #faebcc;
}

div.note.note-warning:not(.no-icon)::before {
position: absolute;
content: "\f06a";
top: 1.5rem;
left: 1rem;
width: 32px;
height: 32px;
}

div.note.note-danger {
position: relative;
color: #a94442;
background-color: #f2dede;
border-color: #ebccd1;
border-left: 3px solid #a94442;
box-shadow: 0 1px 3px 1px #ebccd1;
}

div.note.note-danger:not(.no-icon)::before {
position: absolute;
content: "\f057";
top: 1.5rem;
left: 1rem;
width: 32px;
height: 32px;
}

当我们写文章需要用到警告框时,按照如下格式书写即可:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<div class="note note-success">这是带图标的 success </div>

<div class="note note-success no-icon">这是不带图标的 success </div>

<div class="note note-info">这是带图标的 info</div>

<div class="note note-info no-icon">这是不带图标的 info</div>

<div class="note note-warning">这是带图标的 warning</div>

<div class="note note-warning no-icon">这是不带图标的 warning</div>

<div class="note note-danger">这是带图标的 danger</div>

<div class="note note-danger no-icon">这是不带图标的 danger</div>

Markdown 语法支持混合html代码,从而可以实现上图中的样式效果。

四、结束语

默认主题美化步骤和实战大致这些,如果笔者想到更好的 UI 美化效果,会再次更新本篇内容。