像打游戏一样管理人生——用 Obsidian 搭建个人 OKR 系统

前言

去年某天,我在 B 站刷到了这样一个视频:

都2026了,你还不会用 Obsidian?(终极教程)

在此之前,我对 Obsidian 的认知仅仅是"一个有点极客的笔记软件"。我也是从这个视频开始正式使用obsidian的。

然后最近看到了这个视频:

像打游戏一样科研真的可行吗?我在 Obsidian 里搭了一个万年历系统

这个视频提出了一个让我瞬间心动的概念:把人生当成一个 RPG 游戏来经营。每年是大章节,每季度是主线任务,每月是项目进度,每周是具体执行,每天是经验获取。

于是,我花了几天时间,在 Obsidian 里搭建了一套完整的个人 OKR 系统。这篇文章,就是我这个系统的完整搭建过程的记录。


一、整体架构:从年到天的五层金字塔

我的 OKR 系统遵循一个自顶向下的层次结构:

1
2
3
4
5
6
7
8
9
年度 OKR(目标愿景)

季度 OKR(阶段性目标)

月度 OKR(具体项目及进度)

周度 OKR(具体执行计划)

每日日记(时间记录 + 经验值获取)

每一层都通过 Obsidian 的 Wiki-link 互相串联,形成一个闭环:

  • 年度笔记通过 ![[月度笔记### 核心事项]] 汇总全年十二个月的核心进展
  • 季度笔记引用年度核心目标,并嵌入该季度三个月的回顾
  • 月度笔记嵌入四周的周记推进情况和反思
  • 周度笔记嵌入七天的每日总结和小确幸
  • 每日日记中嵌入本周 OKR 计划板,做到"每日都清楚自己该做什么"

这个结构看起来很复杂,但实际上在 Obsidian 中只需要一套模板就能自动生成。下面我们逐步拆解。


二、日历基础:插件与模板

2.1 推荐的日历插件

首先是日历显示,我推荐使用 Chinese Calendar 插件

DevilRoshan/obsidian-lunar-calendar

这是一个更符合中国用户习惯的日历插件,支持农历显示和节假日标注,比原生日历好用很多。

然后是 Periodic Notes 插件,它可以配合模板,在创建每周/每月/每季度/每年笔记时自动调用对应的 Templater 模板来生成内容。这是整个系统得以运转的基石——你不需要手动写一堆东西,只需要点一下按钮,对应周期的笔记就自动生成了。

2.2 热力图:把经验值可视化

经验值是一个数字,单独看没什么感觉。但如果能像 GitHub 的 Contribution 图一样,把每天的经验值变成一个色块,那就能直观地看到自己这一年的状态起伏。

我用的是这个插件:

vran-dev/obsidian-contribution-graph

它在笔记中嵌入一个 contributionGraph 代码块,读取所有日记页面中的"经验值"属性,生成热力图。我把它放在了年度、季度、月度、周度四个层级的笔记顶部,从不同粒度来审视自己的状态。

热力图的配置大概是这样的(放在年度笔记中):

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
title: 年度经验值热力图
graphType: default
dataSource:
type: PAGE
value: "#日记"
dateField:
type: FILE_NAME
format: yyyy-MM-DD
countField:
type: PAGE_PROPERTY
value: 经验值
cellStyleRules:
- id: Ocean_a
color: "#cae7ecff"
min: "1" max: "20"
text: 😅
- id: Ocean_b
color: "#adccecff"
min: "20" max: "30"
- id: Ocean_c
color: "#8ea6c8ff"
min: "30" max: "40"
- id: Ocean_d
color: "#5d81a1ff"
min: "40" max: "50"
- id: Ocean_e
min: "50" max: "70"
color: "#21537fff"
- id: Ocean_f
min: "70" max: "1000"
color: "#04234bff"
text: 🥳

颜色从浅蓝到深蓝,分数越高颜色越深。每天看一眼,就知道自己这段时间每天的一个状态是怎么样的。


三、模板系统:用 Templater 实现自动化

Obsidian 自带的 Templates 插件功能有限,核心的模板引擎我使用的是 Templater 插件。它能执行 JavaScript 代码,实现日期计算、变量提取、条件判断等高级功能。

具体的模板相关的内容,想了下还是不赘述了,都是比较细碎的一些内容。
况且这种模板只适合自己使用,就不放出来了,后面可能会考虑上传到github的仓库,有感兴趣的可以到我的github仓库去查看。


四、核心灵魂:经验值评分系统

好了,前面都是"基础设施"。真正让这套系统从"普通的 OKR 管理"变成"像打游戏一样管理人生"的,是这套经验值评分系统

4.1 设计理念

这套评分系统不是为了给每一天"打分"——高分不代表"今天过得很爽",低分也不代表"今天是糟糕的一天"。它的核心目标是:

客观量化今天有没有向前走。

你可能会想:我今天刷了 8 小时短视频,但我很开心啊,为什么不能给高分?答案很简单——因为这套系统的评分规则是你自己定义的。如果你想成为一个更健康、更高效的人,那就把"健康作息"和"专注工作"设计成高分项。如果你觉得娱乐也同样重要,那就给娱乐设计一个合理的曲线。规则是活的,但一旦定下来,就严格客观执行,不给自己的偷懒找借口。

这其实借鉴了游戏设计中的一个核心概念:经验值不等于快乐值,经验值等于成长值

4.2 评分维度总览

总分由六个维度组成:

维度标准分核心逻辑
睡眠质量20入睡时间 + 睡眠时长的双 sigmoid 曲线积分
工作学习60时长 S 曲线:太少低分,适中高分,超量收益递减
兴趣爱好15有工作基础后加分,纯娱乐不加分,过度递减
时间记录完整度5记录越完整分越高,允许 2 小时琐事不记录
自我评估10用户自己对今日事项推进的主观评价
习惯打卡~10完成已勾选的习惯累计得分

总分约 100 分,但各维度都是"标准分",实际分数可以超过。

4.3 时间记录:柳比歇夫时间记录法

在讲评分算法之前,必须先讲数据来源——时间记录。

我采用的是柳比歇夫时间记录法,简单来说就是:把一天中每个时间段做了什么,诚实地记录下来。格式如下:

1
2
3
4
5
6
09:00-12:00 【工作】
[项目A][重要]
14:00-15:30 【学习】
[课程B]
16:00-17:30 【运动】
23:00-07:00 【睡觉】
  • 格式:HH:MM-HH:MM 【事件名称】
  • 标签是可选的,用 [标签名] 表示,紧跟在事件下一行
  • 跨午夜的事件(如睡眠)会自动处理

记录放在每日日记的「今日时间记录」板块下。每天睡前花 5 分钟回顾一天,填入时间记录,然后点击插件的星星按钮,一键计算今天获得了多少经验值。

4.4 评分算法详解

4.4.1 睡眠评分:你睡对时间了吗?

睡眠评分的核心思想是:不仅要睡得够,还要睡在对的时间

我设计了一个双 sigmoid 函数来刻画"最佳睡眠窗口":

$$ \text{sleepCurve}(x) = 1 + \frac{9}{1 + e^{-5.0(x - 0.50)}} - \frac{9}{1 + e^{-6.0(x - 9.75)}} $$

431405660

其中 $x$ 是当天的时间(以小时计,0-24)。这个函数在凌晨 0:30 到早上 9:30 之间取值最高(约 10),在其它时间段迅速衰减到接近 1。

计算方法:

  1. 从时间记录中筛选出标记为"睡觉"的事件
  2. 将这些事件的时间区间进行合并(处理白天补觉等碎片化睡眠)
  3. 对每个睡眠区间,用辛普森积分法(n=2000 子区间)计算 sleepCurve 下的面积
  4. 除以"标准睡眠区间"(0:30-9:30)的积分面积,得到比例
  5. 最终得分 = 睡眠标准分 × 比例

这意味着:

  • 如果你从晚上 11 点睡到早上 7 点(8 小时,但部分时间在曲线高分区外),得分大概在 16-18 分
  • 如果你从凌晨 4 点睡到中午 12 点(同样 8 小时,但全在低分区),得分可能只有 5-8 分
  • 如果你的睡眠碎片化严重(多次小睡),合并后也无法拿到高分

这个设计非常关键:它不是在惩罚"睡得少",而是在奖励"睡得规律"。

4.4.2 工作学习评分:拒绝内卷,也拒绝摸鱼

工作学习时长评分采用另一个 S 型曲线:

$$ \text{workCurve}(x) = 7 + \frac{3}{1 + e^{-1.95(x - 2.40)}} - \frac{10}{1 + e^{-3.30(x - 8.49)}} $$

3235944883

这个设计明确传达了一个信号:每天高效工作 6 - 7 小时是最优解,再往上拼命,收益微乎其微,不如去好好休息、发展兴趣。

4.4.3 兴趣爱好评分:先完成正事,再享受生活

兴趣爱好的评分有一个独特的前置条件:必须先满足工作学习的最低标准

曲线函数(经平移后):

$$ \text{hobbyCurve}(x') = 10 + \frac{2}{1 + e^{-7.12(x' - 0.75)}} - \frac{12}{1 + e^{-9.42(x' - 2.49)}} $$

3424650837

其中 $x' = x$(兴趣时长)。

关键机制是工作系数

$$\text{coefficient} = \begin{cases} 1, & \text{工作小时} \geq 6 \\ \frac{\text{工作小时}}{6}, & \text{工作小时} < 6 \end{cases}$$

最终分数 = 标准分 × 兴趣曲线积分比例 × 工作系数。

这个设计背后的逻辑是:兴趣爱好是人生的调味剂,但不是主菜。在完成该做的事情之后去享受爱好,是值得鼓励的;而逃避正事钻进爱好里,就不应该获得高经验值。

4.4.4 时间记录完整度:诚实面对自己

这个维度很简单但很重要:

$$\text{得分} = \text{标准分} \times \frac{\text{已记录小时数}}{24 - \text{允许琐事小时数}}$$

默认允许 2 小时的琐事时间(上厕所、吃饭、发呆等)不需要精确记录。如果你记录了 22 小时,就拿到满分。如果只记录了 12 小时,就只能拿到约一半的分。

这个设计鼓励你尽可能完整地记录时间。因为诚实是自我管理的第一步——你无法优化你看不见的东西。

4.4.5 自我评估:你对自己今天的推进满意吗?

这个维度不需要算法,完全由用户自己填写。在日记的 YAML 前置元数据中,有一个 自我评分 字段:

1
自我评分: 8

你根据自己的感受,给今天的事项推进情况打一个主观分。这是对客观数据的补充——有时候一天下来没做什么"工作学习",但你可能完成了一件困扰很久的事情,或者做了一个重要的决定,这些无法被时间记录捕捉的价值,就通过自我评估来体现。

4.4.6 习惯打卡:小习惯,大积累

每日日记模板中有一个 Callout 块:

1
2
3
> [!success] 习惯打卡
> - [ ] 习惯1 🍭3
> - [x] 习惯2 🍭1

插件会解析这个 Callout 块:

  1. 找到所有 - [x](已勾选)的习惯
  2. 识别每行中 🍭 后面的数字
  3. 累加所有已勾选习惯的分数

五、自制插件:一键计算经验值

上一节讲了评分算法,但它们不可能手动计算。为此,我vibe coding 了一个 Obsidian 插件,专门用来解析日记中的时间记录并自动计算经验值。

5.1 插件功能概览

插件名为「每日经验值计算」(Daily Exp Score),开源在:

bluemoon23333/my-obsidian-plugins

核心功能:

  • 一键计算:点击 Ribbon 栏的星星图标或执行命令「计算今日经验值」
  • 自动解析:从日记中提取时间记录板块,解析时间事件
  • 关键词匹配:根据设置中的关键词,将事件分类为睡眠/工作学习/兴趣爱好
  • 六维评分:分别计算六个维度的分数,汇总后写入日记的 YAML 前置元数据
  • Notice 展示:以弹窗形式展示各维度得分明细

具体的实现逻辑就是依照前面的分数加成的逻辑来的,就不进行赘述,基本上就是直接把需求和完整的逻辑设计都给AI就行了


六、段落级标签聚合:让碎片化思考不再沉没

这是我在搭建这套系统时解决的一个很实际的痛点。

6.1 问题

每天写日记时,经常会在某个时刻写下一些有价值的思考或重要的事件记录。比如:

1
2
今天突然想明白了一个道理:拖延的本质不是懒,而是对失败
的恐惧。与其等待完美的时机,不如先做 5 分钟看看。 #关键思考

但是,日记一天接一天地积累,几个月后你已经有了上百篇日记。你根本不可能回头去一篇一篇翻看,那些曾经闪光的思考就这样沉没在了日记的海洋里。

6.2 解决方案

我的做法是:用一个特定的标签标记重要的段落,然后在月度/年度笔记中用 Dataview 自动聚合

在月度 OKR 模板中,我放置了这样一段 DataviewJS 代码:

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
// ===== 配置区域 =====
const folder = "生活/OKR/日记"; // 日记文件夹
const fileTag = "2026/07"; // 按月份标签筛选
const keyTag = "关键思考"; // 段落中的标签

let pages = dv.pages();

// 按文件夹筛选
if (folder) {
pages = pages.where(p => p.file.path.startsWith(folder + "/"));
}

// 按文件标签筛选
if (fileTag) {
const fullTag = "#" + fileTag;
pages = pages.where(p => p.file.etags && p.file.etags.some(t => t === fullTag));
}

let total = 0;
for (const p of pages) {
const tfile = app.vault.getAbstractFileByPath(p.file.path);
if (!tfile || tfile.extension !== "md") continue;
const content = await app.vault.cachedRead(tfile);
const lines = content.split("\n");
const matches = lines.filter(line => line.includes(`#${keyTag}`));
if (matches.length > 0) {
dv.header(3, p.file.link);
for (const line of matches) {
const cleaned = line.replace(new RegExp(`#${keyTag}`, "g"), "").trim();
if (cleaned) dv.paragraph(cleaned);
}
total += matches.length;
}
}
if (total === 0) {
dv.paragraph("未找到包含 #" + keyTag + " 的段落。");
}

核心思路:

  1. 限定搜索范围(日记文件夹 + 文件级月份标签如 #2026/07
  2. 遍历所有匹配的日记文件
  3. 逐行扫描,找到包含 #关键思考 的行
  4. 去掉标签后,将段落内容展示在月度笔记中

在月度笔记中,同样的代码复制了三份,分别聚合 #关键思考#兴趣发展#人际变化 三个维度。这样当你打开月度 OKR 笔记时,当月的所有重要瞬间就自动呈现在眼前了。

6.3 为什么不用 Block Reference?

你可能会问:Obsidian 不是有 Block Reference 吗?为什么不直接 ![[日记^block-id]] 引用?

原因是:手动维护 Block ID 太累了。每天写日记时你要记住给重要的段落手动加上 ^block-id,还要确保不重名,时间一长几乎必然放弃。而 #标签 就自然得多——写下思考时顺手敲一个 #关键思考,零额外心智负担。


八、写在最后

搭建这套系统花了我不少时间,最大的变化不是"效率提高了多少",而是我对自己的成长有更确切的感知。以前"工作了一整天"可能只是感觉,现在打开热力图一看,那天经验值 25 分——说明其实大部分时间都在摸鱼。以前觉得"这周状态很差",打开周记一看,其实完成了不少事情,只是最后两天有点松懈而已。

相关资源