安知鱼主题细节美化及实用教程

这篇文章是一篇教学文章,在我的网站进行新升级后我会在这里长期更新我所实现的效果。如果你有问题可以在文章末尾的评论区进行提问,我会尽快回复。

请注意,当你改动任何配置文件前请务必进行备份操作,这是一种保障也是一个良好的运维习惯。

1.页脚添加备案号

1.0 效果图

footer_image

1.1 添加 _config.yml 字段

在博客根目录 Hexo 的配置文件(_config.yml)中添加如下新键值(这里要注意,是 Hexo 的配置文件,不是安知鱼主题的配置文件!):

1
2
3
#建议添加在 timezone 下面,你也可以添加在其他位置
icp: 填写 ICP 备案号
gb: 填写公网安备号

1.2 添加、引用 CSS

完成了第 1 步后我们需要为页脚容器进行样式定义。在博客的 /source/ 目录中的 css 文件夹中创建一个名为 coustom.css 的文件(如果你没有 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
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
/*============================= 页脚备案容器开始 blog.yujiay.wang =============================*/

/* 为 #footer-bar 设置相对定位,作为备案容器的定位参考 */
#footer-bar {
/* 为备案信息预留更多空间 */
min-height: 100px;
/* 底部内边距,确保有足够空间 */
padding-bottom: 50px;
}

/* 备案链接容器样式 - 使用ID选择器 */
#beian-links {
/* 定位样式 - 绝对定位在 footer-bar 底部居中 */
position: absolute;
bottom: 15px;
left: 50%;
transform: translateX(-50%);

/* 文本和布局样式 */
display: block;
width: auto;
text-align: center;
white-space: nowrap;

/* 字体样式 */
font-size: 12px;
color: var(--anzhiyu-fontcolor);
line-height: 1.5;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;

/* 确保在最上层 */
z-index: 10;
}

/* 备案链接的样式 */
#beian-links a.footer-bar-link {
color: var(--anzhiyu-fontcolor); /* 链接文字也设置为深色 */
text-decoration: none;
transition: color 0.3s ease; /* 添加过渡效果 */
}

#beian-links a.footer-bar-link:hover {
text-decoration: none;
color: var(--anzhiyu-lighttext); /* 悬停颜色 */
}

/* 移动端适配 */
@media (max-width: 768px) {
#beian-links {
margin: -30px 0;
font-size: 11px;
white-space: normal; /* 允许内容换行 */
text-align: center; /* 确保换行后内容依然居中 */
max-width: 90%;
bottom: 10px;
/* 使整个容器在移动端独占一行,居中效果更稳定 */
display: block;
}

#beian-links a.footer-bar-link {
display: inline-block;
line-height: 1.8;
padding: 2px 4px;
/* 单独成行,可以设置为 block,并赋予宽度或使用其他布局 */
/* display: block; */
}

/* 移动端适配链接样式 */
#beian-links .separator {
display: none !important; /* 上下排列时隐藏竖线分隔符 */
}

}

/* 暗色模式适配 */
[data-theme="dark"] #beian-links a.footer-bar-link {
color: var(--anzhiyu-fontcolor);;
}

[data-theme="dark"] #beian-links a.footer-bar-link:hover {
color: var(--anzhiyu-lighttext);
text-decoration: none;
}

/* 竖线分隔符样式 */
#beian-links .separator {
color: #CCCCCC;
margin: 0 10px;
display: inline-block;
}

/* 暗色模式竖线适配 */
[data-theme="dark"] #beian-links .separator {
color: #666666;
}

/*============================= 页脚备案容器结束 blog.yujiay.wang =============================*/

添加好后记得保存修改的文件。此外还需要在安知鱼主题的配置文件 inject -> head 处进行自定义 css 的引入工作:

1
- <link rel="stylesheet" href="/css/custom.css">

1.3 修改 footer.pug 文件

紧接着我们需要修改模板引擎,这里特别要注意缩进,Pug 的缩进至关重要,它直接决定了代码能否正确运行以及最终生成的HTML结构。如果你不确定缩进是否正确,最简单的办法,就是在 footer.pug 代码的最底部回车两个空行,然后将输入光标删除到最前端(没有缩进)的地方,复制下面的代码,然后将代码的第一行 #footer-wrap 删除掉。删除掉后不要动下面的代码,直接将空行全部删除即可。

1
2
3
4
5
6
7
8
9
#footer-wrap    // 这行最后一定要删除
#beian-links
a.footer-bar-link(href="#修改为你的链接" target="_blank" rel="nofollow noopener")
img.beian-icon(src="#修改为你的图片" alt="公网安备图标" style="width: 14px; height: 14px; vertical-align: -2px; margin-right: 4px;")
| #{config.gb}
span.separator |
a.footer-bar-link(href="https://beian.miit.gov.cn/" target="_blank" rel="nofollow noopener")
img.beian-icon(src="#修改为你的图片" alt="备案图标" style="width: 14px; height: 14px; vertical-align: -2px; margin-right: 4px;")
| #{config.icp}

处理好缩进后我们需要将代码中的链接、图片链接进行替换,替换成为你自己的链接和图片,替换后保存。

1.4 结束语

最后 Hexo 三连(hexo cl && hexo g && hexo s)就可以在页面底部查看效果了,这个 css 进行了响应式适配,移动端也可以很好的展示。

2.添加边栏日历卡片(单卡片风格)

好久不见,I’m back,前段时间去海南出了趟差,又正好赶上大学生们的期末周,手上单子也比较多,没顾得上更新本文,今天终于忙里偷闲,回来更新一下。

今天给大家带来一个我很喜欢的边栏卡片,这个卡片我最早是借鉴一个博主的(但时间太久我找不到他的原文了,希望看到能评论一下,我会链接到原文,感谢这位匿名博主)。网上有很多日历小卡片,但我发现它们都是把 css 单拎出来了,这样我们就需要修改 js、css、yaml and config 四个文件了,但这次介绍这个方法只需要修改三个文件,他将 js 和 css 写到一块了,对于我来说极大的降低了维护成本,而且他的这个风格也很简约。我现在将这个方案分享给大家。

2.0 效果图

BlogCalendarCard

2.1 添加、引用 JavaScript

首先我们需要为日历卡片进行样式逻辑实现和样式定义。在博客的 /source/ 目录中的 js 文件夹中创建一个名为 countdown.js 的文件(如果你没有 js 文件夹可以自行创建一个)。

在新建的 countdown.js 文件中添加以下代码(含样式实现,无需另外添加新 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
const CountdownTimer = (() => {
const config = {
targetDate: "2026-02-17", /* 这里记得每年更新春节日期 */
targetName: "春节",
units: {
day: { text: "今日", unit: "小时" },
week: { text: "本周", unit: "天" },
month: { text: "本月", unit: "天" },
year: { text: "本年", unit: "天" }
}
};

const calculators = {
day: () => {
const hours = new Date().getHours();
return {
remaining: 24 - hours,
percentage: (hours / 24) * 100
};
},
week: () => {
const day = new Date().getDay();
const passed = day === 0 ? 6 : day - 1;
return {
remaining: 6 - passed,
percentage: ((passed + 1) / 7) * 100
};
},
month: () => {
const now = new Date();
const total = new Date(now.getFullYear(), now.getMonth() + 1, 0).getDate();
const passed = now.getDate() - 1;
return {
remaining: total - passed,
percentage: (passed / total) * 100
};
},
year: () => {
const now = new Date();
const start = new Date(now.getFullYear(), 0, 1);
const total = 365 + (now.getFullYear() % 4 === 0 ? 1 : 0);
const passed = Math.floor((now - start) / 86400000);
return {
remaining: total - passed,
percentage: (passed / total) * 100
};
}
};

function updateCountdown() {
const elements = ['eventName', 'eventDate', 'daysUntil', 'countRight']
.map(id => document.getElementById(id));

if (elements.some(el => !el)) return;

const [eventName, eventDate, daysUntil, countRight] = elements;
const now = new Date();
const target = new Date(config.targetDate);

eventName.textContent = config.targetName;
eventDate.textContent = config.targetDate;
daysUntil.textContent = Math.round((target - now.setHours(0,0,0,0)) / 86400000);

countRight.innerHTML = Object.entries(config.units)
.map(([key, {text, unit}]) => {
const {remaining, percentage} = calculators[key]();
return `
<div class="cd-count-item">
<div class="cd-item-name">${text}</div>
<div class="cd-item-progress">
<div class="cd-progress-bar" style="width: ${percentage}%; opacity: ${percentage/100}"></div>
<span class="cd-percentage ${percentage >= 46 ? 'cd-many' : ''}">${percentage.toFixed(2)}%</span>
<span class="cd-remaining ${percentage >= 60 ? 'cd-many' : ''}">
<span class="cd-tip">还剩</span>${remaining}<span class="cd-tip">${unit}</span>
</span>
</div>
</div>
`;
}).join('');
}

function injectStyles() {
const styles = `
.card-countdown .item-content {
display: flex;
}
.cd-count-left {
position: relative;
display: flex;
flex-direction: column;
margin-right: 0.8rem;
line-height: 1.5;
align-items: center;
justify-content: center;
}
.cd-count-left .cd-text {
font-size: 14px;
}
.cd-count-left .cd-name {
font-weight: bold;
font-size: 18px;
}
.cd-count-left .cd-time {
font-size: 30px;
font-weight: bold;
color: var(--anzhiyu-main);
}
.cd-count-left .cd-date {
font-size: 12px;
opacity: 0.6;
}
.cd-count-left::after {
content: "";
position: absolute;
right: -0.8rem;
width: 2px;
height: 80%;
background-color: var(--anzhiyu-main);
opacity: 0.5;
}
.cd-count-right {
flex: 1;
margin-left: .8rem;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.cd-count-item {
display: flex;
flex-direction: row;
align-items: center;
height: 24px;
}
.cd-item-name {
font-size: 14px;
margin-right: 0.8rem;
white-space: nowrap;
}
.cd-item-progress {
position: relative;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
height: 100%;
width: 100%;
border-radius: 8px;
background-color: var(--anzhiyu-background);
overflow: hidden;
}
.cd-progress-bar {
height: 100%;
border-radius: 8px;
background-color: var(--anzhiyu-main);
}
.cd-percentage,
.cd-remaining {
position: absolute;
font-size: 12px;
margin: 0 6px;
transition: opacity 0.3s ease-in-out, transform 0.3s ease-in-out;
}
.cd-many {
color: #fff;
}
.cd-remaining {
opacity: 0;
transform: translateX(10px);
}
.card-countdown .item-content:hover .cd-remaining {
transform: translateX(0);
opacity: 1;
}
.card-countdown .item-content:hover .cd-percentage {
transform: translateX(-10px);
opacity: 0;
}
`;

const styleSheet = document.createElement("style");
styleSheet.textContent = styles;
document.head.appendChild(styleSheet);
}

let timer;
const start = () => {
injectStyles();
updateCountdown();
timer = setInterval(updateCountdown, 600000);
};

['pjax:complete', 'DOMContentLoaded'].forEach(event => document.addEventListener(event, start));
document.addEventListener('pjax:send', () => timer && clearInterval(timer));

return { start, stop: () => timer && clearInterval(timer) };
})();

添加好后记得保存修改的文件。此外还需要在安知鱼主题的配置文件 inject -> bottom 处进行自定义 js 的引入工作:

1
- <script src="/js/countdown.js"></script>

2.2 添加 widget.yml 文件

完成了步骤 2.1 后我们来为小卡片添加 html 倒计时器组件。在博客的 /source/ 目录中的 _data 文件夹中创建一个名为 widget.yml 的文件(_data 文件夹是一个数据存储目录,用来存放网站的各种结构化数据。同上,如果你没有 _data 文件夹可以自行创建一个)。目录和文件创建好后,在 widget.yml 文件中添加以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
top:
- class_name: card-countdown
id_name:
name:
icon:
html: |
<div class="cd-count-left">
<span class="cd-text">距离</span>
<span class="cd-name" id="eventName"></span>
<span class="cd-time" id="daysUntil"></span>
<span class="cd-date" id="eventDate"></span>
</div>
<div id="countRight" class="cd-count-right"></div>

1.3 结束语

最后 Hexo 三连(hexo cl && hexo g && hexo s)就可以在页面侧边栏查看效果了。

但值得注意的是,步骤 2.1 中的 targetDate: "2026-02-17", 这部分(第 3 行)js 代码每年需要手动更新一下日期,如果忘记更新的话,年月日倒计时功能不受影响,只是距离春节天数会变为负数。

最后最后,欢迎大家在评论区给予指正,让我们共同打造快节奏时代不受算法牵制的属于我们自己的小空间!