任务进度自动更新至YAML数据

想要能将任务进度自动更新到YAML区,比如该文件有10个任务,完成了5个。则自动将元数据中的taskprogress更新成50%。这样配合component插件的数据视图可以有一个项目进度条的效果。 同时希望指定一个项目文件夹,里面的文件都可以定时更新进度。默认设置是一分钟更新一次。
效果:

方法:

  1. 在ob中添加一个自定义脚本taskprogress.js
  2. 点击QuickAdd的macro宏,添加自定义的脚本
  3. 点击脚本设置,添加文件夹路径。
  4. 选择启动时运行。

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;
}
2 个赞