从开始工作起,我就习惯了记录工作日志。最开始的方式非常简单,在本子上写个日期,今天是在这家公司的第多少天,顺便记录一句鼓励自己的话。

  1. 翻看前一天的记录确定今天是第几个工作日
  2. 手动找一个英语学习的网站,基本上抄个每日英语什么的,算是今天跟英语单词又说 hello 了

这是一个比较机械的活,也是我每日上班前的重要仪式,虽然有时候会因为业务比较繁忙,而忘记记录,后续我都会将空缺的那几日的工作日计算进去。

后面随着更换工作,有些公司连个本子都不发的时候,我就开始用尝试用笔记工具来记录,最后在经历了各种笔记工具的折腾之后,我开始使用 Obsidian 来记录工作日志和 TODO list。

这些重复性的操作虽然是个仪式,但是要回看前一日的计数,然后 + 1 变成今天的索引,还是挺让人烦恼的。

直到我发现了 Obsidian 的 Templater 插件,我先是是解决了自动编号的问题,后面又思考每日英语句子的获取,是不是也可以完成呢?最终在 AI 的加持下,这个脚本很快就完成了。

最终效果

现在,每次创建新的工作日志时,模板会自动生成:

#workday 2
The quieter you become, the more you can hear. 你越是安静,能听到的便越多。——拉姆·达斯
#home
<光标在这里,可以立即开始记录>

一切都是自动的:

  • ✅ 工作日编号自动计算(支持归档文件夹)
  • ✅ 每日英语句子自动获取(来自欧路词典)
  • ✅ 光标自动定位到内容区域
  • ✅ 开箱即用,无需手动操作

文件结构

我的工作日志组织方式如下:

workday/
├── template/
│   └── journal-template.md  # 模板文件
├── 2024-archive/            # 归档文件夹
│   ├── 2024-01-15.md
│   ├── 2024-01-16.md
│   └── ...
├── 2025-09-01.md
├── 2025-09-02.md
└── 2025-09-24.md

每个日志都有 #workday N 标签,记录这是在当前公司工作的第几天。由于会定期归档,简单的文件计数无法满足需求,必须遍历所有子目录。

完整模板代码

GitHub 代码

<%*
// 获取英语每日一句
async function fetchDailySentence() {
    try {
        const url = "https://dict.eudic.net/home/dailysentence";
        const response = await requestUrl({
            url: url,
            method: "GET",
            headers: {
                "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36"
            }
        });
        
        const html = response.text;
        
        // 提取英文句子
        const englishMatch = html.match(/<p[^>]*class=["'][^"']*sect[^"']*["'][^>]*>(.*?)<\/p>/is);
        let english = "";
        if (englishMatch) {
            english = englishMatch[1].replace(/<[^>]*>/g, "").trim();
        } else {
            const pMatches = html.match(/<p[^>]*>(.*?)<\/p>/igs);
            if (pMatches && pMatches.length >= 2) {
                english = pMatches[0].replace(/<[^>]*>/g, "").trim();
            }
        }
        
        // 提取中文翻译
        const chineseMatch = html.match(/<div[^>]*class=["'][^"']*sect-trans[^"']*["'][^>]*>(.*?)<\/div>/is);
        let chinese = "";
        if (chineseMatch) {
            chinese = chineseMatch[1].replace(/<[^>]*>/g, "").trim();
        } else {
            const altChineseMatch = html.match(/<p[^>]*class=["'][^"']*sect-trans[^"']*["'][^>]*>(.*?)<\/p>/is);
            if (altChineseMatch) {
                chinese = altChineseMatch[1].replace(/<[^>]*>/g, "").trim();
            }
        }
        
        // 提取作者
        const authorMatch = html.match(/本句出自:([^(]+)/);
        const author = authorMatch ? authorMatch[1].trim() : "";
        
        return { english, chinese, author };
    } catch (error) {
        console.error("获取每日一句失败:", error);
        return { english: "", chinese: "", author: "" };
    }
}

// 获取每日英语
const dailySentence = await fetchDailySentence();

// 统计工作日数量
const workdayFiles = app.vault.getMarkdownFiles().filter(file => {
    return file.path.startsWith("workday/") &&
           !file.path.toLowerCase().includes("template");
});

let dayCount = workdayFiles.length;
console.log("计算出的天数:", dayCount);
_%>
#workday <% dayCount %>
<% dailySentence.english %> <% dailySentence.chinese %>
<%* if (dailySentence.author) { _%>——— <% dailySentence.author %>
<%* } _%>
#home
<% tp.file.cursor() %>

功能详解

1. 自动工作日编号

核心逻辑

const workdayFiles = app.vault.getMarkdownFiles().filter(file => {
    return file.path.startsWith("workday/") &&
           !file.path.toLowerCase().includes("template");
});
let dayCount = workdayFiles.length;

特点

  • 📁 递归扫描 workday 文件夹及所有子目录
  • 🚫 自动排除模板文件(名称包含 “template”)
  • 📊 只统计 .md 文件,忽略其他格式
  • ✅ 支持任意层级的归档文件夹

2. 每日英语句子

数据来源欧路词典每日一句

注意事项:仅供学习使用,不要用于其他途径。

获取内容

  • 英文原句
  • 中文翻译
  • 句子出处/作者(如果有)

实现细节

  • 使用 Obsidian 的 requestUrl API 获取网页内容
  • 通过正则表达式提取句子和翻译
  • 包含备用匹配方案,提高成功率
  • 异步获取,不阻塞模板执行

3. 智能光标定位

使用 <% tp.file.cursor() %> 在内容生成完成后自动将光标定位到正文区域,可以立即开始记录当天的工作内容。

配置步骤

步骤 1:安装插件

在 Obsidian 设置中安装 Templater 插件并启用。

步骤 2:启用必要功能

在 Templater 设置中确保以下选项已启用:

  1. Automatic jump to cursor:模板执行后自动跳转到光标位置
  2. Trigger Templater on new file creation:支持文件创建时自动应用模板
templater 配置

步骤 3:创建模板文件

在模板文件夹中创建 journal-template.md,将上述完整代码粘贴进去。

步骤 4:配置文件夹模板(可选)

如果希望在 workday 文件夹中创建的所有新文件都自动应用此模板:

请一定注意我将 journal 的默认路径调整到了我创建的 workday 目录,如果你更加倾向于其他路径,请根据实际情况调整配置。

templater 配置
  1. 进入 Templater 设置 → Folder Templates
  2. 添加规则:workday 文件夹 → journal-template.md

使用体验

创建前

需要做的事情:
1. 打开前一天的日志
2. 查看是第几个工作日
3. 手动输入编号
4. 找一句励志的话
5. 开始写内容

创建后

需要做的事情:
1. 创建新文件(甚至可以设置快捷键)
2. 直接开始写内容 ✅

所有繁琐的准备工作都由模板自动完成!

调试技巧

如果遇到问题,可以打开开发者控制台(Ctrl/Cmd + Shift + I)查看调试信息:

console.log("计算出的天数:", dayCount);
console.log("获取到的句子:", dailySentence);

控制台会显示:

  • 统计到的工作日数量
  • 获取到的英语句子内容
  • 任何可能的错误信息

扩展思路

这个模板框架非常灵活,可以根据需求扩展更多功能:

1. 添加天气信息

async function fetchWeather() {
    // 调用天气 API
}

2. 添加每日任务

const tasks = [
    "- [ ] 查看邮件",
    "- [ ] 站立会议",
    "- [ ] 代码审查"
].join("\n");

3. 添加历史上的今天

const today = tp.date.now("MM-DD");
// 查询历史事件

4. 自定义标签和分类

const tags = ["#工作", "#学习", "#总结"];

其他应用场景

这个方案不仅适用于工作日志,还可以用于:

  • 学习日志:记录学习的第几天 + 每日学习格言
  • 健身日志:统计锻炼天数 + 健身励志语
  • 项目日志:跟踪项目进展 + 项目管理名言
  • 读书笔记:记录阅读进度 + 每日书摘

只需调整文件夹路径、标签名称和数据源即可。

总结

通过 Templater 的强大功能,我们将原本需要手动完成的重复性工作自动化,让工具真正为我们服务。这个小小的改进带来的好处:

  1. 节省时间:每天至少节省 1-2 分钟的准备时间
  2. 提升专注:创建后立即可以开始记录,不被琐事打断
  3. 增添乐趣:每天都有新的英语句子,增加学习动力
  4. 准确可靠:自动计算编号,不会出错

更重要的是,这种自动化思维可以应用到知识管理的各个方面。当我们学会用代码解决重复性问题时,Obsidian 就不仅仅是一个笔记软件,而是一个真正的生产力工具。

如果你也想让日志记录更加高效和有趣,不妨试试这个方案。相信你会和我一样,享受自动化带来的便利和愉悦!


附录:常见问题

Q: 网络请求失败怎么办?
A: 模板已经包含了错误处理,如果获取失败会返回空字符串,不影响日志创建。可以稍后手动添加内容。

Q: 可以更换其他英语句子来源吗?
A: 当然可以!只需修改 fetchDailySentence 函数中的 URL 和解析逻辑即可。

Q: 归档文件夹的名称有要求吗?
A: 没有要求,当前的示例是在 workday/ 目录下,如果你要修改成 journals,请将 templater 中的 Folder template 设置正确即可,不包含 “template” 即可被统计。

Q: 光标没有自动定位怎么办?
A: 确保在 Templater 设置中启用了 “Automatic jump to cursor” 选项。


希望这个模板能帮助你建立更好的工作习惯,让每一天的记录都充满仪式感!