记录这次网站更新

我在生活中,很喜欢记录东西。最初用的Gnotes(国内叫“随笔记”),在毕业后第一年,也许是因为手机本地没迁移上云,我丢失了从高中到工作前大概三千条笔记。那时候的我,特别悲伤。工作后,我开始逐步的转向了“印象笔记”进行记录。也是从那时起,心里一直有个念头,就是自己要搞个完全属于自己的记录平台。

这个网站最初的雏形,其实是我为当时喜欢的人搭建的一个小站点,用来分享一些日常和有趣的东西。23年初,我重新用Hexo框架 + Butterfly主题搭建了现在这个博客。开始分享一些工作、技术相关的内容。

就这样,简单的运行也快三年了,因为我本身不是搞前端的,也没有增加其他花里胡哨的玩意,没出什么问题。偶尔遇到小的bug,上网查一查也能解决。

为什么会有这次更新

这次更新,某种程度上是对过往,一个阶段性的整理。

一方面,是我逐渐放下了很多过去的东西;
另一方面,我每年都会读一些书、看一些电影,却一直缺少一个系统化的记录方式。

之前我尝试过使用 hexo-douban 来管理书影音,但用下来并不顺手,可控性也比较差。与其适应工具,不如重新做一套符合自己习惯的,然后就在这次升级给实现了。

核心实现思路

这次主要做了几件事:

  • 升级 Hexo 及 Butterfly 主题到最新版本

  • 新增 Navidrome 作为个人音乐平台

  • 重构书单和影单页面

  • 支持分页展示,并根据个人评分显示不同样式的阅后笔记

  • 评论系统更新

  • 修改了一些背景图

整体思路并不复杂:下面是我结合AI重新重构书单和影单页面的思路。

数据层:YAML 结构存储

Hexo 官方推荐使用 _data 目录来管理结构化数据。
我将每一本书 / 每一部电影,都作为一个独立条目存放在 books.yml 或 movies.yml 中:

1
2
3
4
5
6
7
8
# _data/books.yml
- title: 人间失格
author: "[日] 太宰治"
publisher: 武汉出版社
rate: 5
cover: /img/book_pic/人间失格.jpg
note: >
有些人并非不合群,只是太早看清了世界。

其中分别描述了书名、作者、出版社、评分、封面、笔记信息。以后每看完一本书,只需要往YAML里加一条记录即可。

后端:自定义 Generator 分页

为了实现可分页的书单和影单页面,我编写了一个自定义 Generator,通过 JS 控制分页逻辑。
代码片段:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
for (let pageNum = 1; pageNum <= totalPages; pageNum++) {
const startIdx = (pageNum - 1) * itemsPerPage
const endIdx = startIdx + itemsPerPage
const paginatedBooks = books.slice(startIdx, endIdx)

// 为第一页生成根路径 /books/,其他页生成 /books/page/2/ 等
let path = pageNum === 1 ? 'books/index.html' : `books/page/${pageNum}/index.html`

pages.push({
path: path,
data: {
books: books, // 所有书籍
paginatedBooks: paginatedBooks, // 当前页书籍
currentPage: pageNum,
totalPages: totalPages,
itemsPerPage: itemsPerPage,
__page: true // 标记为页面类型
},
layout: ['books']
})
}

前端:Pug 模板渲染

页面层使用 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
// layout/books.pug
extends includes/layout

block content
.books-page-wrapper
.books-header
h2 我的书单
p
em 这明显是个书池,但我正努力让它变成海洋

// 从自定义路由获取数据
- const books = page.books || []
- const paginatedBooks = page.paginatedBooks || []
- const currentPage = page.currentPage || 1
- const totalPages = page.totalPages || 1
- const itemsPerPage = page.itemsPerPage || 10

each book in paginatedBooks
.book-item
.book-divider(style="border-top: 1px solid #000;")

.book-card
.book-main
img.book-cover(
src=book.cover
width="100"
height="122"
style="float: left; margin: 5px 10px 5px 0;"
)
.book-text
strong 书名:
| #{book.title}
br
strong 作者:
// ... 其他字段

// 评分驱动的笔记样式
if book.note
-
let noteClass = 'note-low'
if (book.rate >= 8) noteClass = 'note-high'
else if (book.rate >= 6) noteClass = 'note-mid'

.book-note(
class=noteClass
style="clear: both;"
)
| #{book.note}

评分越高,颜色越鲜艳。
好看的书和电影,本就值得被“看见”。

样式层:CSS 变量化设计

自定义样式统一放在 custom.css 中,并通过config.yml的 inject 方式引入

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

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
/* source/css/custom.css */
.books-page-wrapper,.movies-page-wrapper {
--note-high-color: #e91e63;
--note-high-bg: rgba(233, 30, 99, 0.12);

--note-mid-color: #ff9800;
--note-mid-bg: rgba(255, 152, 0, 0.15);

--note-low-color: #607d8b;
--note-low-bg: rgba(96, 125, 139, 0.12);
}

/* 高分 */
.book-note.note-high,
.movie-note.note-high { /* 添加电影笔记的样式 */
color: var(--note-high-color);
background-color: var(--note-high-bg);
}

/* 中分 */
.book-note.note-mid,
.movie-note.note-mid { /* 添加电影笔记的样式 */
color: var(--note-mid-color);
background-color: var(--note-mid-bg);
}

/* 低分 / 默认 */
.book-note.note-low,
.movie-note.note-low { /* 添加电影笔记的样式 */
color: var(--note-low-color);
background-color: var(--note-low-bg);
}

后续如果想整体调整风格,只需要改动变量即可,维护成本也会更低。

写在最后

这次更新本身并不算复杂,主要是书影音界面的升级。但对我来说是一次心境的蜕变,沉潜不喧,轻捷向前。

当然无论是书、电影,还是生活里那些零碎的想法,
能被安放在一个长期稳定、完全可控的地方,本身就是一种安心。

如果你也在用 Hexo,或者正好在折腾类似的页面,希望这次记录能对你有所帮助。