[toc]

参考文章

装修类

butterfly官方文档
Harris’s Blog Butterfly主题美化魔改集锦
https://blog.csdn.net/AAbbccdd12345685/article/details/117871129

相关设置

腾讯云图床访问节点
https://prong-1316442664.cos-website.ap-nanjing.myqcloud.com

报错bug

Error: Spawn failed

  • 删除.deplot_git文件夹
  • git bash 中 git config --global core.autocrlf false
  • 重新执行hexo clean hexo g hexo d

详细操作贴文

font matter引用格式

图片引用直接写链接,不要用md语法![]()

文章模板命名

发文章不可以用如下语法

1
$ hexo new [C语言]-分支结构

文章本地文件命名不能包含"|"竖线符号

解决:

  • 文章本地命名方式形如[C语言]-分支结构
  • git bash创建文章直接输标题,后续自己改为形如C语言 | 分支结构

豆瓣插件爬取不到信息(未解决)

操作类

发文章

来源

Hexo new 的分类

Hexo对生成文章有三种分类:

  1. post:也是默认的方式,一般指一篇博客。
  2. page:指生成一个页面,一般用来做标签和关于页
  3. draft:指草稿,我个人很少用。

生成方式是:hexo new [layout] <title>

比如: hexo new page tags ,即为生成一个名为tags的页面。

文档模板修改

当我们使用 hexo new [layout] <title> 生成文章的生成的文件都是有默认模板的。

比如hexo new post 模板测试

1
2
3
4
5
---
title: 模板测试
date: 2017-2-19 21:53:03
tags:
---
  • 实现修改模板功能

其实每次我们执行 hexo new [layout] <title> 时,Hexo都会去scaffolds文件夹中寻找[layout].md,并根据其内容建立文章。

那么我们直接修改对应的 .md 模板文件即可,或者自己添加一个 demo.md 文件,创建文件的时候执行hexo new demo <title> 即可。

图床上传代码

打开当前目录下的终端并输入
python -m markdown_img

丝滑三联

1
hexo clean && hexo g && hexo s
1
hexo clean && hexo g && hexo d

引用块

在文章中插入引言,可包含作者、来源和标题。

1
2
3
{% blockquote [author[, source]] [link] [source_link_title] %}
content
{% endblockquote %}

简单点说两种用法:

  • 引用名人名言
1
2
3
{% blockquote 鲁迅, 《记念刘和珍君》%}
真的猛士,敢于直面惨淡的人生,敢于正视淋漓的鲜血
{% endblockquote %}
  • 引用别人网站的文章或其他
1
2
3
{% blockquote B站 https://bilibili.com %}
B站可能会倒闭,但是绝对不会变质 http://bilibili.com
{% endblockquote %}

操作记录

title

2023/1/6 14:30 图片懒加载

图片懒加载

2023/1/6 14:30

安装模块
npm install hexo-lazyload-image --save
在主目录配置文件_config.yml增加配置

1
2
3
lazyload:
enable: true
loadingImg: /img/loading.gif

这个就是图片没加载出来的时候,出现一个动图转转转。

备用

懒加载报错

2023/1/6 15:20 打字机特效

打字机特效

2023/1/6 15:20

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# the subtitle on homepage (主頁subtitle)
subtitle:
enable: true
# Typewriter Effect (打字效果)
effect: true
# Effect Speed Options (打字效果速度參數)
startDelay: 300 # time before typing starts in milliseconds
typeSpeed: 150 # type speed in milliseconds
backSpeed: 50 # backspacing speed in milliseconds
# loop (循環打字)
loop: true
# source 調用第三方服務
# source: false 關閉調用
# source: 1 調用一言網的一句話(簡體) https://hitokoto.cn/
# source: 2 調用一句網(簡體) http://yijuzhan.com/
# source: 3 調用今日詩詞(簡體) https://www.jinrishici.com/
# subtitle 會先顯示 source , 再顯示 sub 的內容
source: false
# 如果關閉打字效果,subtitle 只會顯示 sub 的第一行文字
sub:

enable设成true

==注意==

1
2
3
4
# 如果有英文逗号' , ',使用转义字元 &#44;
# 如果有英文双引号' " ',使用转义字元 "
# 开头不允許转义字元,如需要,請把整个句子用双引号包住
# 如果关闭打字效果,subtitle只会显示sub的第一行文字

2023/1/6 16:20 顶部渐变条色加载条

顶部渐变条色加载条

  1. 新建[BlogRoot]\source\css\progress_bar.css文件,写入以下内容(或者你在[BlogRoot]\source\css\custom.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
.pace {
-webkit-pointer-events: none;
pointer-events: none;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
z-index: 2000;
position: fixed;
margin: auto;
top: 4px;
left: 0;
right: 0;
height: 8px;
border-radius: 8px;
width: 7rem;
background: #eaecf2;
border: 1px #e3e8f7;
overflow: hidden
}

.pace-inactive .pace-progress {
opacity: 0;
transition: .3s ease-in
}

.pace .pace-progress {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
-o-box-sizing: border-box;
box-sizing: border-box;
-webkit-transform: translate3d(0, 0, 0);
-moz-transform: translate3d(0, 0, 0);
-ms-transform: translate3d(0, 0, 0);
-o-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
max-width: 200px;
position: absolute;
z-index: 2000;
display: block;
top: 0;
right: 100%;
height: 100%;
width: 100%;
/* linear-gradient(to right, #3494e6, #ec6ead) */
background: linear-gradient(to right, #43cea2, #3866ca);
animation: gradient 2s ease infinite;
background-size: 200%
}

.pace.pace-inactive {
opacity: 0;
transition: .3s;
top: -8px
}
  1. 在主题配置文件_config.butterfly.yml的inject配置项加入刚刚的css样式和必须的js依赖:
1
2
3
4
5
inject:
head:
- <link rel="stylesheet" href="/css/progress_bar.css" media="defer" onload="this.media='all'">
bottom:
- <script async src="//npm.elemecdn.com/pace-js@1.2.4/pace.min.js"></script>

2023/1/6 16:09 文章置顶滚动栏

文章置顶滚动栏 (店长)

2023/1/6 16:09
https://blog.fomal.cc/posts/eec9786.html

  1. 安装插件,在博客根目录 [Blogroot] 下打开终端,运行以下指令
1
npm install hexo-butterfly-swiper --save
  1. 添加配置信息,以下为写法示例
    在站点配置文件_config.yml 或者主题配置文件_config.butterfly.yml 中添加
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# hexo-butterfly-swiper
# see https://akilar.top/posts/8e1264d1/
swiper:
enable: true # 开关
priority: 5 #过滤器优先权
enable_page: all # 应用页面
timemode: date #date/updated
layout: # 挂载容器类型
type: id
name: recent-posts
index: 0
default_descr: 再怎么看我也不知道怎么描述它的啦!
swiper_css: https://npm.elemecdn.com/hexo-butterfly-swiper/lib/swiper.min.css #swiper css依赖
swiper_js: https://npm.elemecdn.com/hexo-butterfly-swiper/lib/swiper.min.js #swiper js依赖
custom_css: https://npm.elemecdn.com/hexo-butterfly-swiper/lib/swiperstyle.css # 适配主题样式补丁
custom_js: https://npm.elemecdn.com/hexo-butterfly-swiper/lib/swiper_init.js # swiper初始化方法

使用方法:在文章的 front_matter 中添加 swiper_index 配置项即可。

1
2
3
4
5
6
7
8
---
title: 文章标题
date: 创建日期
updated: 更新日期
cover: 文章封面
description: 文章描述
swiper_index: 1 #置顶轮播图顺序,非负整数,数字越大越靠前
---

2023-1-6 16:41:00 猫猫滚动条

猫猫滚动条

2023-1-6 16:41:00
https://tzy1997.com/articles/hexo1613/

text

猫猫加载不出来是因为原作者图片图床网络问题,可以替换为自己的图床链接或者内置网页中

2023-1-6 20:55:00 GitHub Calendar (店长)

GitHub Calendar

2023-1-6 20:55:00
https://blog.fomal.cc/posts/eec9786.html

评论区找到可用的api抄录如下https://python-yln-github-calendar-api.vercel.app/api

  1. 安装插件,在博客根目录 [Blogroot] 下打开终端,运行以下指令:
1
2
npm install hexo-filter-gitcalendar --save
npm install hexo-filter-gitcalendar --save
  1. 添加配置信息,以下为写法示例

在站点配置文件_config.yml 或者主题配置文件如_config.butterfly.yml 中添加

原版为

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
# hexo-filter-gitcalendar
# see https://akilar.top/posts/1f9c68c9/
gitcalendar:
enable: true # 开关
priority: 5 #过滤器优先权
enable_page: / # 应用页面
# butterfly挂载容器
layout: # 挂载容器类型
type: id
name: recent-posts
index: 0
# volantis挂载容器
# layout:
# type: class
# name: l_main
# index: 0
# matery挂载容器
# layout:
# type: id
# name: indexCard
# index: 0
# mengd挂载容器
# layout:
# type: class
# name: content
# index: 0
user: Akilarlxh #git用户名
apiurl: 'https://gitcalendar.akilar.top'
minheight:
pc: 280px #桌面端最小高度
mibile: 0px #移动端最小高度
color: "['#e4dfd7', '#f9f4dc', '#f7e8aa', '#f7e8aa', '#f8df72', '#fcd217', '#fcc515', '#f28e16', '#fb8b05', '#d85916', '#f43e06']" #橘黄色调
# color: "['#ebedf0', '#fdcdec', '#fc9bd9', '#fa6ac5', '#f838b2', '#f5089f', '#c4067e', '#92055e', '#540336', '#48022f', '#30021f']" #浅紫色调
# color: "['#ebedf0', '#f0fff4', '#dcffe4', '#bef5cb', '#85e89d', '#34d058', '#28a745', '#22863a', '#176f2c', '#165c26', '#144620']" #翠绿色调
# color: "['#ebedf0', '#f1f8ff', '#dbedff', '#c8e1ff', '#79b8ff', '#2188ff', '#0366d6', '#005cc5', '#044289', '#032f62', '#05264c']" #天青色调
container: .recent-post-item(style='width:100%;height:auto;padding:10px;') #父元素容器,需要使用pug语法
gitcalendar_css: https://npm.elemecdn.com/hexo-filter-gitcalendar/lib/gitcalendar.css
gitcalendar_js: https://npm.elemecdn.com/hexo-filter-gitcalendar/lib/gitcalendar.js

我的配置如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# Ice Kano Plus_in
# Hexo Github Canlendar
# Author: Ice Kano
# Modify: Lete乐特
githubcalendar:
enable: true # true/false,是否开启插件
enable_page: / # 路由地址,如我的 /blog/是代表网站的root主页。/blog/about/代表的是关于页等等
user: prong879 # github 或者 gitee 用户名
layout:
type: id
name: recent-posts
index: 0
githubcalendar_html: '<div class="recent-post-item" style="width:100%;height:auto;padding:10px;"><div id="github_loading" style="width:10%;height:100%;margin:0 auto;display: block"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 50 50" style="enable-background:new 0 0 50 50" xml:space="preserve"><path fill="#d0d0d0" d="M25.251,6.461c-10.318,0-18.683,8.365-18.683,18.683h4.068c0-8.071,6.543-14.615,14.615-14.615V6.461z" transform="rotate(275.098 25 25)"><animateTransform attributeType="xml" attributeName="transform" type="rotate" from="0 25 25" to="360 25 25" dur="0.6s" repeatCount="indefinite"></animateTransform></path></svg></div><div id="github_container"></div></div>'
pc_minheight: 280px
mobile_minheight: 0px
color: "['#ebedf0', '#fdcdec', '#fc9bd9', '#fa6ac5', '#f838b2', '#f5089f', '#c4067e', '#92055e', '#540336', '#48022f', '#30021f']"
api: https://python-yln-github-calendar-api.vercel.app/api
# https://python-github-calendar-api.vercel.app/api
# https://python-gitee-calendar-api.vercel.app/api # 可以用 但是不知道为啥显示的是gitee的
# https://python-github-calendar-api-theta-ruby.vercel.app/api # 自建api也失效妈的
# https://python-github-calendar-api.vercel.app/api
# api: https://python-gitee-calendar-api.vercel.app/api
calendar_js: https://cdn.jsdelivr.net/gh/Zfour/hexo-github-calendar@1.21/hexo_githubcalendar.js
plus_style: ""
  1. 参数释义

2023/1/7 11:20 昼夜转换动画

昼夜转换动画

  1. 新建[Blogroot]\themes\butterfly\layout\includes\custom\sun_moon.pug,这部分其实实质上就是一个svg文件,通过js操作它的旋转显隐,淡入淡出实现动画效果。
  2. 新建[Blogroot]\themes\butterfly\source\css\_layout\sun_moon.styl
  3. 新建[Blogroot]\themes\butterfly\source\js\sun_moon.js,去除了冗余代码,去jquery。感觉源代码做过混淆加密,好多三元运算一层套一层,看昏了都。

2023-1-7 11:52 双栏布局首页

双栏布局首页

2023-1-7 12:52
https://akilar.top/posts/d6b69c49/

  1. 修改[Blogroot]\themes\butterfly\layout\includes\mixins\post-ui.pug,整个替换为下面的代码:
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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
mixin postUI(posts)
each article , index in page.posts.data
.recent-post-item
-
let link = article.link || article.path
let title = article.title || _p('no_title')
const position = theme.cover.position
let leftOrRight = position === 'both'
? index%2 == 0 ? 'left' : 'right'
: position === 'left' ? 'left' : 'right'
let post_cover = article.cover
let no_cover = article.cover === false || !theme.cover.index_enable ? 'no-cover' : ''
-
.recent-post-content(class=leftOrRight)
.recent-post-cover-shadow
.recent-post-cover
img.article-cover(src=url_for(post_cover) onerror=`this.onerror=null;this.src='`+ url_for(theme.error_img.post_page) + `'` alt=title)
.recent-post-info
a.article-title(href=url_for(link) title=title)
.article-title-link= title
.recent-post-meta
.article-meta-wrap
if (is_home() && (article.top || article.sticky > 0))
span.article-meta
i.fas.fa-thumbtack.sticky
span.sticky= _p('sticky')
span.article-meta-separator |
if (theme.post_meta.page.date_type)
span.post-meta-date
if (theme.post_meta.page.date_type === 'both')
i.far.fa-calendar-alt
span.article-meta-label=_p('post.created')
time.post-meta-date-created(datetime=date_xml(article.date) title=_p('post.created') + ' ' + full_date(article.date))=date(article.date, config.date_format)
span.article-meta-separator |
i.fas.fa-history
span.article-meta-label=_p('post.updated')
time.post-meta-date-updated(datetime=date_xml(article.updated) title=_p('post.updated') + ' ' + full_date(article.updated))=date(article.updated, config.date_format)
else
- let data_type_updated = theme.post_meta.page.date_type === 'updated'
- let date_type = data_type_updated ? 'updated' : 'date'
- let date_icon = data_type_updated ? 'fas fa-history' :'far fa-calendar-alt'
- let date_title = data_type_updated ? _p('post.updated') : _p('post.created')
i(class=date_icon)
span.article-meta-label=date_title
time(datetime=date_xml(article[date_type]) title=date_title + ' ' + full_date(article[date_type]))=date(article[date_type], config.date_format)
if (theme.post_meta.page.categories && article.categories.data.length > 0)
span.article-meta
span.article-meta-separator |
i.fas.fa-inbox
each item, index in article.categories.data
a(href=url_for(item.path)).article-meta__categories #[=item.name]
if (index < article.categories.data.length - 1)
i.fas.fa-angle-right.article-meta-link
if (theme.post_meta.page.tags && article.tags.data.length > 0)
span.article-meta.tags
span.article-meta-separator |
i.fas.fa-tag
each item, index in article.tags.data
a(href=url_for(item.path)).article-meta__tags #[=item.name]
if (index < article.tags.data.length - 1)
span.article-meta-link #[='•']

mixin countBlockInIndex
- needLoadCountJs = true
span.article-meta
span.article-meta-separator |
i.fas.fa-comments
if block
block
span.article-meta-label= ' ' + _p('card_post_count')

if theme.comments.card_post_count
case theme.comments.use[0]
when 'Disqus'
+countBlockInIndex
a(href=full_url_for(link) + '#disqus_thread')
i.fa-solid.fa-spinner.fa-spin
when 'Disqusjs'
+countBlockInIndex
a(href=full_url_for(link) + '#disqusjs')
span.disqus-comment-count(data-disqus-url=full_url_for(link))
i.fa-solid.fa-spinner.fa-spin
when 'Valine'
+countBlockInIndex
a(href=url_for(link) + '#post-comment')
span.valine-comment-count(data-xid=url_for(link))
i.fa-solid.fa-spinner.fa-spin
when 'Waline'
+countBlockInIndex
a(href=url_for(link) + '#post-comment')
span.waline-comment-count(id=url_for(link))
i.fa-solid.fa-spinner.fa-spin
when 'Twikoo'
+countBlockInIndex
a.twikoo-count(href=url_for(link) + '#post-comment')
i.fa-solid.fa-spinner.fa-spin
when 'Facebook Comments'
+countBlockInIndex
a(href=url_for(link) + '#post-comment')
span.fb-comments-count(data-href=urlNoIndex(article.permalink))
when 'Remark42'
+countBlockInIndex
a(href=url_for(link) + '#post-comment')
span.remark42__counter(data-url=urlNoIndex(article.permalink))
i.fa-solid.fa-spinner.fa-spin
when 'Artalk'
+countBlockInIndex
a(href=url_for(link) + '#post-comment')
span.artalk-count(data-page-key=url_for(link))
i.fa-solid.fa-spinner.fa-spin
a.article-content(href=url_for(link) title=title)
//- Display the article introduction on homepage
case theme.index_post_content.method
when false
- break
when 1
.article-content-text!= article.description
when 2
if article.description
.article-content-text!= article.description
else
- const content = strip_html(article.content)
- let expert = content.substring(0, theme.index_post_content.length)
- content.length > theme.index_post_content.length ? expert += ' ...' : ''
.article-content-text!= expert
default
- const content = strip_html(article.content)
- let expert = content.substring(0, theme.index_post_content.length)
- content.length > theme.index_post_content.length ? expert += ' ...' : ''
.article-content-text!= expert
.recent-post-arrow

if theme.ad && theme.ad.index
if (index + 1) % 3 == 0
.recent-post-item.ads-wrap!=theme.ad.index

原本代码备份post-ui.pug

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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
mixin postUI(posts)
each article , index in page.posts.data
.recent-post-item
-
let link = article.link || article.path
let title = article.title || _p('no_title')
const position = theme.cover.position
let leftOrRight = position === 'both'
? index%2 == 0 ? 'left' : 'right'
: position === 'left' ? 'left' : 'right'
let post_cover = article.cover
let no_cover = article.cover === false || !theme.cover.index_enable ? 'no-cover' : ''
-
if post_cover && theme.cover.index_enable
.post_cover(class=leftOrRight)
a(href=url_for(link) title=title)
img.post_bg(src=url_for(post_cover) onerror=`this.onerror=null;this.src='`+ url_for(theme.error_img.post_page) + `'` alt=title)
.recent-post-info(class=no_cover)
a.article-title(href=url_for(link) title=title)= title
.article-meta-wrap
if (is_home() && (article.top || article.sticky > 0))
span.article-meta
i.fas.fa-thumbtack.sticky
span.sticky= _p('sticky')
span.article-meta-separator |
if (theme.post_meta.page.date_type)
span.post-meta-date
if (theme.post_meta.page.date_type === 'both')
i.far.fa-calendar-alt
span.article-meta-label=_p('post.created')
time.post-meta-date-created(datetime=date_xml(article.date) title=_p('post.created') + ' ' + full_date(article.date))=date(article.date, config.date_format)
span.article-meta-separator |
i.fas.fa-history
span.article-meta-label=_p('post.updated')
time.post-meta-date-updated(datetime=date_xml(article.updated) title=_p('post.updated') + ' ' + full_date(article.updated))=date(article.updated, config.date_format)
else
- let data_type_updated = theme.post_meta.page.date_type === 'updated'
- let date_type = data_type_updated ? 'updated' : 'date'
- let date_icon = data_type_updated ? 'fas fa-history' :'far fa-calendar-alt'
- let date_title = data_type_updated ? _p('post.updated') : _p('post.created')
i(class=date_icon)
span.article-meta-label=date_title
time(datetime=date_xml(article[date_type]) title=date_title + ' ' + full_date(article[date_type]))=date(article[date_type], config.date_format)
if (theme.post_meta.page.categories && article.categories.data.length > 0)
span.article-meta
span.article-meta-separator |
i.fas.fa-inbox
each item, index in article.categories.data
a(href=url_for(item.path)).article-meta__categories #[=item.name]
if (index < article.categories.data.length - 1)
i.fas.fa-angle-right.article-meta-link
if (theme.post_meta.page.tags && article.tags.data.length > 0)
span.article-meta.tags
span.article-meta-separator |
i.fas.fa-tag
each item, index in article.tags.data
a(href=url_for(item.path)).article-meta__tags #[=item.name]
if (index < article.tags.data.length - 1)
span.article-meta-link #[='•']

mixin countBlockInIndex
- needLoadCountJs = true
span.article-meta
span.article-meta-separator |
i.fas.fa-comments
if block
block
span.article-meta-label= ' ' + _p('card_post_count')

if theme.comments.card_post_count
case theme.comments.use[0]
when 'Disqus'
+countBlockInIndex
a(href=full_url_for(link) + '#disqus_thread')
i.fa-solid.fa-spinner.fa-spin
when 'Disqusjs'
+countBlockInIndex
a(href=full_url_for(link) + '#disqusjs')
span.disqus-comment-count(data-disqus-url=full_url_for(link))
i.fa-solid.fa-spinner.fa-spin
when 'Valine'
+countBlockInIndex
a(href=url_for(link) + '#post-comment')
span.valine-comment-count(data-xid=url_for(link))
i.fa-solid.fa-spinner.fa-spin
when 'Waline'
+countBlockInIndex
a(href=url_for(link) + '#post-comment')
span.waline-comment-count(id=url_for(link))
i.fa-solid.fa-spinner.fa-spin
when 'Twikoo'
+countBlockInIndex
a.twikoo-count(href=url_for(link) + '#post-comment')
i.fa-solid.fa-spinner.fa-spin
when 'Facebook Comments'
+countBlockInIndex
a(href=url_for(link) + '#post-comment')
span.fb-comments-count(data-href=urlNoIndex(article.permalink))
when 'Remark42'
+countBlockInIndex
a(href=url_for(link) + '#post-comment')
span.remark42__counter(data-url=urlNoIndex(article.permalink))
i.fa-solid.fa-spinner.fa-spin
when 'Artalk'
+countBlockInIndex
a(href=url_for(link) + '#post-comment')
span.artalk-count(data-page-key=url_for(link))
i.fa-solid.fa-spinner.fa-spin

//- Display the article introduction on homepage
case theme.index_post_content.method
when false
- break
when 1
.content!= article.description
when 2
if article.description
.content!= article.description
else
- const content = strip_html(article.content)
- let expert = content.substring(0, theme.index_post_content.length)
- content.length > theme.index_post_content.length ? expert += ' ...' : ''
.content!= expert
default
- const content = strip_html(article.content)
- let expert = content.substring(0, theme.index_post_content.length)
- content.length > theme.index_post_content.length ? expert += ' ...' : ''
.content!= expert

if theme.ad && theme.ad.index
if (index + 1) % 3 == 0
.recent-post-item.ads-wrap!=theme.ad.index
  1. 样式方案提供两种:
  • 样式一:电脑端宽屏采用滑动卡片,平板宽度采用双栏布局,手机宽度采用单栏卡片。
  • 样式二:移除滑动卡片,按屏幕宽度依次应用三栏、双栏、单栏。

读者可以根据自己的喜好挑选。

新建目录[Blogroot]\themes\butterfly\source\css\_index_card_style\,并在下面新建对应的文件。注意看牢短横杠哦,路径新建错误导致的问题本店概不负责。

  • 样式一

新建[Blogroot]\themes\butterfly\source\css\_index_card_style\slidecard.styl,填入以下内容。

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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
//default color:
:root
--recent-post-bgcolor: rgba(255, 255, 255, 0.9) //默认背景
--article-content-bgcolor: #49b1f5 //描述版块背景
--recent-post-arrow: #ffffff //箭头配色
--recent-post-cover-shadow: #ffffff //封面遮罩层配色,建议和默认值的颜色相对应。
--recent-post-transition: all 0.5s cubic-bezier(0.59, 0.01, 0.48, 1.17) //动画效果。不了解的不要改动
[data-theme="dark"]
--recent-post-bgcolor: rgba(35,35,35,0.5)
--article-content-bgcolor: #99999a
--recent-post-arrow: #37e2dd
--recent-post-cover-shadow: #232323
// 默认的首页卡片容器布局
.recent-posts
padding 0 15px 0 15px
height fit-content
.recent-post-item
margin-bottom 15px
width 100%
background var(--recent-post-bgcolor)
overflow hidden
border-radius 15px
.recent-post-content
display flex
background var(--recent-post-bgcolor)
position relative
.recent-post-cover
display flex
background transparent
.recent-post-info
display flex
background transparent
flex-direction column
justify-content center
align-items center
.article-title
height 50%
display: flex
text-align: center
align-items: center
justify-content: flex-end
flex-direction: column
.article-title-link
color: var(--text-highlight-color)
transition: all .2s ease-in-out
display: -webkit-box;
-webkit-box-orient: vertical;
overflow: hidden;
&:hover
color: $text-hover
.recent-post-meta
height 50%
display: flex
text-align: center
align-items: center
justify-content: flex-start
flex-direction: column
.article-meta-wrap
color #969797
display: -webkit-box;
-webkit-box-orient: vertical;
overflow: hidden;
a
color: var(--text-highlight-color)
transition: all .2s ease-in-out
color #969797
&:hover
color: $text-hover
.article-content
display flex
text-align: center
flex-direction row
align-items center
justify-content center
.article-content-text
display -webkit-box
-webkit-box-orient vertical
text-overflow: ellipsis
overflow hidden
color #fff
text-shadow 1px 2px 3px #000
&::before
content "❝"
font-size 20px
&::after
content "❞"
font-size 20px
&.ads-wrap
display: block !important
height: auto !important
// PC端滑动卡片样式
@media screen and (min-width:1069px)
.recent-posts
padding 0 15px 0 15px
.recent-post-item
.recent-post-content
position relative
height 200px
width 100%
transition var(--recent-post-transition)
&:hover
.recent-post-cover-shadow
width 10.1%
transition var(--recent-post-transition)
.recent-post-cover
width 10%
transition var(--recent-post-transition)
.article-content
width calc(30% + 80px)
transition var(--recent-post-transition)
.article-content-text
opacity 1
.recent-post-arrow
transition var(--recent-post-transition)
.recent-post-cover-shadow
z-index: 1
transition var(--recent-post-transition)
position: absolute
height 200px
width 40%
.recent-post-cover
height 200px
width 40%
transition var(--recent-post-transition)
img
height 100%
width 100%
object-fit cover

.recent-post-info
height 200px
width calc(60% - 80px)
.article-title
margin: 0px 40px
font-size 24px
.article-title-link
-webkit-line-clamp: 2;
.recent-post-meta
margin: 0px 20px
.article-meta-wrap
font-size 12px
-webkit-line-clamp: 3;
.article-content
height 200px
width 90px
background var(--article-content-bgcolor)
transition var(--recent-post-transition)
.article-content-text
-webkit-line-clamp 4
transition: var(--recent-post-transition)
opacity 0
.recent-post-arrow
transition var(--recent-post-transition)
display block
position absolute
height 20px
width 8px
background var(--recent-post-arrow)
&.both,
&.right
.recent-post-cover-shadow
left 0
background linear-gradient(to left, var(--recent-post-cover-shadow), transparent)
.recent-post-cover
order: 1
.recent-post-info
order: 2
.article-content
order: 3
clip-path polygon(0 50%, 80px 0, 100% 0, 100% 100%, 80px 100%)
.article-content-text
margin 20px 40px 20px 80px
.recent-post-arrow
order: 4
left calc(100% - 80px)
top calc(50% - 10px)
clip-path polygon(0 10px, 8px 0, 8px 20px)
&:hover
.recent-post-arrow
left calc(100% - 40px)
&.left
.recent-post-cover-shadow
right 0
background linear-gradient(to right, var(--recent-post-cover-shadow), transparent)
.recent-post-cover
order: 4
.recent-post-info
order: 3
.article-content
order: 2
clip-path polygon(100% 50%,calc(100% - 80px) 100%,0 100%,0 0,calc(100% - 80px) 0)
.article-content-text
margin 20px 80px 20px 40px
.recent-post-arrow
order: 1
left 72px
top calc(50% - 10px)
clip-path polygon(0 0, 8px 10px, 0 20px)
&:hover
.recent-post-arrow
left 32px
// 双栏布局卡片自适应适配
@media screen and (min-width:572px) and (max-width:1068px)
.recent-posts
padding 0 15px 0 15px
display flex
flex-direction row
flex-wrap wrap
.recent-post-item
border-radius 15px
overflow hidden
width 47%
margin 0px 3% 20px 0px
nav#pagination
width: 100%
// 手机端单栏布局自适应适配
@media screen and (max-width:572px)
.recent-posts
padding 0 15px 0 15px
.recent-post-item
border-radius 15px
overflow hidden

// 手机端及双栏卡片样式
@media screen and (max-width:1068px)
.recent-posts
.recent-post-item
.recent-post-content
flex-direction column
flex-wrap nowrap
align-items center
max-height 350px
height: auto
width 100%
.recent-post-cover
width 100%
height 200px
clip-path polygon(0 130px,0 0,100% 0,100% 130px,50% 100%)
img
height 200px
width 100%
object-fit cover
.recent-post-info
height 150px
width 100%
padding 0px 25px 5px 25px
.article-title
margin: 0px 40px
font-size 18px
.article-title-link
-webkit-line-clamp: 2;
.recent-post-meta
margin: 0px 20px
.article-meta-wrap
font-size 12px
-webkit-line-clamp: 3;
.article-content
position absolute
height 200px
width 100%
background rgba(25,25,25,0.5)
clip-path polygon(0 130px,0 0,100% 0,100% 130px,50% 100%)
.article-content-text
-webkit-line-clamp 3
font-size 16px
margin 0px 25px 30px 25px
.recent-post-arrow
display block
background var(--article-content-bgcolor)
position absolute
height 10px
width 20px
clip-path polygon(0 0,100% 0,50% 100%)
top 20px
  • 样式二
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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
//default color:
:root
--recent-post-bgcolor: rgba(200, 200, 200, 0.5) //默认背景
--article-content-bgcolor: #49b1f5 //描述版块背景
--recent-post-arrow: #ffffff //箭头配色
--recent-post-cover-shadow: #ffffff //封面遮罩层配色,建议和默认值的颜色相对应。
--recent-post-transition: all 0.5s cubic-bezier(0.59, 0.01, 0.48, 1.17) //动画效果。不了解的不要改动
[data-theme="dark"]
--recent-post-bgcolor: rgba(35,35,35,0.5)
--article-content-bgcolor: #99999a
--recent-post-arrow: #37e2dd
--recent-post-cover-shadow: #232323
// 默认的首页卡片容器布局
.recent-posts
padding 0 15px 0 15px
height fit-content
.recent-post-item
margin-bottom 15px
background var(--recent-post-bgcolor)
overflow hidden
border-radius 15px
.recent-post-content
display flex
background var(--recent-post-bgcolor)
position relative
.recent-post-cover
display flex
background transparent
.recent-post-info
display flex
background transparent
flex-direction column
justify-content center
align-items center
.article-title
height 50%
display: flex
text-align: center
align-items: center
justify-content: flex-end
flex-direction: column
.article-title-link
color: var(--text-highlight-color)
transition: all .2s ease-in-out
display: -webkit-box;
-webkit-box-orient: vertical;
overflow: hidden;
&:hover
color: $text-hover
.recent-post-meta
height 50%
display: flex
text-align: center
align-items: center
justify-content: flex-start
flex-direction: column
.article-meta-wrap
color #969797
display: -webkit-box;
-webkit-box-orient: vertical;
overflow: hidden;
a
color: var(--text-highlight-color)
transition: all .2s ease-in-out
color #969797
&:hover
color: $text-hover
.article-content
display flex
text-align: center
flex-direction row
align-items center
justify-content center
.article-content-text
display -webkit-box
-webkit-box-orient vertical
text-overflow: ellipsis
overflow hidden
color #fff
text-shadow 1px 2px 3px #000
&.ads-wrap
display: block !important
height: auto !important
nav#pagination
width: 100%
// 卡片单元布局样式
.recent-posts
padding 0 15px 0 15px
display flex
flex-direction row
flex-wrap wrap
.recent-post-item
border-radius 15px
overflow hidden
.recent-post-content
flex-direction column
flex-wrap nowrap
align-items center
max-height 350px
height: auto
width 100%
.recent-post-cover
width 100%
height 200px
clip-path polygon(0 130px,0 0,100% 0,100% 130px,50% 100%)
img
height 200px
width 100%
object-fit cover
.recent-post-info
height 150px
width 100%
padding 0px 25px 5px 25px
.article-title
margin: 0px 40px
font-size 18px
.article-title-link
-webkit-line-clamp: 2;
.recent-post-meta
margin: 0px 20px
.article-meta-wrap
font-size 12px
-webkit-line-clamp: 3;
.article-content
position absolute
height 200px
width 100%
background rgba(25,25,25,0.5)
clip-path polygon(0 130px,0 0,100% 0,100% 130px,50% 100%)
.article-content-text
-webkit-line-clamp 3
font-size 16px
margin 0px 25px 30px 25px
&::before
content "❝"
font-size 20px
&::after
content "❞"
font-size 20px
.recent-post-arrow
display block
background var(--article-content-bgcolor)
position absolute
height 10px
width 20px
clip-path polygon(0 0,100% 0,50% 100%)
top 20px
// 三栏布局滑动卡片样式
@media screen and (min-width:1069px)
.recent-posts
.recent-post-item
width 32.3%
margin 0px 1% 20px 0px
.recent-post-content
.recent-post-info
.article-title
margin: 0px 5px
.article-title-link
-webkit-line-clamp: 1;
.recent-post-meta
margin: 0px 5px
.article-meta-wrap
-webkit-line-clamp: 2;
// 双栏布局卡片自适应适配
@media screen and (min-width:572px) and (max-width:1068px)
.recent-posts
.recent-post-item
width 47%
margin 0px 3% 20px 0px
// 单栏布局卡片自适应适配
@media screen and (max-width:572px)
.recent-posts
.recent-post-item
width 100%
  1. 修改[Blogroot]\themes\butterfly\source\css\_page\homepage.styl,将整文件内容替换为以下代码:
1
2
3
4
if hexo-config('index_card_style') == 'slidecard'
@import './_index_card_style/slidecard'
else if hexo-config('index_card_style') == 'multicard'
@import './_index_card_style/multicard'

原代码

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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#recent-posts
& > .recent-post-item:not(:first-child)
margin-top: 20px

& > .recent-post-item
@extend .cardHover
display: flex
flex-direction: row
align-items: center
overflow: hidden
height: 18em

+maxWidth768()
flex-direction: column
height: auto

&:hover
img.post_bg
transform: scale(1.1)

&.ads-wrap
display: block !important
height: auto !important

.post_cover
overflow: hidden
width: 44%
height: 100%

+maxWidth768()
width: 100%
height: 230px

img.post_bg
@extend .imgHover

&.right
order: 1

+maxWidth768()
order: 0

& >.recent-post-info
padding: 0 40px
width: 57%

+maxWidth768()
padding: 20px 20px 30px
width: 100%

&.no-cover
width: 100%

+maxWidth768()
padding: 30px 20px

& > .article-title
@extend .limit-more-line
color: var(--text-highlight-color)
font-size: 1.72em
line-height: 1.4
transition: all .2s ease-in-out
-webkit-line-clamp: 2

+maxWidth768()
font-size: 1.43em

&:hover
color: $text-hover

& > .article-meta-wrap
margin: 6px 0
color: $theme-meta-color
font-size: 90%

& > .post-meta-date
cursor: default

.sticky
color: $sticky-color

i
margin: 0 4px 0 0

.fa-spinner
margin: 0

.article-meta-label
if hexo-config('post_meta.page.label')
padding-right: 4px
else
display: none

.article-meta-separator
margin: 0 6px

.article-meta-link
margin: 0 4px

if hexo-config('post_meta.page.date_format') == 'relative'
time
display: none

a
color: $theme-meta-color

&:hover
color: $text-hover
text-decoration: underline

& > .content
@extend .limit-more-line
-webkit-line-clamp: 2
  1. 然后在主题配置文件[Blogroot]\_config.butterfly.yml里新增配置项,这样我们就可以通过配置项自由切换使用哪款了:
1
2
3
# 主页卡片样式
# Docs: https://akilar.top/posts/d6b69c49/
index_card_style: slidecard # slidecard | multicard
  1. 考虑到不管是样式一还是样式二都存在一个布局突变的情况。为了不至于让首页的文章出现空缺,建议将首页生成的文章数量控制为1,2,3的公倍数。修改站点配置文件[Blogroot]\_config.yml。找到以下配置项进行调整,注意这是站点配置文件本就有的配置项,不是新增配置项。建议是调整为12篇。如果你的侧边栏魔改内容特别多,那么建议改成18、24、30。务必确保文章卡片栏比侧栏完全展开要长,这样展示效果最好。
1
2
3
4
5
6
7
8
# Display the article introduction on homepage
# 1: description
# 2: both (if the description exists, it will show description, or show the auto_excerpt)
# 3: auto_excerpt (default)
# false: do not show the article introduction
index_post_content:
method: 2
length: 500 # if you set method to 2 or 3, the length need to config

2023/1/7 22:52:00 豆瓣插件

豆瓣插件

2023/1/7 22:52:00
https://www.npmjs.com/package/hexo-butterfly-douban

偶尔可能网络原因用魔法也爬取不到数据,解决方案是耐心等待

2023-1-8 00:05:00 天气插件

天气插件,有bug暂时放弃

https://blog.csdn.net/weixin_50915462/article/details/120050294
2023-1-8 00:05:00

注册和风天气并设置简约插件

生成代码如下,在Hexo\themes\butterfly\source\js\路径下新建weather.js文件,将上面所复制的代码复制进去:

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
<div id="he-plugin-simple"></div>
<script>
WIDGET = {
"CONFIG": {
"modules": "01234",
"background": "1",
"tmpColor": "FFFFFF",
"tmpSize": "16",
"cityColor": "FFFFFF",
"citySize": "16",
"aqiColor": "FFFFFF",
"aqiSize": "16",
"weatherIconSize": "24",
"alertIconSize": "18",
"padding": "10px 10px 10px 10px",
"shadow": "0",
"language": "auto",
"fixed": "true",
"vertical": "top",
"horizontal": "left",
"left": "10",
"top": "10",
"key": "0350911c0d7c406da21ea9ee15ca74d9"
}
}
</script>
<script src="https://widget.qweather.net/simple/static/js/he-simple-common.js?v=2.0"></script>

在主题配置文件_config.butterfly.yml中找到injectbottom处引入以下两个js文件:

2023-1-8 16:47:00 配置个人域名

配置个人域名

2023-1-8 16:47:00
在腾讯云上购买域名收费标准

年数 首购 续费
前三年

2023-1-8 15:20 配置多个仓库

配置多个仓库

https://www.voidking.com/dev-hexo-multi-git/
2023-1-8 15:20

尝试部署到coding, 发现coding的pages功能无法使用

因此使用Gitee

_config.ymldeployment中,以以下语法配置

1
2
3
4
5
6
7
8
# github
deploy:
- type: git
repo: https://voidking.com/voidking/voidking.github.io.git
branch: master
- type: git
repo: https://voidking.com/voidking/voidking.git
branch: master

在gitee中用类似github的方式配置ssh密钥

gitee要网页审查,技术文档有时候都违规,遂放弃

2023-1-8 19:00:00 安装历史上的今天插件

安装历史上的今天插件

2023-1-8 19:00:00
https://zfe.space/post/hexo-history-calendar.html

安装插件

1
2
3
4
5
6
npm i hexo-history-calendar --save

# 或者

cnpm i hexo-history-calendar --save

新增网站根目录_config 配置项 (不是主题的)

1
2
3
4
5
6
7
8
9
history_calendar:
priority: 4
enable: true
enable_page: all
layout:
type: class
name: sticky_layout
index: 0
temple_html: '<div class="card-widget card-history"><div class="card-content"><div class="item-headline"><i class="fas fa-clock fa-spin"></i><span>那年今日</span></div><div id="history-baidu" style="height: 100px;overflow: hidden"><div class="history_swiper-container" id="history-container" style="width: 100%;height: 100%"><div class="swiper-wrapper" id="history_container_wrapper" style="height:20px"></div></div></div></div>'

2023-1-8 20:00:00 时间轴加上生肖图标

时间轴加上生肖图标

https://akilar.top/posts/22257072/

在[Blogroot]\themes\butterfly\scripts\目录下新建year.js,并在[Blogroot]\themes\butterfly\scripts\year.js中输入以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
hexo.extend.helper.register("getAnimalIcon", function (year) {
var index = parseInt(year) % 12;
var icon = {
0: "icon-monkey",
1: "icon-rooster",
2: "icon-dog",
3: "icon-boar",
4: "icon-rat",
5: "icon-ox",
6: "icon-tiger",
7: "icon-rabbit",
8: "icon-dragon",
9: "icon-snake",
10: "icon-horse",
11: "icon-goat",
};
return icon[index];
});

修改[Blogroot]\themes\butterfly\layout\includes\mixins\article-sort.pug,第 7 行开始,注意缩进。

1
2
3
4
5
6
7
8
9
10
11
12
    - let title = article.title || _p('no_title')
+ - let iconAnimal = '#'+ getAnimalIcon(tempYear)
if tempYear !== year
- year = tempYear
- .article-sort-item.year= year
+ .article-sort-item.year
+ span= year
+ svg.icon(aria-hidden='true')
+ use(xlink:href=iconAnimal)
.article-sort-item(class=no_cover)
if article.cover && theme.cover.archives_enable

2023-1-10 20:30:00 添加访客地球插件

添加访客地球插件

https://www.revolvermaps.com/?target=setupgl
2023-1-10 20:30:00
插入在关于页面,设置大小自适应

1
2
3
4
<div style="position: relative; padding-top: 100%;">
<iframe style="background: transparent !important; position: absolute; left: 0px; top: 0px;" scrolling="no" frameborder="0" allowtransparency="true" width="100%" height="100%" src="//rf.revolvermaps.com/w/6/a/c2.php?i=5qhbea96mmt&amp;m=7&amp;c=ff0000&amp;cr1=ffffff&amp;f=arial&amp;l=0">
</iframe>
</div>

新代码

1
<script type="text/javascript" src="//rf.revolvermaps.com/0/0/6.js?i=5w15y78qsxh&amp;m=0&amp;c=ff0000&amp;cr1=ff0000&amp;f=arial&amp;l=1&amp;s=340" async="async"></script>

2023-1-11 00:24:00 添加博客文章统计图

添加博客文章统计图

https://blog.eurkon.com/post/1213ef82.html
2023-1-11 00:24

ECharts配置项文档
https://echarts.apache.org/zh/option.html#title

  1. 新建charts页面(其实也可以不建,放在想放的地方就行)
1
hexo new page charts
  1. 引入 ECharts.js

全局引用
以 butterfly 主题为例,可以在 [Blogroot]\_config.butterfly.ymlinject 配置项中引入 echart.js 文件。

1
2
3
inject:
head:
- <script src="https://npm.elemecdn.com/echarts@4.9.0/dist/echarts.min.js"></script>

页面引入
可以在 index.md 添加以下内容:

1
<script src="https://npm.elemecdn.com/echarts@4.9.0/dist/echarts.min.js"></script>
  1. 文章统计代码
    以 butterfly 主题为例,可以在 [Blogroot]\themes\butterfly\scripts\helpers\ 目录下新建 charts.js 文件,然后添加以下内容:
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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
const cheerio = require('cheerio')
const moment = require('moment')

hexo.extend.filter.register('after_render:html', function (locals) {
const $ = cheerio.load(locals)
const post = $('#posts-chart')
const tag = $('#tags-chart')
const category = $('#categories-chart')
const htmlEncode = false

if (post.length > 0 || tag.length > 0 || category.length > 0) {
if (post.length > 0 && $('#postsChart').length === 0) {
if (post.attr('data-encode') === 'true') htmlEncode = true
post.after(postsChart(post.attr('data-start')))
}
if (tag.length > 0 && $('#tagsChart').length === 0) {
if (tag.attr('data-encode') === 'true') htmlEncode = true
tag.after(tagsChart(tag.attr('data-length')))
}
if (category.length > 0 && $('#categoriesChart').length === 0) {
if (category.attr('data-encode') === 'true') htmlEncode = true
category.after(categoriesChart(category.attr('data-parent')))
}

if (htmlEncode) {
return $.root().html().replace(/&amp;#/g, '&#')
} else {
return $.root().html()
}
} else {
return locals
}
}, 15)

function postsChart (startMonth) {
const startDate = moment(startMonth || '2020-01')
const endDate = moment()

const monthMap = new Map()
const dayTime = 3600 * 24 * 1000
for (let time = startDate; time <= endDate; time += dayTime) {
const month = moment(time).format('YYYY-MM')
if (!monthMap.has(month)) {
monthMap.set(month, 0)
}
}
hexo.locals.get('posts').forEach(function (post) {
const month = post.date.format('YYYY-MM')
if (monthMap.has(month)) {
monthMap.set(month, monthMap.get(month) + 1)
}
})
const monthArr = JSON.stringify([...monthMap.keys()])
const monthValueArr = JSON.stringify([...monthMap.values()])

return `
<script id="postsChart">
var color = document.documentElement.getAttribute('data-theme') === 'light' ? '#4c4948' : 'rgba(255,255,255,0.7)'
var postsChart = echarts.init(document.getElementById('posts-chart'), 'light');
var postsOption = {
title: {
text: '文章发布统计图',
x: 'center',
textStyle: {
color: color
}
},
tooltip: {
trigger: 'axis'
},
xAxis: {
name: '日期',
type: 'category',
boundaryGap: false,
nameTextStyle: {
color: color
},
axisTick: {
show: false
},
axisLabel: {
show: true,
color: color
},
axisLine: {
show: true,
lineStyle: {
color: color
}
},
data: ${monthArr}
},
yAxis: {
name: '文章篇数',
type: 'value',
nameTextStyle: {
color: color
},
splitLine: {
show: false
},
axisTick: {
show: false
},
axisLabel: {
show: true,
color: color
},
axisLine: {
show: true,
lineStyle: {
color: color
}
}
},
series: [{
name: '文章篇数',
type: 'line',
smooth: true,
lineStyle: {
width: 0
},
showSymbol: false,
itemStyle: {
opacity: 1,
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: 'rgba(128, 255, 165)'
},
{
offset: 1,
color: 'rgba(1, 191, 236)'
}])
},
areaStyle: {
opacity: 1,
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: 'rgba(128, 255, 165)'
}, {
offset: 1,
color: 'rgba(1, 191, 236)'
}])
},
data: ${monthValueArr},
markLine: {
data: [{
name: '平均值',
type: 'average',
label: {
color: color
}
}]
}
}]
};
postsChart.setOption(postsOption);
window.addEventListener('resize', () => {
postsChart.resize();
});
postsChart.on('click', 'series', (event) => {
if (event.componentType === 'series') window.location.href = '/archives/' + event.name.replace('-', '/');
});
</script>`
}

function tagsChart (len) {
const tagArr = []
hexo.locals.get('tags').map(function (tag) {
tagArr.push({ name: tag.name, value: tag.length, path: tag.path })
})
tagArr.sort((a, b) => { return b.value - a.value })

const dataLength = Math.min(tagArr.length, len) || tagArr.length
const tagNameArr = []
for (let i = 0; i < dataLength; i++) {
tagNameArr.push(tagArr[i].name)
}
const tagNameArrJson = JSON.stringify(tagNameArr)
const tagArrJson = JSON.stringify(tagArr)

return `
<script id="tagsChart">
var color = document.documentElement.getAttribute('data-theme') === 'light' ? '#4c4948' : 'rgba(255,255,255,0.7)'
var tagsChart = echarts.init(document.getElementById('tags-chart'), 'light');
var tagsOption = {
title: {
text: 'Top ${dataLength} 标签统计图',
x: 'center',
textStyle: {
color: color
}
},
tooltip: {},
xAxis: {
name: '标签',
type: 'category',
nameTextStyle: {
color: color
},
axisTick: {
show: false
},
axisLabel: {
show: true,
color: color,
interval: 0
},
axisLine: {
show: true,
lineStyle: {
color: color
}
},
data: ${tagNameArrJson}
},
yAxis: {
name: '文章篇数',
type: 'value',
splitLine: {
show: false
},
nameTextStyle: {
color: color
},
axisTick: {
show: false
},
axisLabel: {
show: true,
color: color
},
axisLine: {
show: true,
lineStyle: {
color: color
}
}
},
series: [{
name: '文章篇数',
type: 'bar',
data: ${tagArrJson},
itemStyle: {
borderRadius: [5, 5, 0, 0],
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: 'rgba(128, 255, 165)'
},
{
offset: 1,
color: 'rgba(1, 191, 236)'
}])
},
emphasis: {
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: 'rgba(128, 255, 195)'
},
{
offset: 1,
color: 'rgba(1, 211, 255)'
}])
}
},
markLine: {
data: [{
name: '平均值',
type: 'average',
label: {
color: color
}
}]
}
}]
};
tagsChart.setOption(tagsOption);
window.addEventListener('resize', () => {
tagsChart.resize();
});
tagsChart.on('click', 'series', (event) => {
if(event.data.path) window.location.href = '/' + event.data.path;
});
</script>`
}

function categoriesChart (dataParent) {
const categoryArr = []
let categoryParentFlag = false
hexo.locals.get('categories').map(function (category) {
if (category.parent) categoryParentFlag = true
categoryArr.push({
name: category.name,
value: category.length,
path: category.path,
id: category._id,
parentId: category.parent || '0'
})
})
categoryParentFlag = categoryParentFlag && dataParent === 'true'
categoryArr.sort((a, b) => { return b.value - a.value })
function translateListToTree (data, parent) {
let tree = []
let temp
data.forEach((item, index) => {
if (data[index].parentId == parent) {
let obj = data[index];
temp = translateListToTree(data, data[index].id);
if (temp.length > 0) {
obj.children = temp
}
if (tree.indexOf())
tree.push(obj)
}
})
return tree
}
const categoryNameJson = JSON.stringify(categoryArr.map(function (category) { return category.name }))
const categoryArrJson = JSON.stringify(categoryArr)
const categoryArrParentJson = JSON.stringify(translateListToTree(categoryArr, '0'))

return `
<script id="categoriesChart">
var color = document.documentElement.getAttribute('data-theme') === 'light' ? '#4c4948' : 'rgba(255,255,255,0.7)'
var categoriesChart = echarts.init(document.getElementById('categories-chart'), 'light');
var categoryParentFlag = ${categoryParentFlag}
var categoriesOption = {
title: {
text: '文章分类统计图',
x: 'center',
textStyle: {
color: color
}
},
legend: {
top: 'bottom',
data: ${categoryNameJson},
textStyle: {
color: color
}
},
tooltip: {
trigger: 'item'
},
series: []
};
categoriesOption.series.push(
categoryParentFlag ?
{
nodeClick :false,
name: '文章篇数',
type: 'sunburst',
radius: ['15%', '90%'],
center: ['50%', '55%'],
sort: 'desc',
data: ${categoryArrParentJson},
itemStyle: {
borderColor: '#fff',
borderWidth: 2,
emphasis: {
focus: 'ancestor',
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(255, 255, 255, 0.5)'
}
}
}
:
{
name: '文章篇数',
type: 'pie',
radius: [30, 80],
roseType: 'area',
label: {
color: color,
formatter: '{b} : {c} ({d}%)'
},
data: ${categoryArrJson},
itemStyle: {
emphasis: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(255, 255, 255, 0.5)'
}
}
}
)
categoriesChart.setOption(categoriesOption);
window.addEventListener('resize', () => {
categoriesChart.resize();
});
categoriesChart.on('click', 'series', (event) => {
if(event.data.path) window.location.href = '/' + event.data.path;
});
</script>`
}

更多统计图的自定义属性可以查看 ECharts配置项文档 ,根据自行喜好对 ECharts 统计图进行修改。

  1. 使用统计图
    在上文新建的 [Blogroot]\source\charts\index.md 文件中添加以下内容:

当然也可以在其他页面引入文章统计图,如果出现图表显示不全的现象可以修改 div 的 height 属性。。

  • posts-chartdata-start="2021-01" 属性表示文章发布时间统计图仅显示 2021-01 及以后的文章数据。
  • tags-chartdata-length="10" 属性表示仅显示排名前 10 的标签。
  • categories-chartdata-parent="true" 属性表示 有子分类 时以旭日图显示分类,其他 无子分类设置为false不设置该属性设置为其他非true属性 情况都以饼状图显示分类。

可能遇到的问题

控制台报错 Uncaught ReferenceError: require is not defined

解决方案:

不能直接在页面引用 charts.js,是放在主题文件夹 [Blogroot]\themes\butterfly\scripts\helpers\ 里面,hexo g 的时候会在 div 后面追加 echarts 图的 js。页面不需要引入 charts.js。

控制台报错 Uncaught ReferenceError: echarts is not defined。

解决方案:

需要在统计图的前引入 echarts.js 文件,最好是在页面的头部引入。

控制台报错 Cannot find module ‘cheerio’。

解决方案:

安装 cheerio,控制台执行 npm i cheerio --save。

2023-1-11 14:24:00 添加追番统计

追番插件

安装

安装代码:

1
npm i hexo-bilibili-bangumi-anzhiyu

将下面的配置写入站点的配置文件 _config.yml 里(不是主题的配置文件).

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
# 追番设置
bangumi: # 追番设置
enable: true
source: bili
path:
vmid: 37924260
title: '追番列表'
quote: '我看到了我的爱恋 我飞到她的身边 我拿出给她的礼物 那是一小块凝固的时间'
show: 1
lazyload: true
loading:
showMyComment: false
pagination: false
metaColor:
color:
webp:
progress:
extraOrder:
proxy:
host: '代理host'
port: '代理端口'
extra_options:
key: value
cinema: # 追剧设置
enable: true
path:
vmid: 37924260
title: '追剧列表'
quote: '生命不息,追剧不止!'
show: 1
lazyload: true
loading:
metaColor:
color:
webp:
progress:
extraOrder:
extra_options:
key: value
  • enable*: 是否启用
  • source: 数据源,仅支持追番,追剧仅支持哔哩哔哩源。bili: 哔哩哔哩源, bgm: Bangumi源
  • proxy: 代理设置,仅在使用支持bgm源追番时生效。默认false
  • path: 页面路径,默认bangumis/index.html, cinemas/index.html
  • vmid*: 哔哩哔哩的 vmid(uid)如何获取?或Bangumi的用户id如何获取?
  • title: 该页面的标题
  • quote: 写在页面开头的一段话,支持 html 语法,可留空。
  • show: 初始显示页面:0: 想看, 1: 在看, 2: 看过,默认为1
  • lazyload: 是否启用图片懒加载,如果与主题的懒加载冲突请关闭,默认true
  • loading: 图片加载完成前的 loading 图片,需启用图片懒加载
  • metaColor: meta 部分(简介上方)字体颜色
  • color: 简介字体颜色
  • webp: 番剧封面使用webp格式(此格式在safari浏览器下不显示,但是图片大小可以缩小 100 倍左右,仅支持哔哩哔哩源), 默认true
  • progress: 获取番剧数据时是否显示进度条,默认true
  • extraOrder: 手动添加的番剧/追剧数据是否优先显示,1为优先,其它为不优先
  • showMyComment: 使用bgm源时显示自己的评价及评论,默认false
  • pagination: 分页优化,只将第一页的数据渲染到html文件中,其余数据将通过异步请求加载,避免番剧过多时html文件过大导致页面加载缓慢,建议番剧较多时使用,默认false
  • extra_options: 此配置会扩展到Hexopage变量中

使用方式

创建页面

1
hexo new page bangumis
1
hexo new page cinemas

在导航栏里设置

在 hexo generate 或 hexo deploy 之前使用

1
2
hexo bangumi -u
hexo cinema -u
1
$ hexo clean && hexo bangumi -u && hexo cinema -u && hexo g && hexo s

命令更新番剧数据!

删除数据命令

1
hexo bangumi -d

例如(代码)

1
hexo bangumi -u && hexo clean && hexo g -d

获取 uid

登录哔哩哔哩后前往https://space.bilibili.com/页面,网址最后的一串数字就是 uid

需要将追番列表设置为公开!

手动添加番剧追剧数据

因为某些番剧在哔哩哔哩上没有,但是又想在hexo中展示,怎么办呢?现在支持手动添加番剧数据了!

在 sources/_data/ 目录下新建文件,命名为 extra_bangumis.json(追番数据)或extra_cinemas.json(追剧数据) ,并添加以如下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
"watchedExtra": [
{
"title": "缘之空",
"type": "番剧",
"area": "日本",
"cover": "https://cdn.jsdelivr.net/gh/mmdjiji/bangumis@main/Yosuga-no-Sora/cover.jpg",
"totalCount": "全12话",
"id": 0,
"follow": "不可用",
"view": "不可用",
"danmaku": "不可用",
"coin": "不可用",
"score": "不可用",
"des": "远离都市的田园小镇,奥木染。春日野悠带着妹妹穹,来到了这座城镇。坐落在这里的是,儿时暑假经常造访的充满回忆的已故祖父的家。双亲因意外事故而丧生,变得无依无靠..."
}
]
}

title 是番剧的标题,cover 是封面图链接, des 是简介,上述字段均根据需要修改。

另外除了 watchedExtra 数组,还可以在后面添加新的数组,可用数组名如下:

可用数组名 含义
wantWatchExtra 想看
watchingExtra 在看
watchedExtra 看过
需要注意,在两个数组之间需要用 , 分隔。

2023-1-11 18:24:00 添加追字数统计

要为Butterfly配上字数统计特性, 你需要如下几个步骤:

  1. 打开 hexo 工作目录

npm install hexo-wordcount --save or yarn add hexo-wordcount

  1. 修改 主题配置文件:
1
2
3
4
5
wordcount:
enable: true
post_wordcount: true
min2read: true
total_wordcount: true

2023-1-24 14:24:00 修改版权样式

修改版权样式

https://www.imcharon.com/117/

原代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
if theme.post_copyright.enable && page.copyright !== false
- let author = page.copyright_author || config.author
- let authorHref = page.copyright_author_href || theme.post_copyright.author_href || config.url
- let url = page.copyright_url || page.permalink
- let info = page.copyright_info || _p('post.copyright.copyright_content', theme.post_copyright.license_url, theme.post_copyright.license, config.url, config.title)
.post-copyright
.post-copyright__author
span.post-copyright-meta= _p('post.copyright.author') + ": "
span.post-copyright-info
a(href=authorHref)=author
.post-copyright__type
span.post-copyright-meta= _p('post.copyright.link') + ": "
span.post-copyright-info
a(href=url_for(url))= theme.post_copyright.decode ? decodeURI(url) : url
.post-copyright__notice
span.post-copyright-meta= _p('post.copyright.copyright_notice') + ": "
span.post-copyright-info!= info

打开ROOT\themes\butterfly\layout\includes\post文件夹,将下列代码覆盖post-copyright.pug文件

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
if theme.post_copyright.enable && page.copyright !== false
- let author = page.copyright_author ? page.copyright_author : config.author
- let url = page.copyright_url ? page.copyright_url : page.permalink
.post-copyright
.post-copyright__title
span.post-copyright-info
h #[=page.title]
.post-copyright__type
span.post-copyright-info
a(href=url_for(url))= theme.post_copyright.decode ? decodeURI(url) : url
.post-copyright-m
.post-copyright-m-info
.post-copyright-a(style="display: inline-block;width: 120px")
h 作者
.post-copyright-cc-info
h=author
.post-copyright-c(style="display: inline-block;width: 120px")
h 发布于
.post-copyright-cc-info
h=date(page.date, config.date_format)
.post-copyright-u(style="display: inline-block;width: 120px")
h 更新于
.post-copyright-cc-info
h=date(page.updated, config.date_format)
.post-copyright-c(style="display: inline-block;width: 120px")
h 许可协议
.post-copyright-cc-info
a.icon(rel='noopener' target='_blank' title='Creative Commons' href='https://creativecommons.org/')
i.fab.fa-creative-commons
a(rel='noopener' target='_blank' title='CC BY 4.0' href='https://creativecommons.org/licenses/by/4.0/deed.zh') CC BY 4.0

打开ROOT\themes\butterfly\source\css_layout文件夹,修改post.styl文件

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
  .post-copyright
position: relative
margin: 2rem 0 .5rem
padding: .5rem .8rem
border: 1px solid var(--light-grey)
transition: box-shadow .3s ease-in-out
+ overflow: hidden
+ border-radius: 12px!important
+ background-color: rgb(239 241 243)

&:before
- @extend .fontawesomeIcon
- position: absolute
- top: .1rem
- right: .6rem
- color: $theme-color
- content: '\f1f9'
- font-size: 1rem
+ position absolute
+ right -26px
+ top -120px
+ content '\f25e'
+ font-size 200px
+ font-family 'Font Awesome 5 Brands'
+ opacity .2

&:hover
box-shadow: 0 0 8px 0 rgba(232, 237, 250, .6), 0 2px 4px 0 rgba(232, 237, 250, .5)

.post-copyright
&-meta
color: $light-blue
font-weight: bold

&-info
padding-left: .3rem

a
- text-decoration: underline
+ text-decoration: none
word-break: break-word

&:hover
text-decoration: none

+ .post-copyright-cc-info
+ color: $theme-color;

.post-outdate-notice
position: relative
margin: 0 0 1rem
padding: .5em 1.2em
border-radius: 15px
background-color: $noticeOutdate-bg
color: $noticeOutdate-color

源代码

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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
beautify()
headStyle(fontsize)
padding-left: unit(fontsize + 12, 'px')

&:before
margin-left: unit((-(fontsize + 6)), 'px')
font-size: unit(fontsize, 'px')

&:hover
padding-left: unit(fontsize + 18, 'px')

h1,
h2,
h3,
h4,
h5,
h6
transition: all .2s ease-out

&:before
position: absolute
top: calc(50% - 7px)
color: $title-prefix-icon-color
content: $title-prefix-icon
line-height: 1
transition: all .2s ease-out
@extend .fontawesomeIcon

&:hover
&:before
color: $light-blue

h1
headStyle(20)

h2
headStyle(18)

h3
headStyle(16)

h4
headStyle(14)

h5
headStyle(12)

h6
headStyle(12)

ol,
ul
p
margin: 0 0 8px

li
&::marker
color: $light-blue
font-weight: 600
font-size: 1.05em

&:hover
&::marker
color: var(--pseudo-hover)

ul > li
list-style-type: circle

#article-container
word-wrap: break-word
overflow-wrap: break-word

a
color: $theme-link-color

&:hover
text-decoration: underline

img
display: block
margin: 0 auto 20px
max-width: 100%
transition: filter 375ms ease-in .2s

p
margin: 0 0 16px

iframe
margin: 0 0 20px

kbd
margin: 0 3px
padding: 3px 5px
border: 1px solid #b4b4b4
border-radius: 3px
background-color: #f8f8f8
box-shadow: 0 1px 3px rgba(0, 0, 0, .25), 0 2px 1px 0 rgba(255, 255, 255, .6) inset
color: #34495e
white-space: nowrap
font-weight: 600
font-size: .9em
font-family: Monaco, 'Ubuntu Mono', monospace
line-height: 1em

if hexo-config('anchor.button.enable')
a.headerlink
&:after
@extend .fontawesomeIcon
float: right
color: var(--headline-presudo)
content: $archor-button-icon
font-size: .95em
transition: all .3s

&:hover
&:after
color: var(--pseudo-hover)

if !hexo-config('anchor.button.always_show')
a.headerlink
&:after
opacity: 0

h1,
h2,
h3,
h4,
h5,
h6
&:hover
a.headerlink
&:after
opacity: 1

ol,
ul
ol,
ul
padding-left: 20px

li
margin: 4px 0

p
margin: 0 0 8px

if hexo-config('beautify.enable')
if hexo-config('beautify.field') == 'site'
beautify()
else if hexo-config('beautify.field') == 'post'
&.post-content
beautify()

> :last-child
margin-bottom: 0 !important

#post
.tag_share
&:after
display: block
clear: both
content: ''

.post-meta
&__tag-list
display: inline-block

&__tags
display: inline-block
margin: 8px 8px 8px 0
padding: 0 12px
width: fit-content
border: 1px solid $light-blue
border-radius: 12px
color: $light-blue
font-size: .85em
transition: all .2s ease-in-out

&:hover
background: $light-blue
color: var(--white)

.post_share
display: inline-block
float: right
margin: 8px 0 0
width: fit-content

.social-share
font-size: .85em

.social-share-icon
margin: 0 4px
width: w = 1.85em
height: w
font-size: 1.2em
line-height: w

.post-copyright
position: relative
margin: 40px 0 10px
padding: 10px 16px
border: 1px solid var(--light-grey)
transition: box-shadow .3s ease-in-out

&:before
@extend .fontawesomeIcon
position: absolute
top: 2px
right: 12px
color: $theme-color
content: '\f1f9'
font-size: 1.3em

&:hover
box-shadow: 0 0 8px 0 rgba(232, 237, 250, .6), 0 2px 4px 0 rgba(232, 237, 250, .5)

.post-copyright
&-meta
color: $light-blue
font-weight: bold

&-info
padding-left: 6px

a
text-decoration: underline
word-break: break-word

&:hover
text-decoration: none

.post-outdate-notice
position: relative
margin: 0 0 20px
padding: .5em 1.2em
border-radius: 3px
background-color: $noticeOutdate-bg
color: $noticeOutdate-color

if hexo-config('noticeOutdate.style') == 'flat'
padding: .5em 1em .5em 2.6em
border-left: 5px solid $noticeOutdate-border

&:before
@extend .fontawesomeIcon
position: absolute
top: 50%
left: .9em
color: $noticeOutdate-border
content: '\f071'
transform: translateY(-50%)

.ads-wrap
margin: 40px 0

新建copyright.css,适配夜间模式和美化字体样式,放入ROOT\themes\butterfly\source\css

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[data-theme="dark"]
#post .post-copyright {
background-color: rgb(7 8 10);
text-shadow: #bfbeb8 1px 0 4px;
}
[data-theme="dark"]
#post .post-copyright {
border: 1px solid rgb(19 18 18 / 35%);
}
[data-theme="dark"]
.post-copyright-info {
color: #e0e0e4;
}
#post .post-copyright__title{
font-size:22px;
}
#post .post-copyright__notice{
font-size:15px;
}

配置主题文件

1
2
3
4
inject:
head
- <link rel="stylesheet" href="/css/copyright.css">
bottom:

2023-1-24 15:24:00 增加标签云文章数上下标

https://blog.eurkon.com/post/6687849c.html

增加标签云文章数上下标

前言

本文教程主要针对 Hexo Butterfly 主题博客,在 Butterfly 主题中,文章标签页和标签侧边栏都有文章标签的词云图,但仅仅用字体大小表示某个标签下的文章数量是不明显的,可以在这个基础上加上表示某个标签下文章数的上下标,其中 表示上标, 表示下标。

修改 page.js

  1. 打开 \themes\butterfly\layout\includes\page\tags.pug 文件和 \themes\butterfly\layout\includes\widget\card_tags.pug 文件,发现绘制彩色标签云都是使用了 cloudTags 函数。

另外一个绘制标签云的 tagcloud 函数是 hexo 自带的,有兴趣的可以到 \node_modules\hexo\lib\plugins\helper\tagcloud.js 研究,这里不多介绍。

  1. 搜索 cloudTags 函数,可以在 \themes\butterfly\scripts\helpers\page.js 找到绘制标签云的代码,增加 tag.length</sup><sub>{tag.length}</sup> 或 <sub>{tag.length} 可绘制表示标签文章数的上下标。
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
hexo.extend.helper.register('cloudTags', function (options = {}) {
const theme = hexo.theme.config
const env = this
let source = options.source
const minfontsize = options.minfontsize
const maxfontsize = options.maxfontsize
const limit = options.limit
const unit = options.unit || 'px'

let result = ''
if (limit > 0) {
source = source.limit(limit)
}

const sizes = []
source.sort('length').forEach(tag => {
const { length } = tag
if (sizes.includes(length)) return
sizes.push(length)
})

const length = sizes.length - 1
source.forEach(tag => {
const ratio = length ? sizes.indexOf(tag.length) / length : 0
const size = minfontsize + ((maxfontsize - minfontsize) * ratio)
let style = `font-size: ${parseFloat(size.toFixed(2))}${unit};`
const color = 'rgb(' + Math.floor(Math.random() * 201) + ', ' + Math.floor(Math.random() * 201) + ', ' + Math.floor(Math.random() * 201) + ')' // 0,0,0 -> 200,200,200
style += ` color: ${color}`
- result += `<a href="${env.url_for(tag.path)}" style="${style}">${tag.name}</a>`
+ result += `<a href="${env.url_for(tag.path)}" style="${style}">${tag.name}<sup>${tag.length}</sup></a>`
})
return result
})

2023-1-24 22:24:00 修改友链样式

修改友链样式

https://anzhiy.cn/posts/292d.html
打开[Blogroot]\source\_data\link.yml,输入:

标准写法

1
2
3
4
5
6
7
8
- class_name: 推荐博客
flink_style: flexcard # 可选flexcard butterfly二选一
link_list:
- name: 安知鱼`Blog
link: https://anzhiy.cn/
avatar: https://img02.anzhiy.cn/adminuploads/1/2022/09/15/63232b7d91d22.jpg
descr: 生活明朗,万物可爱
siteshot: https://npm.elemecdn.com/anzhiyu-blog@1.1.6/img/post/common/anzhiy.cn.jpg

替换[Blogroot]\themes\butterfly\layout\includes\page\flink.pug

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
#article-container
if top_img === false
h1.page-title= page.title
.flink
if site.data.link
each i in site.data.link
if i.class_name
h2!= i.class_name
if i.class_desc
.flink-desc!=i.class_desc
if i.flink_style === 'butterfly'
.butterfly-flink-list
each item in i.link_list
.flink-list-item
a(href=url_for(item.link) title=item.name target="_blank")
.flink-item-icon
if theme.lazyload.enable
img(data-lazy-src=url_for(item.avatar) onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.flink) + `'` alt=item.name )
else
img(src=url_for(item.avatar) onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.flink) + `'` alt=item.name )
.flink-item-info
.flink-item-name= item.name
.flink-item-desc(title=item.descr)= item.descr
else if i.flink_style === 'flexcard'
.flexcard-flink-list
each item in i.link_list
a.flink-list-card(href=url_for(item.link) target='_blank' data-title=item.descr)
.wrapper.cover
- var siteshot = item.siteshot ? url_for(item.siteshot) : 'https://image.thum.io/get/width/400/crop/800/allowJPG/wait/20/noanimate/' + item.link
if theme.lazyload.enable
img.cover.fadeIn(data-lazy-src=siteshot onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.post_page) + `'` alt='' )
else
img.cover.fadeIn(src=siteshot onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.post_page) + `'` alt='' )
.info
if theme.lazyload.enable
img.flink-avatar(data-lazy-src=url_for(item.avatar) onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.flink) + `'` alt='' )
else
img(src=url_for(item.avatar) onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.flink) + `'` alt='' )
span.flink-sitename= item.name
!= page.content

flink.pug原文件

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
#article-container
.flink
- let pageContent = page.content
if page.flink_url
script.
(()=>{
const replaceSymbol = (str) => {
return str.replace(/[\p{P}\p{S}]/gu, "-")
}

let result = ""
fetch("!{url_for(page.flink_url)}")
.then(response => response.json())
.then(str => {
for(let i = 0; i < str.length; i++){
const replaceClassName = replaceSymbol(str[i].class_name)
const className = str[i].class_name ? `<h2 id="${replaceClassName}"><a href="#${replaceClassName}" class="headerlink" title="${str[i].class_name}"></a>${str[i].class_name}</h2>` : ""
const classDesc = str[i].class_desc ? `<div class="flink-desc">${str[i].class_desc}</div>` : ""

let listResult = ""
const lists = str[i].link_list
for(let j = 0; j < lists.length; j++){
listResult += `
<div class="flink-list-item">
<a href="${lists[j].link}" title="${lists[j].name}" target="_blank">
<div class="flink-item-icon">
<img class="no-lightbox" src="${lists[j].avatar}" onerror='this.onerror=null;this.src="!{url_for(theme.error_img.flink)}"' alt="${lists[j].name}" />
</div>
<div class="flink-item-name">${lists[j].name}</div>
<div class="flink-item-desc" title="${lists[j].descr}">${lists[j].descr}</div>
</a>
</div>`
}

result += `${className}${classDesc} <div class="flink-list">${listResult}</div>`
}

document.querySelector(".flink").insertAdjacentHTML("afterbegin", result)
})
})()

else
if site.data.link
- let result = ""
each i in site.data.link
- let className = i.class_name ? markdown(`## ${i.class_name}`) : ""
- let classDesc = i.class_desc ? `<div class="flink-desc">${i.class_desc}</div>` : ""

- let listResult = ""

each j in i.link_list
-
listResult += `
<div class="flink-list-item">
<a href="${j.link}" title="${j.name}" target="_blank">
<div class="flink-item-icon">
<img class="no-lightbox" src="${j.avatar}" onerror='this.onerror=null;this.src="${url_for(theme.error_img.flink)}"' alt="${j.name}" />
</div>
<div class="flink-item-name">${j.name}</div>
<div class="flink-item-desc" title="${j.descr}">${j.descr}</div>
</a>
</div>`
-

- result += `${className}${classDesc} <div class="flink-list">${listResult}</div>`

- pageContent = result + pageContent
!= pageContent


替换

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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
.flink-desc
margin: .2rem 0 .5rem

.butterfly-flink-list
overflow: auto
padding: 10px 10px 0
text-align: center

& > .flink-list-item
position: relative
float: left
overflow: hidden
line-height: 17px
-webkit-transform: translateZ(0)
height: 100px;
padding: 10px;
width: calc(100% / 5 - 0.5rem)
margin: 0.5rem 0.25rem;
border-radius: 12px;
border: var(--style-border);
background-color: var(--anzhiyu-card-bg);
-webkit-transition: all .3s ease-in-out;
-moz-transition: all .3s ease-in-out;
-o-transition: all .3s ease-in-out;
-ms-transition: all .3s ease-in-out;
transition: all .3s ease-in-out;

+maxWidth1024()
width: calc(50% - 15px) !important

+maxWidth600()
width: calc(100% - 15px) !important

&:hover
border-color: var(--anzhiyu-main)!important;
background-color: var(--anzhiyu-main)!important;
box-shadow: var(--anzhiyu-shadow-theme)!important;

.flink-item-icon
width: 0;
height: 0;
margin-left: -10px;
.flink-item-name,.flink-item-desc
color: var(--anzhiyu-white);

&:hover:before,
&:focus:before,
&:active:before
transform: scale(1)

a
color: var(--font-color)
text-decoration: none

.flink-item-icon
float: left
overflow: hidden
margin: 15px 10px
width: 60px
height: 60px
border-radius: 35px
transition: all .3s ease-out
margin: 8px 0 8px 0;
background: var(--anzhiyu-background);
border-radius: 50%;
overflow: hidden;

img
width: 100%
height: 100%
transition: filter 375ms ease-in .2s, transform .3s
object-fit: cover

.img-alt
display: none
.flink-item-info
display: flex;
flex-wrap: wrap;
padding-left: 10px;
text-align: left;
flex-direction: column;

.flink-item-name
@extend .limit-one-line
padding: 12px 0 16px 0;
height: auto;
font-weight: bold
font-size: 1.2em
color: var(--anzhiyu-fontcolor);

.flink-item-desc
@extend .limit-one-line
padding: 0
height: 35px
font-size: .93em
opacity: .7;
color: var(--anzhiyu-fontcolor);
word-break: break-all;
white-space: break-spaces;
display: -webkit-box;
overflow: hidden;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;

.flink-name
margin-bottom: 5px
font-weight: bold
font-size: 1.5em

#article-container img
margin-bottom: 0.5rem;
object-fit: cover;
max-height: 900px;
.flexcard-flink-list
overflow hidden
.flink-list-card
.wrapper img
transition: transform .5s ease-out !important;
&:hover
border-color: var(--anzhiyu-main)!important;
background-color: var(--anzhiyu-main)!important;
box-shadow: var(--anzhiyu-shadow-theme)!important;

& > a
width: calc(100% / 5 - 0.5rem);
height 150px
position relative
display block
margin: 0.5rem 0.25rem;
float left
overflow hidden
padding: 0;
border-radius: 8px;
transition all .3s ease 0s, transform .6s cubic-bezier(.6, .2, .1, 1) 0s
box-shadow none
border: var(--style-border)!important;
&:hover
.info
transform translateY(-100%)
.wrapper
img
transform scale(1.2)
&::before
position: fixed
width:inherit
margin:auto
left:0
right:0
top:10%
border-radius: 10px
text-align: center
z-index: 100
content: attr(data-title)
font-size: 20px
color: #fff
padding: 10px
background-color: rgba($theme-color,0.8)

.cover
width 100%
transition transform .5s ease-out
.wrapper
position relative
.fadeIn
animation coverIn .8s ease-out forwards
img
height 150px
pointer-events none
.info
display flex
flex-direction column
justify-content center
align-items center
width 100%
height 100%
overflow hidden
border-radius 3px
background-color hsla(0, 0%, 100%, .7)
transition transform .5s cubic-bezier(.6, .2, .1, 1) 0s
img
position relative
top 45px
width 80px
height 80px
border-radius 50%
box-shadow 0 0 10px rgba(0, 0, 0, .3)
z-index 1
text-align center
pointer-events none
span
padding 20px 10% 60px 10%
font-size 16px
width 100%
text-align center
box-shadow 0 0 10px rgba(0, 0, 0, .3)
background-color hsla(0, 0%, 100%, .7)
color var(--font-color)
white-space nowrap
overflow hidden
text-overflow ellipsis
.flexcard-flink-list>a .info,
.flexcard-flink-list>a .wrapper .cover
position absolute
top 0
left 0

@media screen and (max-width:1024px)
.flexcard-flink-list
& > a
width calc(33.33333% - 15px)

@media screen and (max-width:600px)
.flexcard-flink-list
& > a
width calc(50% - 15px)

[data-theme=dark]
.flexcard-flink-list a .info,
.flexcard-flink-list a .info span
background-color rgba(0, 0, 0, .6)
.flexcard-flink-list
& > a
&:hover
&:before
background-color: rgba(#121212,0.8);
.justified-gallery > div > img,
.justified-gallery > figure > img,
.justified-gallery > a > a > img,
.justified-gallery > div > a > img,
.justified-gallery > figure > a > img,
.justified-gallery > a > svg,
.justified-gallery > div > svg,
.justified-gallery > figure > svg,
.justified-gallery > a > a > svg,
.justified-gallery > div > a > svg,
.justified-gallery > figure > a > svg
position static!important

flink.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
84
85
86
87
#article-container
.flink
margin-bottom: 20px

.flink-list
overflow: auto
padding: 10px 10px 0
text-align: center

& > .flink-list-item
position: relative
float: left
overflow: hidden
margin: 15px 7px
width: calc(100% / 3 - 15px)
height: 90px
border-radius: 8px
line-height: 17px
-webkit-transform: translateZ(0)

+maxWidth1024()
width: calc(50% - 15px) !important

+maxWidth600()
width: calc(100% - 15px) !important

&:hover
.flink-item-icon
margin-left: -10px
width: 0

&:before
position: absolute
top: 0
right: 0
bottom: 0
left: 0
z-index: -1
background: var(--text-bg-hover)
content: ''
transition: transform .3s ease-out
transform: scale(0)

&:hover:before,
&:focus:before,
&:active:before
transform: scale(1)

a
color: var(--font-color)
text-decoration: none

.flink-item-icon
float: left
overflow: hidden
margin: 15px 10px
width: 60px
height: 60px
border-radius: 35px
transition: width .3s ease-out

img
width: 100%
height: 100%
transition: filter 375ms ease-in .2s, transform .3s
object-fit: cover

.img-alt
display: none

.flink-item-name
@extend .limit-one-line
padding: 16px 10px 0 0
height: 40px
font-weight: bold
font-size: 1.43em

.flink-item-desc
@extend .limit-one-line
padding: 16px 10px 16px 0
height: 50px
font-size: .93em

.flink-name
margin-bottom: 5px
font-weight: bold
font-size: 1.5em

获取网站截图接口
https://image.thum.io/get/width/400/crop/800/allowJPG/wait/20/anzhiy.cn/https://http://ehall.njust.edu.cn/new/index.html

2023-1-26 22:24:00 魔改关于界面

魔改关于界面

本部分参照了安知鱼HiPeach的教程

写成教程啦

content

2023-1-26 23:15:00 butterfly宽幅调整

butterfly宽幅调整

content

2023-1-26 23:45:00 个人信息卡片调整

个人信息卡片调整

Eacls的方案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*个人信息美化*/
#aside-content>.card-widget.card-info {
background: #fff url(https://www.eacls.top/img/info.webp) top 33% center no-repeat;
position: relative;
}
#aside-content .card-info #card-info-btn {
display: none;
}
#aside-content .card-info .author-info__name {
font-weight: 700;
color: black;
}
#aside-content .card-info .author-info__description {
font-weight: 600;
color: black;
}
.site-data > a .headline {
color: rgb(0 0 0 / 100%);
}

HiPeach的方案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*个人信息美化*/
#aside-content>.card-widget.card-info {
background: #fff url(/media/info.webp) top 18% center no-repeat;
position: relative;
}
#aside-content .card-info .site-data {
display: none;
}
#aside-content .card-info .author-info__name {
font-weight: 700;
color: black;
}
#aside-content .card-info .author-info__description {
font-weight: 600;
color: black;
}
.site-data > a .headline {
color: rgb(0 0 0 / 100%);
}

安知鱼的方案(渐变色)

1
2
3
4
5
6
7
8
9
10
11
12
#aside-content > .card-widget.card-info {
background: linear-gradient(-45deg, var(--anzhiyu-main), #031764, #150136, #67044d);
background-size: 400%;
box-shadow: var(--anzhiyu-shadow-black);
animation: gradient 15s ease infinite;
position: relative;
color: var(--anzhiyu-white);
}
.site-data > a .headline,
.site-data > a .length-num {
color: var(--anzhiyu-white);
}

我的渐变色

1
2
3
4
5
6
7
8
9
10
11
12
#aside-content > .card-widget.card-info {
background: linear-gradient(-45deg, var(--HiPeach-main), #ef7e51, #b53e1d, #67044d);
background-size: 400%;
box-shadow: var(--HiPeach-shadow-black);
animation: gradient 15s ease infinite;
position: relative;
color: var(--HiPeach-white);
}
.site-data > a .headline,
.site-data > a .length-num {
color: var(--HiPeach-white);
}

2023-1-26 23:57:00 文章页信息栏美化

文章页信息栏美化

https://www.eacls.top/posts/286b8081/

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
/*文章页信息栏美化*/
#post-info .post-title {
font-weight: 600; /*字体粗细*/
font-size: 2.5em; /*字体大小*/
line-height: 2.2; /*元素高度*/
letter-spacing: 1px; /*字体间距*/
}

/*信息栏高度调整*/
#page-header.post-bg {
height: 26rem;
}

/*Web端信息栏适配*/
@media screen and (min-width: 421px){
#page-header #post-info {
bottom: 8rem;
}
}

/*Wap端信息栏适配*/
@media screen and (max-width: 420px){
#page-header #post-info {
bottom: 2rem;
}
}

2023-1-27 00:11:00 网址卡片外挂标签

2023-3-6 00:11:00 RSS订阅

RSS订阅

经过博友建议,加上了RSS订阅功能。参考教程如下:

其中参数的定义可查看插件github官方文档

2023-4-30 17:28:00 生成永久链接

停更快两个月,原因是储存博客数据的移动硬盘坏了。心太痛!
此前我也曾经坏过硬盘,幸亏有以前的经验,迅速第一时间硬盘断电,开盘恢复数据。将近2T的数据应该基本完全修复,感谢维修师傅,总共费用450,业务能力和费用都没得说。如果在南京的同学也遇到硬盘损坏,悄悄帮师傅打个广告:南京红警数据恢复。
万幸博客数据完整无损,万幸硬盘中各类笔记完整无损,以前的图像视频估计也基本无损。
深深意识到数据备份的重要性。有时间专门写个帖。

安装插件

1
npm install hexo-abbrlink --save

使用

修改_config.yml

1
2
## permalink: :year/:month/:day/:title/
permalink: posts/:abbrlink.html ## 此处可以自己设置

增加以下设置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
## abbrlink config
abbrlink:
alg: crc32 #support crc16(default) and crc32 进制
rep: hex #support dec(default) and hex 算法
drafts: false #(true)Process draft,(false)Do not process draft. false(default)
## Generate categories from directory-tree
## depth: the max_depth of directory-tree you want to generate, should > 0
auto_category:
enable: true #true(default)
depth: #3(default)
over_write: false
auto_title: false #enable auto title, it can auto fill the title by path
auto_date: false #enable auto date, it can auto fill the date by time today
force: false #enable force mode,in this mode, the plugin will ignore the cache, and calc the abbrlink for every post even it already had abbrlink.

评论
avatar
Prong
这是尖头叉子在霍格沃茨的休息室~
Follow Me
公告
鼠鼠我啊,做着玩捏~
最新文章
网站资讯
文章数目 :
60
已运行时间 :
本站总字数 :
241.6k
本站访客数 :
本站总访问量 :
最后更新时间 :
访客地球