想要能将任务进度自动更新到YAML区,比如该文件有10个任务,完成了5个。则自动将元数据中的taskprogress更新成50%。这样配合component插件的数据视图可以有一个项目进度条的效果。 同时希望指定一个项目文件夹,里面的文件都可以定时更新进度。默认设置是一分钟更新一次。
效果:
方法:
- 在ob中添加一个自定义脚本taskprogress.js
- 点击QuickAdd的macro宏,添加自定义的脚本
- 点击脚本设置,添加文件夹路径。
- 选择启动时运行。
taskprogress.js的内容
module.exports = {
entry: async (QuickAdd, settings, params) => {
const folderPath = settings["FolderPath"];
const intervalMinutes = settings["IntervalMinutes"];
const yaml = "taskprogress";
setInterval(async () => {
const startTime = new Date();
console.log(`文件夹: ${folderPath}`);
console.log(`任务开始时间: ${startTime.toLocaleTimeString()}`);
// 获取文件夹下所有文件
const files = await getAllFilesInFolder(folderPath);
console.log(`处理文件总数: ${files.length}`);
let processedFiles = 0;
for (const file of files) {
const content = await app.vault.read(file);
const taskRegex = /^- \[.\] .*/gm;
const subTaskRegex = /^\t*- \[.\] .*/gm; // 匹配前面有一个或多个tab的子任务
const tasks = content.match(taskRegex) || [];
let totalTasks = 0;
let completedTasks = 0;
// 遍历任务,识别亲本任务和子任务
tasks.forEach(task => {
const taskIndex = content.indexOf(task);
const nextTaskIndex = content.indexOf('\n-', taskIndex + 1);
const taskBlock = content.slice(taskIndex, nextTaskIndex === -1 ? undefined : nextTaskIndex);
const subTaskMatches = taskBlock.match(subTaskRegex) || [];
const completedSubTaskMatches = taskBlock.match(/^\t*- \[x\] .*/gm) || [];
if (subTaskMatches.length > 0) {
totalTasks += subTaskMatches.length;
completedTasks += completedSubTaskMatches.length;
} else {
totalTasks += 1;
if (task.startsWith('- [x]')) {
completedTasks += 1;
}
}
});
let taskProgress;
if (totalTasks > 0) {
taskProgress = (completedTasks * 100 / totalTasks).toFixed(2);
} else {
taskProgress = 100; // 如果没有任务,则设置为100
}
await app.fileManager.processFrontMatter(file, fm => {
fm[yaml] = taskProgress;
});
}
const endTime = new Date();
console.log(`任务结束时间: ${endTime.toLocaleTimeString()}`);
}, intervalMinutes * 60000); // 自定义时间间隔,以分钟为单位
},
settings: {
name: "自动插入任务完成进度至YAML",
author: "suosuo",
options: {
"FolderPath": {
type: "text",
defaultValue: "",
placeholder: "请输入文件夹路径,如:Project"
},
"IntervalMinutes": {
type: "number",
defaultValue: 1,
placeholder: "请输入时间间隔(分钟)"
}
}
}
};
async function getAllFilesInFolder(folderPath) {
const folder = app.vault.getAbstractFileByPath(folderPath);
const files = [];
if (folder && folder.children) {
for (const child of folder.children) {
if (child.children) {
files.push(...await getAllFilesInFolder(child.path));
} else {
files.push(child);
}
}
}
return files;
}