I tried using dataviewjs to aggregate my journal by week into the weekly journal generated by the Calander plug-in, and I succeeded, pretty much!
Using this as a weekly diary template, you can click on the calander plugin to automatically summarize your weekly diary to the weekly diary page.
// Weekly 模板 - 展示本周 Dairy 目录下的笔记(基于文件名日期)
// 获取当前文件名(格式应为 2025-W11 这样的周标识)
const weekTitle = dv.current().file.name;
// 解析周标识,获取年份和周数
const match = weekTitle.match(/(\d{4})-W(\d{1,2})/);
if (!match) {
dv.el("div", "❌ 错误:文件名格式应为 YYYY-WXX(如 2025-W11)", {
cls: "error-message",
attr: { style: "color: #e74c3c; padding: 10px; border-left: 3px solid #e74c3c; background-color: #fadbd8;" }
});
return;
}
const year = parseInt(match[1]);
const week = parseInt(match[2]);
// 计算本周的开始日期和结束日期
function getDateOfWeek(weekNum, year) {
const jan4 = new Date(year, 0, 4);
const jan4Day = jan4.getDay() || 7;
const firstMonday = new Date(year, 0, 4 - jan4Day + 1);
const targetMonday = new Date(firstMonday);
targetMonday.setDate(firstMonday.getDate() + (weekNum - 1) * 7);
const targetSunday = new Date(targetMonday);
targetSunday.setDate(targetMonday.getDate() + 6);
return {
start: targetMonday,
end: targetSunday
};
}
const weekDates = getDateOfWeek(week, year);
const weekStart = weekDates.start;
const weekEnd = weekDates.end;
// 格式化日期为 YYYY-MM-DD
function formatDate(date) {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
return `${year}-${month}-${day}`;
}
// 生成本周的日期范围(YYYY-MM-DD 格式)
const dateRange = [];
const currentDate = new Date(weekStart);
while (currentDate <= weekEnd) {
dateRange.push(formatDate(currentDate));
currentDate.setDate(currentDate.getDate() + 1);
}
// 输出周信息 - 使用自定义样式的标题
dv.el("h1", `🗓️ 第 ${week} 周总结`, {
attr: {
style: "color: #3498db; border-bottom: 2px solid #3498db; padding-bottom: 8px; margin-bottom: 20px;"
}
});
dv.el("div", `📅 ${formatDate(weekStart)} 至 ${formatDate(weekEnd)}`, {
attr: {
style: "font-size: 1.2em; color: #7f8c8d; margin-bottom: 20px;"
}
});
// 获取 Dairy 目录下本周的所有文件(基于文件名匹配)
const dairyNotes = dv.pages('"Dairy"')
.filter(page => {
const filenameMatch = page.file.name.match(/^(\d{4}-\d{2}-\d{2})/);
if (!filenameMatch) return false;
const dateStr = filenameMatch[1];
return dateRange.includes(dateStr);
})
.sort(page => page.file.name);
// 检查是否有笔记
if (dairyNotes.length === 0) {
dv.el("div", "📝 本周没有日记记录", {
cls: "empty-notes",
attr: {
style: "text-align: center; padding: 20px; color: #95a5a6; font-style: italic; border: 1px dashed #bdc3c7; border-radius: 5px;"
}
});
} else {
// 显示统计信息
dv.el("div", `📊 本周共有 ${dairyNotes.length} 条日记记录`, {
cls: "stats",
attr: {
style: "background-color: #e8f4f8; padding: 10px 15px; border-radius: 5px; margin-bottom: 20px; font-weight: bold; color: #2980b9;"
}
});
// 按日期处理每个笔记
for (const note of dairyNotes) {
// 从文件名提取日期
const dateStr = note.file.name.match(/^(\d{4}-\d{2}-\d{2})/)[1];
const date = new Date(dateStr);
const dayNames = ["周日", "周一", "周二", "周三", "周四", "周五", "周六"];
const dayName = dayNames[date.getDay()];
// 显示日期作为二级标题
const headerContainer = dv.el("div", "", {
cls: "date-header",
attr: {
style: "margin-top: 30px; margin-bottom: 10px; background-color: #f5f5f5; border-radius: 5px; padding: 8px 15px; display: flex; align-items: center;"
}
});
// 添加日期图标
dv.el("span", "📆", {
attr: { style: "margin-right: 10px; font-size: 1.2em;" },
container: headerContainer
});
// 添加日期链接
const linkSpan = dv.el("span", "", { container: headerContainer });
dv.el("a", dateStr, {
attr: {
href: note.file.path,
style: "font-size: 1.2em; font-weight: bold; color: #16a085; text-decoration: none;"
},
container: linkSpan
});
// 添加星期几
dv.el("span", ` ${dayName}`, {
attr: { style: "margin-left: 10px; color: #7f8c8d;" },
container: headerContainer
});
// 加载笔记内容
const content = await dv.io.load(note.file.path);
// 移除 YAML 前置元数据(如果有)
let cleanContent = content;
if (content.startsWith('---')) {
const endOfYaml = content.indexOf('---', 3);
if (endOfYaml > 0) {
cleanContent = content.substring(endOfYaml + 3).trim();
}
}
// 显示笔记内容,带样式的卡片
dv.el("div", cleanContent, {
cls: "note-content",
attr: {
style: "padding: 15px; background-color: #ffffff; border-left: 3px solid #2ecc71; border-radius: 0 5px 5px 0; margin-bottom: 5px; box-shadow: 0 1px 3px rgba(0,0,0,0.1);"
}
});
// 添加分隔线
dv.el("div", "", {
cls: "separator",
attr: { style: "height: 1px; background: linear-gradient(to right, transparent, #e0e0e0, transparent); margin: 25px 0;" }
});
}
}