mohのAI正在绞尽脑汁想思路ING···
mohのAI摘要
mohのAI-Lite

个人卡片背景图

1、在自建的css样式中加入一下代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[data-theme="light"] #aside-content > .card-widget.card-info {
background-image: url(https://s11.ax1x.com/2023/05/02/p9GWEin.jpg);
background-repeat: no-repeat;
background-attachment: inherit;
background-size: 100%;
}
[data-theme="dark"] #aside-content > .card-widget.card-info {
background-image: url(https://s11.ax1x.com/2023/05/02/p9GWVGq.jpg);
background-repeat: no-repeat;
background-attachment: inherit;
background-size: 100%;
}

/* 个人信息卡片背景图 */

归档、分类详情页卡片样式开发

预览

首先创建根目录/source/css/layout.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
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
/* 归档、标签、分类页 */
:root {
--ichika-color: rgba(100, 180, 239, 0.51);
--ichika-hover-color: #ECAFFF;
--ichika-widget-hover: #CFF0FF;
--ichika-font-white: #FDFDFD;
--ichika-light-green: #B2FFCA;
--ichika-light-purple: #F6B9FF;
--ichika-green: #11D991;
--ichika-purple: #E764FF;
--ichika-light-grey: #F2F2F2;
--ichika-card-bg: rgba(255,255,255,0.45);
--ichika-emphasis-color: #F7F81A;
--ichika-bgblur: blur(10px);
--ichika-footer-bg: linear-gradient(to bottom,transparent 0%,rgba(255,255,255,0.7) 40%);
--ichika-font-grey: #888888;
--ichika-categorycard-bg: linear-gradient(to top,rgba(255,255,255,0),rgba(255,255,255,1))
}

[data-theme='dark'] {
--global-bg:black;
--ichika-color: #1688C9;
--ichika-widget-hover: #1B6587;
--ichika-card-bg: rgba(0,0,0,0.7);
--ichika-footer-bg: linear-gradient(to bottom,transparent 0%,rgba(0,0,0,0.7) 40%);
--ichika-font-grey: #BBBBBB;
--ichika-categorycard-bg:linear-gradient(to top,rgba(0,0,0,0),rgba(0,0,0,1))
}


.layout.hide-aside{
max-width:1200px;
}

#archive,#tag,#category {
background: var(--ichika-card-bg);
padding: 25px 10px;
}

.article-sort-title{
margin-top:30px;
margin-bottom:20px;
}

.article-sort-item::before, .article-sort-title::before, .article-sort-title::after {
content: none;
}

.article-sort .year{
width:100%!important;
border-bottom:dashed 5px var(--ichika-color);
font-size:26px;
margin-top:20px;
}

.article-sort{
border:none;
display:flex;
flex-wrap:wrap;
margin:20px 20px;
padding:0;
}

.article-sort-item:not(.year){
padding:8px 10px;
width:calc(50% - 0.8rem);
margin:0.4rem;
border:2px solid var(--ichika-color);
border-radius:15px;
background:var(--card-bg);
transition:0.5s;
height:120px;
}

.article-sort-item-a{
position:absolute;
width:100%;
height:100%;
}

.article-sort-item-img{
transition:0.5s;
height:90px;
width:140px;
}

.article-sort-item > a >img{
border-radius:15px;
}

.article-sort-item-title {
font-size: 22px;
padding-left: 10px;
margin: 10px 0;
line-height:25px;
text-overflow:ellipsis;
}

.article-sort-item-title:hover{
transform:none;
}

.article-sort-meta{
height:max-content;
position:relative;
}

.article-sort-meta > .article-meta-wrap{
float:left;
}

.article-sort-meta > .article-sort-item-time{
float:right;
}

.article-sort-item-categories,.article-sort-item-tags{
margin:0 3px;
padding:5px 8px;
border-radius:25px;
border:1px solid var(--dark-grey);
font-size:12px;
transition:0.5s;
}

.article-sort-item-info > div:not(.article-sort-meta){
display:flex;
}

.article-sort-description,.article-sort-item > i{
width:0;
opacity:0;
overflow:hidden;
transition:0.5s;
}

.article-sort-description {
width: 0;
height: 59px;
vertical-align: middle;
margin: 5px 10px 0 15px;
text-overflow:ellipsis;
}

.article-sort-item:hover:not(.year){
background-color:var(--ichika-color);
box-shadow: 0 0 10px var(--ichika-color);
}

.article-sort-item:hover:not(.year){
background-color:var(--ichika-color);
box-shadow: 0 0 10px var(--ichika-color);
}

.article-sort-item:hover:not(.year) .article-sort-description,.article-sort-item:hover:not(.year) > i{
width:auto;
opacity:1;
}

.article-sort-item:hover:not(.year) .article-sort-description{
width:auto;
}

.article-sort-item:hover:not(.year) .article-sort-item-img{
transition:0.5s;
width:0;
}

.article-sort-item:hover:not(.year) .article-sort-item-title{
color:var(--ichika-font-white)!important;
}

.article-sort-item:hover:not(.year) .article-meta-wrap a,.article-sort-item:hover:not(.year) .article-sort-description,.article-sort-item:hover:not(.year) .article-sort-item-time{
color:var(--ichika-light-grey)!important;
}

.article-sort-item:hover:not(.year) .article-sort-item-categories{
border:1.5px solid var(--ichika-green);
}

.article-sort-item:hover:not(.year) .article-sort-item-tags{
border:1.5px solid var(--ichika-purple);
}

.article-sort-item:hover:not(.year) .article-sort-item-categories:hover{
background:var(--ichika-green);
box-shadow:0 0 5px var(--ichika-green);
}

.article-sort-item:hover:not(.year) .article-sort-item-tags:hover{
background:var(--ichika-purple);
box-shadow:0 0 5px var(--ichika-purple);
}

@media screen and (max-width:768px) {
.article-sort-item:not(.year) {
width: 100%;
}

.article-sort-meta > .article-meta-wrap {
display: none;
}

.article-sort-item-title {
font-size: 16px;
}

.article-sort-item-img{
width:90px;
}
}


themes/butterfly/layout/includes/mixins/article-sort.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
mixin articleSort(posts)
.article-sort
- var year
- posts.each(function (article) {
- let tempYear = date(article.date, 'YYYY')
- let no_cover = article.cover === false || !theme.cover.archives_enable ? 'no-article-cover' : ''
- let title = article.title || _p('no_title')
if tempYear !== year
- year = tempYear
.article-sort-item.year= year
.article-sort-item(class=no_cover)
a.article-sort-item-a(href=url_for(article.path) title=title)
if article.cover && theme.cover.archives_enable
a.article-sort-item-img(href=url_for(article.path) title=title)
img(src=url_for(article.cover) alt=title onerror=`this.onerror=null;this.src='${url_for(theme.error_img.post_page)}'`)
.article-sort-item-info
div
a.article-sort-item-title(href=url_for(article.path) title=title)= title
.article-sort-description= article.description
.article-sort-meta
.article-meta-wrap
if (theme.post_meta.page.categories && article.categories.data.length > 0)
span.article-sort-item-categories
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
if (theme.post_meta.page.tags && article.tags.data.length > 0)
span.article-sort-item-tags
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 #[=' ']
.article-sort-item-time
i.far.fa-calendar-alt
time.post-meta-date-created(datetime=date_xml(article.date) title=_p('post.created') + ' ' + full_date(article.date))= date(article.date, config.date_format)
i.fas.fa-chevron-right
- })

参考文章:

欢迎来访者(侧边栏)

由于liushen给出的api代码不全,因此我完善了api内容,就有了以下的教程

效果图:

image-20260405102231574

教程开始

按照惯例,我们先实现插入html结构 ,新建pug文件如下:

1
[BlogRoot]\themes\butterfly\layout\includes\widget\card_welcome.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
.card-widget.card-welcome
.item-headline
i.fa.fa-user
span 欢迎来访者!
.item-content
p 👋🏻我是moh,一个
span(style="font-weight: bold; color: #3498db") 热爱编程
| 的技术爱好者,喜欢分享经验。😊
p ❓有问题欢迎提问,确保内容有意义,详情请见
a(href="https://how-to-ask.liushen.fun/" target="_blank" style="font-weight: bold; color: #2980b9") 提问的智慧
| 。如需联系我,欢迎通过
a(href="mailto:01@liushen.fun" style="font-weight: bold; color: #9b59b6") 邮箱
| 联系我!📧
#welcome-info
.error-message(style="height: 200px; display: flex; justify-content: center; align-items: center;")
p(style="text-align: center;")
span(style="font-size: 40px;") 😥
br
span(style="font-size: 16px;") 由于网络问题
br
span(style="font-size: 16px;") 位置API请求错误
br
span(style="font-size: 16px;") 请刷新重试呀🤗~

结构实现了,下面将该结构插入到对应的位置,可以在当前目录下的index.pug找到对应结构,如下:

文件路径:

1
[BlogRoot]\themes\butterfly\layout\includes\widget\index.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
#aside-content.aside-content
//- post
if is_post()
- const tocStyle = page.toc_style_simple
- const tocStyleVal = tocStyle === true || tocStyle === false ? tocStyle : theme.toc.style_simple
if showToc && tocStyleVal
.sticky_layout
include ./card_post_toc.pug
else
!=partial('includes/widget/card_author', {}, {cache: true})
!=partial('includes/widget/card_poem', {}, {cache: true})
!=partial('includes/widget/card_rewards', {}, {cache: true})
!=partial('includes/widget/card_announcement', {}, {cache: true})
!=partial('includes/widget/card_top_self', {}, {cache: true})
.sticky_layout
if showToc
include ./card_post_toc.pug
if page.series
include ./card_post_series.pug
!=partial('includes/widget/card_recent_post', {}, {cache: true})
!=partial('includes/widget/card_ad', {}, {cache: true})
else
//- page
!=partial('includes/widget/card_author', {}, {cache: true})
+ !=partial('includes/widget/card_welcome', {}, {cache: true})
!=partial('includes/widget/card_poem', {}, {cache: true})
!=partial('includes/widget/card_rewards', {}, {cache: true})
!=partial('includes/widget/card_announcement', {}, {cache: true})
!=partial('includes/widget/card_top_self', {}, {cache: true})

.sticky_layout
if showToc
include ./card_post_toc.pug
!=partial('includes/widget/card_recent_post', {}, {cache: true})
!=partial('includes/widget/card_ad', {}, {cache: true})
!=partial('includes/widget/card_newest_comment', {}, {cache: true})
!=partial('includes/widget/card_categories', {}, {cache: true})
!=partial('includes/widget/card_tags', {}, {cache: true})
!=partial('includes/widget/card_archives', {}, {cache: true})
!=partial('includes/widget/card_webinfo', {}, {cache: true})
!=partial('includes/widget/card_bottom_self', {}, {cache: true})

结构实现了,还需要实现其样式,新建以下文件:

1
[BlogRoot]\themes\butterfly\source\css\_layout\card-welcome.styl

写入以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#aside-content
.card-widget.card-welcome
padding: 8px
.item-headline
margin: 12px 16px 0 16px
.item-content
margin: 0 16px 10px 16px
#welcome-info
text-align center
background-color: var(--liushen-card-bg)
border-radius: 12px
padding: 16px
margin: 8px
// border: 2px solid var(--liushen-text)
.ip-address
// 模糊效果
filter: blur(5px)
color: var(--default-bg-color)
transition: filter 0.5s
&:hover
filter: none

经过渲染应该就可以看到结果了。

不过由于我们的访客卡片需要调用api,所以还需要js的配合,在任意自定义js文件中添加以下内容:

新建以下文件:

1
[BlogRoot]/source/js/card-welcome.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
// 显示欢迎信息
// 计算两点之间的距离(单位:公里)
function getDistance(lat1, lon1, lat2, lon2) {
const R = 6371;
const dLat = (lat2 - lat1) * Math.PI / 180;
const dLon = (lon2 - lon1) * Math.PI / 180;
const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) *
Math.sin(dLon / 2) * Math.sin(dLon / 2);
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
return Math.round(R * c);
}

// 获取IP位置信息
function fetchIpLocation() {
return fetch('http://ip-api.com/json/?fields=status,message,country,regionName,city,lat,lon,query&lang=zh-CN')
.then(response => response.json())
.then(data => {
if (data.status !== 'success') {
throw new Error(data.message || 'IP定位失败');
}
return {
ip: data.query,
data: {
country: data.country,
prov: data.regionName,
city: data.city,
district: '',
lng: data.lon,
lat: data.lat
}
};
})
.catch(error => {
console.error('获取IP位置信息失败:', error);
return null;
});
}
function showWelcome(ipLocation) {
if (!ipLocation || !ipLocation.data) {
console.error('ipLocation data is not available.');
return;
}

let dist = getDistance(24.4798, 118.0894, ipLocation.data.lat, ipLocation.data.lng);
let pos = ipLocation.data.country;
let ip = ipLocation.ip;
let posdesc;

// 以下的代码需要根据新API返回的结果进行相应的调整
switch (ipLocation.data.country) {
case "日本":
posdesc = "よろしく,一起去看樱花吗";
break;
case "美国":
posdesc = "Let us live in peace!";
break;
case "英国":
posdesc = "想同你一起夜乘伦敦眼";
break;
case "俄罗斯":
posdesc = "干了这瓶伏特加!";
break;
case "法国":
posdesc = "C'est La Vie";
break;
case "德国":
posdesc = "Die Zeit verging im Fluge.";
break;
case "澳大利亚":
posdesc = "一起去大堡礁吧!";
break;
case "加拿大":
posdesc = "拾起一片枫叶赠予你";
break;
case "中国":
pos = ipLocation.data.prov + " " + ipLocation.data.city + " " + ipLocation.data.district;
switch (ipLocation.data.prov) {
case "北京市":
posdesc = "北——京——欢迎你~~~";
break;
case "天津市":
posdesc = "讲段相声吧";
break;
case "河北省":
posdesc = "山势巍巍成壁垒,天下雄关铁马金戈由此向,无限江山";
break;
case "山西省":
posdesc = "展开坐具长三尺,已占山河五百余";
break;
case "内蒙古自治区":
posdesc = "天苍苍,野茫茫,风吹草低见牛羊";
break;
case "辽宁省":
posdesc = "我想吃烤鸡架!";
break;
case "吉林省":
posdesc = "状元阁就是东北烧烤之王";
break;
case "黑龙江省":
posdesc = "很喜欢哈尔滨大剧院";
break;
case "上海市":
posdesc = "众所周知,中国只有两个城市";
break;
case "江苏省":
switch (ipLocation.data.city) {
case "南京市":
posdesc = "这是我挺想去的城市啦";
break;
case "苏州市":
posdesc = "上有天堂,下有苏杭";
break;
default:
posdesc = "散装是必须要散装的";
break;
}
break;
case "浙江省":
switch (ipLocation.data.city) {
case "杭州市":
posdesc = "东风渐绿西湖柳,雁已还人未南归";
break;
default:
posdesc = "望海楼明照曙霞,护江堤白蹋晴沙";
break;
}
break;
case "河南省":
switch (ipLocation.data.city) {
case "郑州市":
posdesc = "豫州之域,天地之中";
break;
case "信阳市":
posdesc = "品信阳毛尖,悟人间芳华";
break;
case "南阳市":
posdesc = "臣本布衣,躬耕于南阳此南阳非彼南阳!";
break;
case "驻马店市":
posdesc = "峰峰有奇石,石石挟仙气嵖岈山的花很美哦!";
break;
case "开封市":
posdesc = "刚正不阿包青天";
break;
case "洛阳市":
posdesc = "洛阳牡丹甲天下";
break;
default:
posdesc = "可否带我品尝河南烩面啦?";
break;
}
break;
case "安徽省":
posdesc = "蚌埠住了,芜湖起飞";
break;
case "福建省":
posdesc = "井邑白云间,岩城远带山";
break;
case "江西省":
posdesc = "落霞与孤鹜齐飞,秋水共长天一色";
break;
case "山东省":
posdesc = "遥望齐州九点烟,一泓海水杯中泻";
break;
case "湖北省":
switch (ipLocation.data.city) {
case "黄冈市":
posdesc = "红安将军县!辈出将才!";
break;
case "武汉市":
posdesc = "你想去长江游泳嘛?";
break;
default:
posdesc = "来碗热干面~";
break;
}
break;
case "湖南省":
posdesc = "74751,长沙斯塔克";
break;
case "广东省":
switch (ipLocation.data.city) {
case "广州市":
posdesc = "看小蛮腰,喝早茶了嘛~";
break;
case "深圳市":
posdesc = "今天你逛商场了嘛~";
break;
case "阳江市":
posdesc = "阳春合水!博主家乡~ 欢迎来玩~";
break;
default:
posdesc = "来两斤福建人~";
break;
}
break;
case "广西壮族自治区":
posdesc = "桂林山水甲天下";
break;
case "海南省":
posdesc = "朝观日出逐白浪,夕看云起收霞光";
break;
case "四川省":
posdesc = "康康川妹子";
break;
case "贵州省":
posdesc = "茅台,学生,再塞200";
break;
case "云南省":
posdesc = "玉龙飞舞云缠绕,万仞冰川直耸天";
break;
case "西藏自治区":
posdesc = "躺在茫茫草原上,仰望蓝天";
break;
case "陕西省":
posdesc = "来份臊子面加馍";
break;
case "甘肃省":
posdesc = "羌笛何须怨杨柳,春风不度玉门关";
break;
case "青海省":
posdesc = "牛肉干和老酸奶都好好吃";
break;
case "宁夏回族自治区":
posdesc = "大漠孤烟直,长河落日圆";
break;
case "新疆维吾尔自治区":
posdesc = "驼铃古道丝绸路,胡马犹闻唐汉风";
break;
case "台湾省":
posdesc = "我在这头,大陆在那头";
break;
case "香港特别行政区":
posdesc = "永定贼有残留地鬼嚎,迎击光非岁玉";
break;
case "澳门特别行政区":
posdesc = "性感荷官,在线发牌";
break;
default:
posdesc = "带我去你的城市逛逛吧!";
break;
}
break;
default:
posdesc = "带我去你的国家逛逛吧";
break;
}

// 根据本地时间切换欢迎语
let timeChange;
let date = new Date();
if (date.getHours() >= 5 && date.getHours() < 11) timeChange = "<span>🌤️ 早上好,快趁机多睡点懒觉!</span>";
else if (date.getHours() >= 11 && date.getHours() < 13) timeChange = "<span>☀️ 中午好,记得午休喔~</span>";
else if (date.getHours() >= 13 && date.getHours() < 17) timeChange = "<span>🕞 下午好,饮茶先啦!</span>";
else if (date.getHours() >= 17 && date.getHours() < 19) timeChange = "<span>🚶‍♂️ 下班啦!主打一个不听老板话~</span>";
else if (date.getHours() >= 19 && date.getHours() < 24) timeChange = "<span>🌙 晚上好,来一起熬夜吧呜😭</span>";
else timeChange = "夜深了,早点休息,少熬夜";

let welcomeInfoElement = document.getElementById("welcome-info");

if (welcomeInfoElement) {
welcomeInfoElement.innerHTML =
`嗷嗷!热烈欢迎🤪!来自<br><b><span style="color: var(--default-bg-color)">${pos}</span></b><br> 的铁铁,你好呀!😝<br>${posdesc}🍂<br>你目前距博主约 <b><span style="color: var(--default-bg-color)">${dist}</span></b> 公里!<br>你的网络IP为:<b><span class="ip-address" style="font-size: 15px;">${ip}</span></b><br>${timeChange} <br>`;
} else {
console.log("Pjax无法获取元素");
}
}

// 判断是否存在 "welcome-info" 元素
function isWelcomeInfoAvailable() {
let welcomeInfoElement = document.getElementById("welcome-info");
return welcomeInfoElement !== null;
}

// Pjax 完成后调用的处理函数
function handlePjaxComplete(ipLocation) {
if (isWelcomeInfoAvailable()) {
showWelcome(ipLocation);
}
}

// 加载时调用
function onLoad() {
fetchIpLocation().then(ipLocation => {
if (isWelcomeInfoAvailable()) {
showWelcome(ipLocation);
}
document.addEventListener("pjax:complete", () => handlePjaxComplete(ipLocation));
});
}

// 绑定 window.onload 事件
window.onload = onLoad;

最后将自定义的js文件引入到配置文件即可

参考文章:

今日诗词(侧边栏)

效果预览

image-20260405110956142

教程开始

按照惯例,我们先实现插入html结构 ,新建pug文件如下:

1
[BlogRoot]\themes\butterfly\layout\includes\widget\card_poem.pug

写入以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#card-poem.card-widget
#poem_sentence
#poem_info
#poem_dynasty
#poem_author
script(src='/js/jinrishici.js', charset='utf-8')
script(type='text/javascript').
jinrishici.load(function(result) {
var sentence = document.querySelector("#poem_sentence")
var author = document.querySelector("#poem_author")
var dynasty = document.querySelector("#poem_dynasty")

var sentenceText = result.data.content
sentenceText = sentenceText.substr(0, sentenceText.length - 1);
sentence.innerHTML = sentenceText
dynasty.innerHTML = result.data.origin.dynasty
author.innerHTML = result.data.origin.author + '《' + result.data.origin.title + '》'
});

结构实现了,下面将该结构插入到对应的位置,可以在当前目录下的index.pug找到对应结构,如下:

文件路径:

1
[BlogRoot]\themes\butterfly\layout\includes\widget\index.pug

在代码中插入以下带号的那行代码,注意缩进问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  else
//- page
!=partial('includes/widget/card_author', {}, {cache: true})
!=partial('includes/widget/card_welcome', {}, {cache: true})
+ !=partial('includes/widget/card_poem', {}, {cache: true})
!=partial('includes/widget/card_top_self', {}, {cache: true})

.sticky_layout
if showToc
include ./card_post_toc.pug
!=partial('includes/widget/card_recent_post', {}, {cache: true})
!=partial('includes/widget/card_ad', {}, {cache: true})
!=partial('includes/widget/card_newest_comment', {}, {cache: true})
!=partial('includes/widget/card_categories', {}, {cache: true})
!=partial('includes/widget/card_tags', {}, {cache: true})
!=partial('includes/widget/card_archives', {}, {cache: true})
!=partial('includes/widget/card_webinfo', {}, {cache: true})
!=partial('includes/widget/card_bottom_self', {}, {cache: true})

结构实现了,还需要实现其样式,新建以下文件:

1
[BlogRoot]\themes\butterfly\source\css\_layout\card-jinrishici.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
/* 古诗词卡片 */
#card-poem
display: flex
flex-direction: column
padding: 0.5rem !important

div#poem_sentence
text-align: center
font-family: serif, cursive
line-height: 1.4
margin-bottom: 0.5rem
padding: 1rem
border-radius: 8px
background: var(--liushen-card-bg)
min-height: 62px

div#poem_info
display: flex
color: var(--liushen-secondtext)
font-size: 0.5rem
justify-content: center
flex-wrap: wrap

div#poem_author
order: 1
padding: 2px
margin-left: 8px

div#poem_dynasty
order: 0
padding: 2px 4px 2px 6px
background: var(--liushen-button-bg)
color: var(--liushen-text)
border-radius: 8px

最后引入js 新建文件

1
[BlogRoot]\themes\butterfly\source\js\jinrishici.js

复制以下代码

1
2
!function(e){var n,t={},o="jinrishici-token";function i(){return document.getElementById("jinrishici-sentence")||0!=document.getElementsByClassName("jinrishici-sentence").length}function c(){t.load(function(e){var n=document.getElementById("jinrishici-sentence"),t=document.getElementsByClassName("jinrishici-sentence");if(n&&(n.innerText=e.data.content),0!==t.length)for(var o=0;o<t.length;o++)t[o].innerText=e.data.content})}function r(e,n){var t=new XMLHttpRequest;t.open("get",n),t.withCredentials=!0,t.send(),t.onreadystatechange=function(n){if(4===t.readyState){var o=JSON.parse(t.responseText);"success"===o.status?e(o):console.error("今日诗词API加载失败,错误原因:"+o.errMessage)}}}t.load=function(n){return e.localStorage&&e.localStorage.getItem(o)?function(e,n){return r(e,"https://v2.jinrishici.com/one.json?client=browser-sdk/1.2&X-User-Token="+encodeURIComponent(n))}(n,e.localStorage.getItem(o)):function(n){return r(function(t){e.localStorage.setItem(o,t.token),n(t)},"https://v2.jinrishici.com/one.json?client=browser-sdk/1.2")}(n)},e.jinrishici=t,i()?c():(n=function(){i()&&c()},"loading"!=document.readyState?n():document.addEventListener?document.addEventListener("DOMContentLoaded",n):document.attachEvent("onreadystatechange",function(){"complete"==document.readyState&&n()}))}(window);

参考文章:

赞赏侧边栏

效果:

image-20260405120330764

教程开始

1、赞赏数据

展示赞赏者的前提是,得有赞赏数据,所以我们先来构建该数据,创建文件[BlogRoot]/source/_data/rewards.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
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
donate:
# 支付宝收款码
alipay:
name: 支付宝收款码
image: /config/img/alipay.png
# 微信收款码
wechat:
name: 微信收款码
image: /config/img/wechat.png
thank_img: https://p.liiiu.cn/i/2025/10/10/68e9199157351.webp
# 赞赏页面链接
page_url: /rewards/
# 赞赏者列表
list:
- name: 银河香港
avatar: https://p.liiiu.cn/i/2025/02/26/67bec7d0eb734.webp
website:
date: 2025-03-15
amount: ¥100.00
description: 你我皆是生活银河中的闪耀星辰
- name: 周润发
avatar: https://p.liiiu.cn/i/2025/03/20/67dbe8c6a6221.webp
website: https://blog.zrf.me
date: 2025-08-01
amount: ¥30.00
description: 收录开源,好用的互联网项目~
- name: SXY
avatar: https://p.liiiu.cn/i/2025/10/11/68e93a9ccee45.webp
website:
date: 2025-08-29
amount: ¥10.00
description: 地球与物理专业的大三学生
- name: Ljx
avatar: https://p.liiiu.cn/i/2025/10/09/68e7d8ed2a70b.webp
website: https://blog.ljx.icu/
date: 2025-10-09
amount: ¥8.88
description: 一个无聊无趣的人~
- name: AirTouch
avatar: https://p.liiiu.cn/i/2025/07/18/687a369fc3610.webp
website: https://www.xsl.im/
date: 2025-10-10
amount: ¥18.88
description: 岩间琉璃云间月
- name: 短巷与雨
avatar: https://p.liiiu.cn/i/2024/11/18/673ac90233753.webp
website: https://space.xsl.im/
date: 2025-10-12
amount: ¥28.88
description: 为学日益,为道日损。
- name: 老罗博客
avatar: https://p.liiiu.cn/i/2025/06/01/683bc6062b113.webp
website: https://www.luosir.cn
date: 2025-10-12
amount: ¥8.88
description: 人生就是折腾
- name: 温柔鱼
avatar: https://p.liiiu.cn/i/2025/10/08/68e5e1f17ed12.webp
website: https://blog.vrou.cn
date: 2025-10-17
amount: ¥8.88
description: "NULL"
- name: 不知名朋友
avatar: https://p.liiiu.cn/i/2025/10/11/68e93a9ccee45.webp
website:
date: 2025-10-19
amount: ¥2.00
description: 感谢朋友的赞助~

其中列表的时间顺序建议上面最早,下面最新,因为我懒得写排序了嘻嘻,所以直接倒序,方便实用(反正每次添加都是往文件底部添加啦)。

有了数据,我们就开始添加到页面上吧

按照惯例,我们先实现插入html结构 ,新建pug文件如下:

1
[BlogRoot]\themes\butterfly\layout\includes\widget\card_rewards.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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
.card-widget.card-reward
.item-headline
.headline-content
i.fa-solid.fa-person-praying
span 能量榜
.show-more-inline
- var pageUrl = site.data.rewards.donate.page_url || '/reward/'
a(href=url_for(pageUrl) class="btn-show-more-inline")
span 前往赞赏
.item-content
if site.data.rewards && site.data.rewards.donate && site.data.rewards.donate.list.length > 0
- var allSponsors = site.data.rewards.donate.list.slice()
- allSponsors.sort(function() { return Math.random() - 0.5 })
- var carouselSponsors = allSponsors.slice(0, 40)
- var listSponsors = allSponsors.slice(0, 20)

if carouselSponsors.length > 0
.top-sponsor-carousel
.carousel-container
.carousel-item
a.sponsor-link-card(target="_blank" rel="nofollow noopener")
.sponsor-avatar
img.sponsor-avatar-img(src=url_for(carouselSponsors[0].avatar) alt=carouselSponsors[0].name onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.flink) + `'`)
.sponsor-info
.sponsor-name= carouselSponsors[0].name
.sponsor-desc= carouselSponsors[0].description

if listSponsors.length > 1
.sponsors-list
each sponsor in listSponsors
if sponsor.website
a.sponsor-item(href=sponsor.website target="_blank" rel="nofollow noopener")
.sponsor-small-name= sponsor.name
else
.sponsor-item
.sponsor-small-name= sponsor.name

if allSponsors.length > 20
- var pageUrl = site.data.rewards.donate.page_url || '/reward/'
a.sponsor-item.more-sponsor(href=url_for(pageUrl) target="_blank" rel="nofollow noopener")
.sponsor-small-name
| 查看更多
i.fa-solid.fa-angles-right

.sponsors-note
p 你们的赞赏是我最大的动力
p ※ 此处数据随机显示

script.
if (!window.sponsorsData) {
window.sponsorsData = !{JSON.stringify(carouselSponsors)};
}

function initRewardCarousel() {
const container = document.querySelector('.carousel-container');
const link = container.querySelector('.sponsor-link-card');
const avatar = container.querySelector('.sponsor-avatar-img');
const name = container.querySelector('.sponsor-name');
const desc = container.querySelector('.sponsor-desc');

if (!container || sponsorsData.length === 0) return;

let currentIndex = 0;
let intervalId = null;
let isTransitioning = false;

function updateSponsorInfo(sponsor) {
if (sponsor.website) {
link.href = sponsor.website;
// 确保有链接时移除 pointer-events 样式
link.style.pointerEvents = '';
link.style.cursor = 'pointer';
} else {
link.removeAttribute('href');
// 只有在没有链接时才添加 pointer-events: none
link.style.pointerEvents = 'none';
link.style.cursor = 'default';
}

avatar.src = sponsor.avatar;
avatar.alt = sponsor.name;

name.textContent = sponsor.name;
desc.textContent = sponsor.description;
}

function showSponsor(index) {
if (index < 0 || index >= sponsorsData.length || isTransitioning) return;

isTransitioning = true;
const sponsor = sponsorsData[index];

container.style.opacity = '0';

setTimeout(() => {
updateSponsorInfo(sponsor);
container.style.opacity = '1';
currentIndex = index;

setTimeout(() => {
isTransitioning = false;
}, 300);
}, 300);
}

function nextSponsor() {
const nextIndex = (currentIndex + 1) % sponsorsData.length;
showSponsor(nextIndex);
}

function startAutoPlay() {
if (intervalId) clearInterval(intervalId);
intervalId = setInterval(nextSponsor, 3000);
}

function stopAutoPlay() {
if (intervalId) {
clearInterval(intervalId);
intervalId = null;
}
}

const carousel = document.querySelector('.top-sponsor-carousel');
if (carousel) {
carousel.addEventListener('mouseenter', stopAutoPlay);
carousel.addEventListener('mouseleave', startAutoPlay);
}

container.style.transition = 'opacity 0.3s ease-in-out';

// 初始化第一个赞助者信息
updateSponsorInfo(sponsorsData[0]);

startAutoPlay();

return {
showSponsor,
nextSponsor,
startAutoPlay,
stopAutoPlay
};
}
initRewardCarousel();
//- document.addEventListener("pjax:complete", function() {
//- initRewardCarousel();
//- });
else
.no-sponsors
p 暂无赞助者,成为第一个支持本站的朋友吧!
else
.no-sponsors
p 暂无赞助者数据

结构实现了,下面将该结构插入到对应的位置,可以在当前目录下的index.pug找到对应结构,如下

文件路径:

1
[BlogRoot]\themes\butterfly\layout\includes\widget\index.pug

在代码中插入以下带号的那行代码,注意缩进问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
  else
//- page
!=partial('includes/widget/card_author', {}, {cache: true})
!=partial('includes/widget/card_welcome', {}, {cache: true})
!=partial('includes/widget/card_poem', {}, {cache: true})
+ !=partial('includes/widget/card_rewards', {}, {cache: true})
!=partial('includes/widget/card_top_self', {}, {cache: true})

.sticky_layout
if showToc
include ./card_post_toc.pug
!=partial('includes/widget/card_recent_post', {}, {cache: true})
!=partial('includes/widget/card_ad', {}, {cache: true})
!=partial('includes/widget/card_newest_comment', {}, {cache: true})
!=partial('includes/widget/card_categories', {}, {cache: true})
!=partial('includes/widget/card_tags', {}, {cache: true})
!=partial('includes/widget/card_archives', {}, {cache: true})
!=partial('includes/widget/card_webinfo', {}, {cache: true})
!=partial('includes/widget/card_bottom_self', {}, {cache: true})

引入css样式,新建文件

1
[blogRoot]/source/css/card_rewards.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
donate:
# 支付宝收款码
alipay:
name: 支付宝收款码
image: /config/img/alipay.png
# 微信收款码
wechat:
name: 微信收款码
image: /config/img/wechat.png
thank_img: https://p.liiiu.cn/i/2025/10/10/68e9199157351.webp
# 赞赏页面链接
page_url: /rewards/
# 赞赏者列表
list:
- name: 银河香港
avatar: https://p.liiiu.cn/i/2025/02/26/67bec7d0eb734.webp
website:
date: 2025-03-15
amount: ¥100.00
description: 你我皆是生活银河中的闪耀星辰
- name: 周润发
avatar: https://p.liiiu.cn/i/2025/03/20/67dbe8c6a6221.webp
website: https://blog.zrf.me
date: 2025-08-01
amount: ¥30.00
description: 收录开源,好用的互联网项目~
- name: SXY
avatar: https://p.liiiu.cn/i/2025/10/11/68e93a9ccee45.webp
website:
date: 2025-08-29
amount: ¥10.00
description: 地球与物理专业的大三学生
- name: Ljx
avatar: https://p.liiiu.cn/i/2025/10/09/68e7d8ed2a70b.webp
website: https://blog.ljx.icu/
date: 2025-10-09
amount: ¥8.88
description: 一个无聊无趣的人~
- name: AirTouch
avatar: https://p.liiiu.cn/i/2025/07/18/687a369fc3610.webp
website: https://www.xsl.im/
date: 2025-10-10
amount: ¥18.88
description: 岩间琉璃云间月
- name: 短巷与雨
avatar: https://p.liiiu.cn/i/2024/11/18/673ac90233753.webp
website: https://space.xsl.im/
date: 2025-10-12
amount: ¥28.88
description: 为学日益,为道日损。
- name: 老罗博客
avatar: https://p.liiiu.cn/i/2025/06/01/683bc6062b113.webp
website: https://www.luosir.cn
date: 2025-10-12
amount: ¥8.88
description: 人生就是折腾
- name: 温柔鱼
avatar: https://p.liiiu.cn/i/2025/10/08/68e5e1f17ed12.webp
website: https://blog.vrou.cn
date: 2025-10-17
amount: ¥8.88
description: "NULL"
- name: 不知名朋友
avatar: https://p.liiiu.cn/i/2025/10/11/68e93a9ccee45.webp
website:
date: 2025-10-19
amount: ¥2.00
description: 感谢朋友的赞助~

注意:

* 在配置文件里面也要进行引入改自定义文件 

最后实现hexo三件套 则就有最终效果了

赞赏页面

如果不出所料,侧边栏应该实现了,下面实现赞赏页面,由于不涉及Javascript,所以实现起来可简单多了,还是一样,首先添加Pug页面结构文件,创建[blogRoot]\themes\butterfly\layout\includes\page\rewards.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
#article-container
if top_img === false
h1.page-title= page.title

.reward-page
// 感谢图片
.thank-image
img.no-lightbox(
src=site.data.rewards.donate.thank_img
alt="感谢"
onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.post) + `'`
)

// 收款码区域
.payment-codes
.payment-item.alipay
.payment-content
.payment-image
img(src=site.data.rewards.donate.alipay.image alt=site.data.rewards.donate.alipay.name)
.payment-info
.payment-name= site.data.rewards.donate.alipay.name
//- .payment-desc 支付宝扫一扫
.payment-item.wechat
.payment-content
.payment-image
img(src=site.data.rewards.donate.wechat.image alt=site.data.rewards.donate.wechat.name)
.payment-info
.payment-name= site.data.rewards.donate.wechat.name
//- .payment-desc 微信扫一扫

// 赞赏者列表
.sponsors-list
.sponsors-header
.sponsors-description
p 你的每一份支持都是对我的莫大鼓励

.sponsors-container
if site.data.rewards && site.data.rewards.donate && site.data.rewards.donate.list.length > 0
// 反转列表,因为最新的在最后
- var sortedSponsors = site.data.rewards.donate.list.slice().reverse()

// 计算统计数据
- var totalCount = sortedSponsors.length
- var totalAmount = 0
- sortedSponsors.forEach(function(sponsor) {
- var amount = parseFloat(String(sponsor.amount).replace('¥', ''));
- if (!isNaN(amount)) {
- totalAmount += amount;
- }
- })

each sponsor, index in sortedSponsors
.sponsor-item
if sponsor.website
a.sponsor-card(href=sponsor.website target="_blank" rel="noopener noreferrer" style="text-decoration: none;")
.background-img(
style=`background-image:url(${sponsor.avatar});background-repeat:no-repeat;background-size:cover;background-position:right;mask-image:linear-gradient(to left, transparent, black);-webkit-mask-image:linear-gradient(to left, transparent, black);`
onerror=`this.onerror=null;this.style.backgroundImage='url("` + url_for(theme.error_img.post_page) + `")'`
)
.sponsor-card-left
.sponsor-avatar-title
img.no-lightbox(
src=sponsor.avatar
alt=''
onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.post_page) + `'`
)
.sponsor-name= sponsor.name
.sponsor-desc= sponsor.description
.sponsor-card-right
.sponsor-amount= sponsor.amount
.sponsor-date= sponsor.date ? String(sponsor.date).slice(0, 10) : ''
else
.sponsor-card(style="pointer-events: none; cursor: default;")
.background-img(
style=`background-image:url(${sponsor.avatar});background-repeat:no-repeat;background-size:cover;background-position:right;mask-image:linear-gradient(to left, transparent, black);-webkit-mask-image:linear-gradient(to left, transparent, black);`
onerror=`this.onerror=null;this.style.backgroundImage='url("` + url_for(theme.error_img.post_page) + `")'`
)
.sponsor-card-left
.sponsor-avatar-title
img.no-lightbox(
src=sponsor.avatar
alt=''
onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.post_page) + `'`
)
.sponsor-name= sponsor.name
.sponsor-desc= sponsor.description
.sponsor-card-right
.sponsor-amount= sponsor.amount
.sponsor-date= sponsor.date ? String(sponsor.date).slice(0, 10) : ''

else
.no-sponsors
p 暂无赞赏者数据

// 统计信息
.statistics
.total-count 共计
span.stat-number= totalCount
| 笔打款
.total-amount 累计金额
span.stat-number ¥#{totalAmount.toFixed(2)}

!= page.content

然后修改[blogRoot]\themes\butterfly\layout\page.pug文件,添加上Rewards页面的布局:(➕号的代码,注意格式)

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
extends includes/layout.pug

block content
- const noCardLayout = ['shuoshuo', '404'].includes(page.type) ? 'nc' : ''
- var commentsJsLoad = false

mixin commentLoad
if page.comments !== false && theme.comments.use
- commentsJsLoad = true
!=partial('includes/third-party/comments/index', {}, {cache: true})

#page(class=noCardLayout)
if top_img === false && page.title
page-title= page.title

case page.type
when 'tags'
include includes/page/tags.pug
+commentLoad
when 'link'
include includes/page/flink.pug
+commentLoad
+ when 'rewards'
+ include includes/page/rewards.pug
+ +commentLoad
when 'categories'
include includes/page/categories.pug
+commentLoad
when 'devices'
include includes/page/devices.pug
when 'shuoshuo'
include includes/page/shuoshuo.pug
when 'about'
include includes/page/about.pug
when '404'
include includes/page/404.pug
default
include includes/page/default-page.pug
+commentLoad

删掉加号后自行注意缩进,这里缩进应该挺明显的吧,所以就不多说啦。

页面结构添加完成,下面实现样式,创建文件[blogRoot]\themes\butterfly\source\css\_page\rewards.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
#article-container
.reward-page
// 感谢图片
.thank-image
text-align: center
img
box-shadow: none
height: 200px
.img-alt
display: none

// 收款码区域
.payment-codes
display: flex
justify-content: center
gap: 40px
margin: 30px 0
flex-wrap: wrap

@media screen and (max-width: 768px)
gap: 20px

.payment-item
text-align: center
transition: transform 0.3s ease

&:hover
transform: translateY(-5px)

.payment-content
display: flex
flex-direction: column
align-items: center
gap: 15px

.payment-image
width: 250px
height: 250px
border-radius: 15px
overflow: hidden
box-shadow: 0 5px 20px rgba(0, 0, 0, 0.1)

@media screen and (max-width: 768px)
width: 150px
height: 150px

img
width: 100%
height: 100%
object-fit: cover

.payment-info
.payment-name
font-size: 16px
color: var(--liushen-text)
font-weight: 600
margin-bottom: 5px

// 赞赏者列表
.sponsors-list
margin-bottom: 30px

// 头部区域
.sponsors-header
display: flex
flex-direction: row-reverse

.sponsors-description
p
font-size: 16px
color: var(--liushen-secondtext)
font-style: italic

.sponsors-container
display: flex
flex-wrap: wrap
justify-content: flex-start
margin: -8px // 抵消子元素的 margin

.sponsor-item
margin: 8px // 统一的 margin
// 默认宽度 (1列)
width: "calc(100% - %s)" % (8px * 2)

// 800px 及以上 (2列)
@media screen and (min-width: 800px)
width: "calc(100% / 2 - %s)" % (8px * 2)

// 1200px 及以上 (3列)
@media screen and (min-width: 1200px)
width: "calc(100% / 3 - %s)" % (8px * 2)

background-color: var(--liushen-card-bg)
border: var(--liushen-card-border)
border-radius: 12px
transition: all 0.3s ease
overflow: hidden

&:hover
transform: translateY(-2px)
.background-img
opacity: 0.5
transform: translateX(-50%) translateY(-50%) scale(1.3) !important

.sponsor-avatar-title
opacity: 0 !important
.sponsor-desc
opacity: 1 !important


.sponsor-card
display: flex
justify-content: space-between
height: 52px
width: 100%
align-items: center
padding: 10px
transition: all 0.3s ease
position: relative

.background-img
position: absolute
transform: translateX(-50%) translateY(-50%)
width: 400px
height: 400px
border-radius: 50%
transition: all 0.3s ease
opacity: 0.7
z-index: 0
top: 50%
left: 10px

.sponsor-card-left
display: flex
z-index: 1
align-items: center
gap: 15px
flex: 1
min-width: 0

.sponsor-avatar-title
display: flex
height: 100%
align-items: center
gap: 10px
opacity: 1
transition: all 0.3s ease

img
width: 20px
margin: 0
height: 20px
border-radius: 50%
object-fit: cover

.sponsor-name
font-size: 16px
font-weight: 600
color: var(--liushen-text)
transition: all 0.3s ease
white-space: nowrap
overflow: hidden
text-overflow: ellipsis

.sponsor-desc
position: absolute
transform: translateY(-50%)
z-index: 1
left: 20px
top: 50%
font-size: 16px
font-weight: 600
color: var(--liushen-text)
opacity: 0
transition: all 0.3s ease
white-space: nowrap
overflow: hidden
text-overflow: ellipsis
max-width: calc(100% - 180px)

.sponsor-card-right
text-align: right
display: flex
gap:10px

.sponsor-amount
font-size: 16px
font-weight: 600
line-height: 1
color: var(--default-bg-color)

.sponsor-date
font-size: 16px
line-height: 1
color: var(--liushen-secondtext)

.sponsor-card:hover &
color: rgba(255, 255, 255, 0.8)

.statistics
display: flex
flex-direction: column
gap: 5px
font-size: 16px
color: var(--liushen-text)
margin-top: 20px
.stat-number
font-weight: 600
color: var(--default-bg-color)

// 无数据提示
.no-sponsors
text-align: center
padding: 50px
color: var(--liushen-secondtext)

p
font-size: 16px
margin: 0

// 定义渐入动画
@keyframes fadeInUp
from
opacity: 0
transform: translateY(20px)
to
opacity: 1
transform: translateY(0)

页面渲染结构,页面样式均写完了,我们如何定位该页面的位置呢?在[blogRoot]/source创建Rewards文件夹,内部创建index.md文件,写入以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
---
title: 感谢赞助,每一份都是对我莫大的支持
date: 2018-06-07 22:17:49
type: "rewards"
aside: false

---


感谢每一份慷慨的赞赏,它不仅是支持,更是我前行路上温暖的光。这份心意我已悉心珍藏,会化作动力,努力为大家创造更多价值💗

**【温馨提示】** 如果您在赞赏时,能留下备注或在下方评论区说一声,就能方便我将这份心意与您对应上,为您记录在专属的感谢名单里。期待与您相遇!

注意添加顶部的type: "rewards",这一句是关键!

再次渲染,访问对应目录,应该就可以看见啦,教程完结!

参考文章

butterfly主页瀑布流双栏调整记录

前言

心血来潮,突然想把主页文章卡片改双栏瀑布流,根据官方文档教程,只需要把配置文件中的index_layout: 1改为index_layout: 6即可,但是在我27英寸显示器中成了三栏,更是当文章标题过长时会导致卡片错位情况,这种错位样式在三栏中个人觉得难以欣赏。

问题解决

瀑布流布局(index_layout: 67)的列数是通过 .recent-post-item 的宽度计算控制的。默认配置在超宽屏幕(≥2000px)会显示 3 列。具体的样式在[BlogRoot]\themes\butterfly\source\css\_page\homepage.styl中调整,添加以下+号代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#recent-posts
.recent-post-item
@extend .cardHover
position: relative
overflow: hidden
margin-bottom: 20px

if $indexLayout == 6 || ($indexLayout == 7)
display: inline-block
width: calc(100% / 2 - 8px)
vertical-align: top

+maxWidth768()
width: 100%

+minWidth2000()
width: calc(100% / 3 - 8px)
+ width: calc(100% / 2 - 8px)

if $indexLayout == 1 || ($indexLayout == 2 || ($indexLayout == 3))

注意 : 加上➕号那行代码说明超大屏幕时候也显示两列,如果后续想显示三列则把➕号代码注释或者删掉即可