Obsidian 自动化 Cookbook
将 QuickAdd(快速输入)、Templater(模板引擎)和 Dataview(数据查询)三大插件组合使用,可以实现强大的自动化工作流。本文提供 12 个实战配方,覆盖日常知识管理的核心场景。
三件套各自职责
| 插件 | 核心职责 | 在自动化中的角色 |
|---|---|---|
| QuickAdd | 快速捕获输入 | 入口:一键创建笔记、快速填写属性 |
| Templater | 模板渲染与脚本 | 引擎:动态生成内容、执行逻辑 |
| Dataview | 数据查询与展示 | 输出:自动汇总、统计、仪表板 |
配方 1:一键创建读书笔记
目标:输入书名,自动创建包含标准结构的读书笔记。
Templater 模板
markdown
<%*
// templates/book-note.md
const title = await tp.system.prompt("书名");
const author = await tp.system.prompt("作者");
const category = await tp.system.suggester(
["技术", "商业", "文学", "心理学", "历史", "其他"],
["技术", "商业", "文学", "心理学", "历史", "其他"]
);
-%>
---
title: "《<% title %>》"
author: "<% author %>"
category: "<% category %>"
status: to-read
rating:
started_date:
finished_date:
total_pages:
current_page: 0
tags: [book, <% category %>]
created: <% tp.date.now("YYYY-MM-DD") %>
---
# 《<% title %>》
> 作者: <% author %>
## 📖 基本信息
| 项目 | 内容 |
|------|------|
| 状态 | 📋 待阅读 |
| 分类 | <% category %> |
| 开始日期 | — |
| 完成日期 | — |
| 当前页数 | 0 |
## 💡 核心观点
-
## 📝 章节笔记
### 第一章
### 第二章
## ✍️ 读后感
## 🔗 相关书籍
```dataview
LIST
FROM "books"
WHERE author = "<% author %>" AND file.name != this.file.name
SORT rating DESC
### QuickAdd 配置
1. 创建 QuickAdd Capture → 选择模板文件
2. 设置文件名格式:`books/{{DATE:YYYY-MM-DD}}-{{VALUE}}`
3. 设置保存路径:`books/`
## 配方 2:每日晨间日记自动化
**目标**:每天早上一键生成包含天气、待办、回顾的晨间日记。
### Templater 模板
```markdown
<%*
// templates/morning-journal.md
const weather = await tp.system.suggester(
["☀️ 晴天", "⛅ 多云", "🌧️ 雨天", "❄️ 雪天", "🌫️ 雾天"],
["sunny", "cloudy", "rainy", "snowy", "foggy"]
);
const mood = await tp.system.suggester(
["😀 很好", "🙂 不错", "😐 一般", "😕 不好", "😢 糟糕"],
[5, 4, 3, 2, 1]
);
-%>
---
type: daily-journal
date: <% tp.date.now("YYYY-MM-DD") %>
weather: <% weather %>
mood: <% mood %>
tags: [journal, morning]
---
# 📅 <% tp.date.now("YYYY年MM月DD日 dddd") %>
## 🌤️ 今日概况
- 天气:<% weather %>
- 心情:<% mood %>
## 🎯 今日目标
```dataviewjs
// 自动拉取今日待办
const today = dv.date("today");
const tasks = dv.pages('"tasks"')
.file.tasks
.where(t => !t.completed)
.where(t => t.due == today || t.text.includes(today.toFormat("yyyy-MM-dd")))
.limit(5);
if (tasks.length > 0) {
dv.taskList(tasks, false);
} else {
dv.paragraph("今日暂无待办任务,享受轻松的一天!");
}📝 晨间反思
昨日回顾
今日感恩
今日重点
📊 本周数据
dataviewjs
const weekStart = dv.date("today").minus({ days: dv.date("today").weekday - 1 });
const weekNotes = dv.pages('"daily"')
.where(p => p.file.day >= weekStart && p.file.day <= dv.date("today"))
.sort(p => p.file.day);
dv.table(
["日期", "心情", "天气", "笔记数"],
weekNotes.map(p => [
p.file.link,
p.mood ? "⭐".repeat(p.mood) : "—",
p.weather || "—",
p.file.tasks.length
])
);🔗 昨日日记
dataviewjs
const yesterday = dv.date("today").minus({ days: 1 });
const yd = dv.pages('"daily"')
.where(p => p.file.day == yesterday);
if (yd.length > 0) {
dv.paragraph("📝 " + yd[0].file.link);
} else {
dv.paragraph("昨日无日记记录");
}
## 配方 3:会议记录自动生成
**目标**:输入会议主题和参会人,自动生成会议记录模板并创建关联任务。
### QuickAdd Macro 模板
```markdown
<%*
// templates/meeting-note.md
const topic = await tp.system.prompt("会议主题");
const attendees = await tp.system.prompt("参会人员(逗号分隔)");
const attendeeList = attendees.split(",").map(a => a.trim());
// 创建会议笔记
const fileName = `会议-${tp.date.now("YYYYMMDD-HHmm")}-${topic}`;
await tp.file.rename(fileName);
await tp.file.move(`meetings/${fileName}`);
-%>
---
type: meeting
topic: "<% topic %>"
attendees: [<% attendeeList.map(a => `"${a}"`).join(", ") %>]
date: <% tp.date.now("YYYY-MM-DD") %>
time: <% tp.date.now("HH:mm") %>
status: draft
tags: [meeting]
---
# 📋 会议:<% topic %>
## 📝 基本信息
| 项目 | 内容 |
|------|------|
| 日期 | <% tp.date.now("YYYY-MM-DD") %> |
| 时间 | <% tp.date.now("HH:mm") %> |
| 参会人 | <% attendees %> |
| 记录人 | [[<% tp.frontmatter.author || "我" %>] |
## 📋 议程
1.
## 💬 讨论内容
### 议题 1
**讨论要点:**
-
**决议:**
-
### 议题 2
## ✅ 行动项
- [ ]
- [ ]
- [ ]
## 📎 附件
-
## 🔗 相关项目
```dataview
LIST
FROM "projects"
WHERE contains(file.outlinks, this.file.link)
SORT file.name📤 会后任务
dataviewjs
// 自动从会议笔记中提取任务并汇总
const tasks = dv.current().file.tasks;
if (tasks.length > 0) {
dv.header(3, "📋 本次会议行动项");
dv.taskList(tasks.where(t => !t.completed), false);
const completed = tasks.where(t => t.completed);
if (completed.length > 0) {
dv.header(4, "✅ 已完成");
dv.taskList(completed, false);
}
}
## 配方 4:项目状态看板自动更新
**目标**:Dataview 自动从项目笔记中提取状态,生成看板式概览。
```dataviewjs
// project-dashboard.md
const projects = dv.pages('"projects"')
.where(p => p.status);
const statuses = {
"🟢 进行中 (active)": projects.where(p => p.status === "active"),
"🟡 暂停 (paused)": projects.where(p => p.status === "paused"),
"🔵 规划中 (planning)": projects.where(p => p.status === "planning"),
"✅ 已完成 (done)": projects.where(p => p.status === "done"),
"📦 已归档 (archived)": projects.where(p => p.status === "archived")
};
dv.header(2, "📊 项目看板");
for (let [label, group] of Object.entries(statuses)) {
if (group.length === 0) continue;
dv.header(3, `${label} — ${group.length} 个项目`);
dv.table(
["项目", "优先级", "截止日期", "进度", "负责"],
group.sort(p => p.priority || 99).map(p => {
const daysLeft = p.deadline
? Math.floor((dv.date(p.deadline) - dv.date("today")).days)
: null;
return [
p.file.link,
p.priority ? `P${p.priority}` : "—",
p.deadline ? `${p.deadline} (${daysLeft}天)` : "—",
p.progress ? `${p.progress}%` : "—",
p.assignee || "—"
];
})
);
}
// 统计概览
dv.header(3, "📈 统计概览");
dv.table(
["指标", "数值"],
[
["项目总数", projects.length],
["进行中", projects.where(p => p.status === "active").length],
["本月到期", projects.where(p => p.deadline && dv.date(p.deadline).month == dv.date("today").month).length],
["已逾期", projects.where(p => p.deadline && dv.date(p.deadline) < dv.date("today") && p.status !== "done").length]
]
);配方 5:周报自动生成
目标:一键生成本周工作周报,包含任务完成情况、新增笔记和项目进展。
Templater 模板
markdown
<%*
// templates/weekly-report.md
const today = tp.date.now("YYYY-MM-DD");
const weekNum = tp.date.now("ww");
await tp.file.rename(`周报-W${weekNum}-${today}`);
await tp.file.move(`reports/weekly/${tp.file.title}`);
-%>
---
type: weekly-report
week: <% tp.date.now("ww") %>
date: <% today %>
period: <% tp.date.now("YYYY-[W]ww") %>
tags: [report, weekly]
---
# 📋 周报 — <% tp.date.now("YYYY年MM月DD日") %> (W<% weekNum %>)
## 📊 本周概览
```dataviewjs
const today = dv.date("today");
const weekStart = today.minus({ days: today.weekday - 1 });
const weekEnd = weekStart.plus({ days: 6 });
// 新增笔记
const newNotes = dv.pages()
.where(p => p.file.ctime >= weekStart && p.file.ctime <= weekEnd.plus({days: 1}))
.where(p => !p.file.path.startsWith("Templates"))
.where(p => !p.file.path.startsWith("reports"));
// 完成任务
const completedTasks = dv.pages()
.file.tasks
.where(t => t.completed)
.where(t => t.completion >= weekStart && t.completion <= weekEnd.plus({days: 1}));
// 未完成任务
const pendingTasks = dv.pages()
.file.tasks
.where(t => !t.completed);
dv.table(
["📊 指标", "数值"],
[
["📝 新增笔记", newNotes.length],
["✅ 完成任务", completedTasks.length],
["📋 待办任务", pendingTasks.length],
["📁 活跃项目", dv.pages('"projects"').where(p => p.status == "active").length]
]
);✅ 本周完成任务
dataviewjs
const today = dv.date("today");
const weekStart = today.minus({ days: today.weekday - 1 });
const weekEnd = weekStart.plus({ days: 6 });
const tasks = dv.pages()
.file.tasks
.where(t => t.completed)
.where(t => t.completion >= weekStart && t.completion <= weekEnd.plus({days: 1}));
if (tasks.length > 0) {
dv.taskList(tasks, true);
} else {
dv.paragraph("本周无已完成任务");
}📝 本周新增笔记
dataviewjs
const today = dv.date("today");
const weekStart = today.minus({ days: today.weekday - 1 });
const weekEnd = weekStart.plus({ days: 6 });
const notes = dv.pages()
.where(p => p.file.ctime >= weekStart && p.file.ctime <= weekEnd.plus({days: 1}))
.where(p => !p.file.path.startsWith("Templates"))
.where(p => !p.file.path.startsWith("reports"))
.sort(p => p.file.ctime, 'desc');
dv.table(
["笔记", "创建时间", "标签"],
notes.map(p => [
p.file.link,
p.file.ctime.toFormat("MM-dd HH:mm"),
p.tags ? p.tags.join(", ") : "—"
])
);📋 下周计划
- [ ]
- [ ]
- [ ]
💡 反思与总结
本周亮点
待改进
下周重点
## 配方 6-12:更多自动化配方
### 配方 6:自动标签建议
```dataviewjs
// 根据笔记内容自动推荐标签
const content = dv.current().file.content;
const keywords = {
"技术": ["代码", "编程", "API", "框架", "开发", "bug", "部署"],
"学习": ["课程", "教程", "学习", "笔记", "复习", "考试"],
"工作": ["会议", "项目", "汇报", "截止", "客户", "需求"],
"生活": ["旅行", "美食", "运动", "健康", "家庭"]
};
const suggestions = [];
for (let [tag, words] of Object.entries(keywords)) {
const matches = words.filter(w => content.includes(w));
if (matches.length > 0) {
suggestions.push({ tag, count: matches.length, words: matches });
}
}
if (suggestions.length > 0) {
dv.header(4, "🏷️ 建议标签");
dv.table(
["标签", "匹配关键词数", "关键词"],
suggestions.sort((a, b) => b.count - a.count).map(s =>
[`#${s.tag}`, s.count, s.words.join(", ")]
)
);
}配方 7:过期笔记提醒
dataviewjs
// 检测超过 90 天未修改的笔记
const threshold = dv.date("today").minus({ days: 90 });
const stale = dv.pages()
.where(p => p.file.mtime < threshold)
.where(p => !p.file.path.startsWith("Templates"))
.where(p => !p.file.path.startsWith("Archive"))
.sort(p => p.file.mtime)
.limit(20);
if (stale.length > 0) {
dv.header(3, `⚠️ ${stale.length} 篇笔记超过 90 天未更新`);
dv.table(
["笔记", "最后修改", "天数"],
stale.map(p => [
p.file.link,
p.file.mtime.toFormat("yyyy-MM-dd"),
Math.floor((dv.date("today") - dv.date(p.file.mtime)).days)
])
);
}配方 8:知识图谱密度分析
dataviewjs
// 分析笔记的链接密度
const pages = dv.pages()
.where(p => !p.file.path.startsWith("Templates"))
.where(p => !p.file.path.startsWith("Archive"));
const stats = pages.map(p => ({
name: p.file.name,
links: p.file.outlinks.length,
backlinks: p.file.inlinks.length,
total: p.file.outlinks.length + p.file.inlinks.length
})).sort((a, b) => b.total - a.total).slice(0, 15);
dv.header(3, "🔗 链接最密集的笔记 Top 15");
dv.table(
["笔记", "出链", "入链", "总计"],
stats.map(s => [s.name, s.links, s.backlinks, s.total])
);
// 孤岛笔记(无链接)
const orphans = pages.where(p => p.file.outlinks.length === 0 && p.file.inlinks.length === 0);
dv.header(3, `🏝️ 孤岛笔记 (${orphans.length})`);
if (orphans.length > 0) {
dv.list(orphans.limit(10).file.link);
}配方 9:批量属性补全
使用 Templater 批量为笔记添加缺失的属性:
javascript
<%*
// 批量为 books/ 下的笔记添加缺失属性
const files = app.vault.getMarkdownFiles()
.filter(f => f.path.startsWith("books/"));
let count = 0;
for (let file of files) {
const content = await app.vault.read(file);
const hasStatus = content.includes("status:");
const hasRating = content.includes("rating:");
if (!hasStatus || !hasRating) {
const newContent = content.replace(/^---\n/, `---\n${!hasStatus ? "status: to-read\n" : ""}${!hasRating ? "rating: \n" : ""}`);
await app.vault.modify(file, newContent);
count++;
}
}
tR += `已更新 ${count} 个文件`;
-%>配方 10:自动生成目录页
dataviewjs
// 自动为指定文件夹生成目录页
const folder = dv.current().file.folder;
const pages = dv.pages(`"${folder}"`)
.where(p => p.file.name !== dv.current().file.name)
.sort(p => p.file.name);
dv.header(2, `📂 ${folder} 目录 (${pages.length} 篇)`);
// 按标签分组
const byTag = {};
for (let p of pages) {
const tag = p.tags ? p.tags[0] : "未分类";
if (!byTag[tag]) byTag[tag] = [];
byTag[tag].push(p);
}
for (let [tag, group] of Object.entries(byTag).sort()) {
dv.header(3, `${tag} (${group.length})`);
dv.list(group.map(p => p.file.link));
}配方 11:读书进度追踪
dataviewjs
// 自动计算阅读进度并提醒
const books = dv.pages('"books"').where(p => p.status === "reading");
if (books.length === 0) {
dv.paragraph("📖 当前没有正在阅读的书籍");
} else {
dv.header(3, "📖 阅读进度追踪");
for (let book of books) {
const progress = book.total_pages && book.total_pages > 0
? Math.round((book.current_page || 0) / book.total_pages * 100)
: 0;
const filled = Math.floor(progress / 5);
const bar = "█".repeat(filled) + "░".repeat(20 - filled);
dv.paragraph(
`${book.file.link}\n\`${bar}\` ${progress}% (${book.current_page || 0}/${book.total_pages || "?"})`
);
}
}配方 12:知识盲区检测
dataviewjs
// 检测哪些标签下的笔记数量太少(可能存在知识盲区)
const tagCounts = {};
const pages = dv.pages().where(p => p.tags);
for (let p of pages) {
for (let tag of p.tags) {
tagCounts[tag] = (tagCounts[tag] || 0) + 1;
}
}
const sorted = Object.entries(tagCounts).sort((a, b) => a[1] - b[1]);
const sparse = sorted.filter(([tag, count]) => count <= 2);
dv.header(3, `🔍 知识盲区检测 (${sparse.length} 个标签仅 1-2 篇笔记)`);
if (sparse.length > 0) {
dv.table(
["标签", "笔记数", "建议"],
sparse.slice(0, 15).map(([tag, count]) => [
tag,
count,
count === 1 ? "考虑补充更多笔记或合并到相关标签" : "考虑补充更多内容"
])
);
}三件套联动最佳实践
工作流设计原则
- 单一职责:每个模板只做一件事
- 模板命名规范:
模板名-用途.md - 属性先行:所有模板都应包含标准化 frontmatter
- 渐进式自动化:先手动 → 再模板化 → 最后自动化
- 定期审查:每月检查模板是否需要更新
推荐插件配置顺序
1. 安装 Templater → 设置模板目录
2. 安装 QuickAdd → 配置快速捕获
3. 安装 Dataview → 启用 JavaScript 查询
4. 创建基础模板 → 测试工作流
5. 逐步添加自动化配方相关文档
- QuickAdd 插件 — QuickAdd 基础教程
- Templater 高级教程 — Templater 详解
- Dataview 实战指南 — Dataview 入门
- DataviewJS 高级用法 — 编程式查询
- Properties 完整指南 — 属性系统
- Dataview 速查表 — 语法速查
- Templater 速查表 — 函数速查