😶🌫️ 本页面在移动端下显示问题比较大,是使用 dataviewjs 渲染的,与 AI 斗智斗勇了好久也没解决,但页面是可以正常跳转的,大家尽量使用电脑来查看。
读书清单
const folder = "阅读/读书清单";
// 1. 拉取所有符合条件的页面,并按创建时间倒序
let pages = dv.pages(`"${folder}"`)
.filter(p => p.file.name !== "")
.filter(p => p["dg-publish"] === true)
.sort(p => p.file.ctime, 'desc');
// 2. 按 年-月 分组
let monthGroups = {};
for (let p of pages) {
let dt = p.file.ctime;
let key = `${dt.year}-${dt.month}`;
if (!monthGroups[key]) monthGroups[key] = [];
monthGroups[key].push(p);
}
// 3. 输出
for (let monthKey of Object.keys(monthGroups)) {
// 月标题
let [year, month] = monthKey.split('-');
dv.paragraph(`**${year} 年 ${month} 月:**`);
let groupPages = monthGroups[monthKey];
// 确定当天列表的顺序(按创建时间排序已在 pages 中)
let days = [...new Set(groupPages.map(p => p.file.ctime.day))];
for (let day of days) {
dv.paragraph(`\n${day} 号:`);
// 当天的文章,按最后修改时间倒序
let dayPages = groupPages
.filter(p => p.file.ctime.day === day)
.sort((a, b) => b.file.mtime.ts - a.file.mtime.ts);
for (let p of dayPages) {
let filepath = p.file.path.replace(/\$/, "");
let link = `《${p.file.name}》`;
let m = p.file.mtime;
let modified = `${m.year}.${m.month}.${m.day}`;
dv.paragraph(`${link} 『最后一次修改时间:${modified}』`);
}
}
dv.paragraph(""); // 月份之间空行
}
图书书库
// 1. 根目录
const root = "阅读/书库";
// 2. 原始分类映射(末尾不带斜杠)
const pathArray = {
inbox: "0_inbox",
马克思主义: "A_马克思主义",
世界哲学: "B_哲学/B1_世界哲学",
中国哲学: "B_哲学/B2_中国哲学",
心理学: "B_哲学/B84_心理学",
社会科学: "C_社会科学总论",
政治法律: "D_政治法律",
军事: "E_军事",
经济学: "F_经济/F0_经济学",
农业经济: "F_经济/F3_农业经济",
工业经济: "F_经济/F4_工业经济",
金融经济: "F_经济/F8_金融",
文教科体: "G_文教科体",
语言文字: "H_语言文字",
世界文学: "I_文学/I1_世界文学",
小说: "I_文学/I2_中国文学/小说",
诗词: "I_文学/I2_中国文学/诗词",
儿童文学: "I_文学/I2_中国文学/儿童文学",
艺术: "J_艺术",
世界历史: "K_历史地理/K1_世界史",
中国历史: "K_历史地理/K2_中国史",
人物传记: "K_历史地理/K81_传记",
地理: "K_历史地理/地理",
自然科学: "N_自然科学总论",
数学: "O_数理化/O1_数学",
物理: "O_数理化/O4_物理学",
天文地球: "P_天文地球",
生物: "Q_生物科学",
医药卫生: "R_医药卫生",
农业: "S_农业科学",
电信: "T_工业技术/TN_电信技术",
计算机: "T_工业技术/TP_计算机技术",
交通: "U_交通运输",
航空航天: "V_航空航天",
环境安全: "X_环境安全",
综合图书: "Z_综合图书"
};
// 3. 构建前缀分组映射
let groupMap = {}; // prefix -> Set of pages
for (let subpath of Object.values(pathArray)) {
// 前缀 = 第一个斜杠前的部分
let prefix = subpath.split('/')[0];
if (!groupMap[prefix]) groupMap[prefix] = new Set();
// 查询该子路径下所有带 #书籍 且 dg-publish 为 true 的文件
const folder = `${root}/${subpath}`;
let pages = dv.pages(`"${folder}" and #书籍`)
.filter(p => p["dg-publish"] === true);
for (let p of pages) {
groupMap[prefix].add(p);
}
}
// 4. 按字母顺序遍历每个前缀分组
for (let prefix of Object.keys(groupMap).sort()) {
const pages = Array.from(groupMap[prefix]);
if (!pages.length) continue; // 若无内容则跳过
// 4.1 解析字母与分类名
const [letter, rawName] = prefix.split('_');
const className = rawName; // 如 "马克思主义"、"哲学" 等
// 4.2 区块标题
dv.header(3, `${letter} 类:${className} 分区`);
// 4.3 按文件名排序
pages.sort(p => p.file.name);
// 4.4 渲染表格
dv.table(
["书名", "标签", "作者", "ISBN"],
pages.map(p => {
const fileKey = p.file.path.replace(/\$/, "");
const link = `《${p.file.name}》`;
let tags = "";
if (Array.isArray(p.tags)) {
tags = p.tags.map(t => `#${t}`).join("、");
} else if (p.tags) {
tags = `#${p.tags}`;
}
return [
link,
tags,
p.作家 ?? "",
p.ISBN ?? ""
];
})
);
}