mermaid自动汇总tasks任务并形成甘特图


遇到的问题

想要使用mermaid语法做甘特图,自动讲笔记里边的tasks任务汇总起来,包括起止时间等,这个可以通过代码实现吗?

还是说需要一些插件协同来实现自动抓取

已尝试的解决方案

在论坛看到好像有大神实现了,但是没有代码,自己折腾了一会儿没搞明白

1 个赞

基本思路可以是, 在 dataview 块里拼一段 mermaid 语法
mermaid 内容先从硬编码开始, 最终应该是动态获取的

```dataviewjs
const mermaid_code = `
gantt
    title A Gantt Diagram
    dateFormat  YYYY-MM-DD
    section Section
    A task           :a1, 2024-01-01, 30d
    Another task     :after a1  , 20d
    section Another
    Task in sec      :2024-01-12  , 12d
    another task     : 24d
`

dv.paragraph('```mermaid\n' + mermaid_code + '\n```');
```

以下这俩帖子都有附代码供参考 Automatic Gantt Chart from Obsidian Tasks & Dataview - Share & showcaseObsidian 针对项目文件的自动任务甘特图 - 经验分享

2 个赞
```dataviewjs
function textParser(taskText) {
    let d = taskText.indexOf("📅");
    let DueText="";
    if(d>=0){
    	let i=taskText.slice(d).search(/([12]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01]))/);
    	DueText=taskText.substr(d+i,10);
    } 
    
	let sch = taskText.indexOf("⏳");
	let scheduledText="";
	if(sch>0){
		let i=taskText.slice(sch).search(/([12]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01]))/);
		scheduledText=taskText.substr(sch+i,10);
	} 
    
	let st = taskText.indexOf("🛫");
	let startText="";
	if(st>0){
		let i=taskText.slice(st).search(/([12]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01]))/);
		startText=taskText.substr(st+i,10);
	} 
	
	let di = taskText.indexOf("✅");
	let doneText="";
 	if(di>0){
 		let i=taskText.slice(di).search(/([12]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01]))/);
 		doneText=taskText.substr(di+i,10);
	 } 

    let h = taskText.indexOf("⏫");
    let m = taskText.indexOf("🔼");
    let l = taskText.indexOf("🔽");

    let PriorityText = "";
    if (h >= 0) {
        PriorityText = "High";
    }
    if (m >= 0) {
        PriorityText = "Medium";
    }
    if (l >= 0) {
        PriorityText = "Low";
    }
	const emojisIndex = [d,sch,st,di,h,m,l]
    const presentEmojiIndex = emojisIndex.filter(x => x > 0);
    
    let 	nameText = taskText.slice(0,Math.min(...presentEmojiIndex)).trim();
    
    return {
        done: doneText,
        due: DueText,
        name: nameText,
        priority: PriorityText,
        scheduled: scheduledText,
        start: startText
    };
}

function loopGantt(page) {
    if (!page || !page.file || !page.file.tasks || page.file.tasks.length === 0) {
        return "";
    }

    let querySections = "";
    let taskArray = page.file.tasks;
    
    let hasParentTask = taskArray.some(task => task.children && task.children.length > 0);

    for (let task of taskArray) {
        let taskObj = textParser(task.text);
        
        if (hasParentTask && task.children && task.children.length > 0) {
            querySections += `section ${taskObj.name}\n`;
            continue;
        }

        let status = task.status === "x" ? "done" : "active";
        let critStat = taskObj.priority === "high" ? "crit, " : "";

        let taskLine = `${taskObj.name} :${critStat}${status}, `;
        
        if (taskObj.start) {
            taskLine += `${taskObj.start}, `;
        }
        
        if (taskObj.due) {
            taskLine += `${taskObj.due}`;
        }
        taskLine += '\n';
        querySections += taskLine;
    }
    
    return querySections;
}

let currentPage = dv.current();
let result = loopGantt(currentPage);

if (result) {
    const Mermaid = `gantt
    title ${currentPage.file.name}
    dateFormat YYYY-MM-DD
    axisFormat %m-%d
    tickInterval 7d
    `;

    const fullMermaidCode = Mermaid + result;

    dv.paragraph('```mermaid\n' + fullMermaidCode + '\n```');
}
```

根据 tasks 的 start 和 due 来生成 gant

2 个赞

如果你想用 done 或者别的作为截止时间,就改这一段。

2 个赞

对于坐标轴和日期格式,改这里

3 个赞