这样的需求dataview能达到吗?

在「页面A」这个文档中,有以下内容(代码框内的)。
我希望能用 dataview 查询出「学习Python」这个任务所有后代任务中已完成任务的情况。
以表格显示,表格的第1列是已完成的任务名称,第2列是任务完成时间,第3列是任务完成所花费的时间(time属性后面的值)。

我用GPT写了半天,一直都是错的。dataviewjs 也不行,不知道怎么操作。

- [ ] 学习 Python
	- [ ] 学习第一章
		- [x] 学习第一节 ✅ 2024-11-15 (time::40m)
		- [ ] 学习第二节
			- [x] 学习第 2.1 小节 (time::65m) ✅ 2024-11-25
			- [x] 学习第 2.2 小节 (Time:: 30m) ✅ 2024-11-21
		- [ ] 学习第三节 
		- [ ] 学习第四节了
			- [ ] 学习第 4.1 小节
- [ ] 学习 JS
	- [x] 学习第一节 (Time:: 20m) ✅ 2024-11-01

大致是类似下面这样子:

```dataviewjs

const mainTaskName = "学习 Python"; // 目标任务名称
const completedTasks = [];

// 获取所有页面
const pages = dv.pages(`"仓库下的/有可能含有目标主任务的笔记目录"`);
// console.log(pages);
// 遍历每个页面的任务
let taskResult = [];
for (const page of pages) {
    for (const task of page.file.tasks) {
	    console.log(task);
	    if (task.text === mainTaskName) { 
		    recursiveProcessTask(task);
	    }
	}
}

function recursiveProcessTask(task) {
    // 遍历子任务
    console.log(task);
    for (const child of task.children) {
        // 检查子任务是否已完成
        if (child.completed) {
            // 将已完成的任务信息添加到结果数组
            let taskShortName = child.text.split(/\(Time/i)[0].split(/(✅|➕)/)[0];
            taskResult.push([taskShortName, child.completion, child.time || child.Time]);
        }
        // 递归处理子任务
        if (child.children && child.children.length > 0) {
            recursiveProcessTask(child);
        }
    }
}

// 输出表格
dv.table(["已完成任务名称", "完成时间", "完成所花费的时间"], taskResult);

```

这个只是基本的, 还没想好 “要是上层任务和下层任务都记录了时间” 怎么办
此外, 大小写 (time::65m) (Time:: 30m) 最好还是统一了吧, 否则麻烦


PS.

我自己的体会, 直接问 GPT 或许也能成功, 但是细节总是差点

适合干这种事的工具也许是, 收集一些 dv 资料 (md 格式就行, 不必非得是 js 格式) 之后:

  • 问 Obsidian Copilot (全库 QA 模式)
    • 或 Obsidian Smart Connections 同理
    • 好处是一边问着, 一边就测试了
  • 问 Cursor @Codebase 模式
    • 或 Windsurf 同理
    • 这个好处是它们就是为了代码优化的, 且可以专门指定某个 “专管 dv 的子目录” 拿 Cursor 打开, 嵌入速度快, 语料的主题集中

折腾这一通 RAG 后, 这类 dv 问题直接就能问出来吗? 好了不少, 但还是难做到一次成功… 尚需研究…

这个65分钟换成 「1小时、5分钟」 的格式,好奇怪,有办法调整一下吗?

另外,像「完成所花费的时间」能否像notion那样做页下总数统计?

「1小时、5分钟」 的格式

因为 duration 对象默认会被 format 成这个人类可读形态, 改成 task.time.minutes 就好了

能否像notion那样做页下总数统计?

不知道 notion 具体怎么做的, 如果只把上面时间加起来, 那倒是简单
实际上这可能还得看具体需求, task 多级路径上是否既有规划又有实际完成时间, 当父级 task 和子级都写时间, 是以谁为准, 等等


```dataviewjs

const mainTaskName = "学习 Python"; // 目标任务名称
const completedTasks = [];

// 获取所有页面
const pages = dv.pages(`"仓库下的/有可能含有目标主任务的笔记目录"`);
// console.log(pages);
// 遍历每个页面的任务
let taskResult = [];
for (const page of pages) {
    for (const task of page.file.tasks) {
	    console.log(task);
	    if (task.text === mainTaskName) { 
		    recursiveProcessTask(task);
	    }
	}
}

function recursiveProcessTask(task) {
    // 遍历子任务
    console.log(task);
    for (const child of task.children) {
        // 检查子任务是否已完成
        if (child.completed) {
            // 将已完成的任务信息添加到结果数组
            let taskShortName = child.text.split(/\(Time/i)[0].split(/(✅|➕)/)[0];
            taskResult.push([taskShortName, child.completion, child.time.minutes]);
        }
        // 递归处理子任务
        if (child.children && child.children.length > 0) {
            recursiveProcessTask(child);
        }
    }
}
taskResult.push([`Total: ${mainTaskName}`, 
                 taskResult.map(task => task[1]).reduce((a, b) => a > b ? a : b), 
                 taskResult.reduce((total, task) => total + task[2], 0)
                 ]);
// 输出表格
dv.table(["已完成任务名称", "完成日期", "花费时间(min)"], taskResult);

```