QueryView 插件实现的日记热力图或索引

本贴最后更新于 329 天前,其中的信息可能已经斗转星移

QueryView 插件 真是一个功能强大的插件。

安装插件后,在 daily note/2024 文档内通过 /qv 空格 使用模板,点击 更新 sql 按钮,填入以下内容

热力图

20250127151015.jpg

所有 daily note 都在一个图

//!js
const query = async () => {
  let dv = Query.DataView(protyle, item, top);

  const blocks = await Query.dailynote(null, -1);

  const yearSet = new Set();
  const data = blocks.map(block => {
    const m = block.ial.match(/dailynote-(\d{4})(\d{2})(\d{2})/);
    const [_, year, month, day] = m;
    yearSet.add(Number.parseInt(year, 10));

    return {
      id: block.id,
      date: `${year}-${month}-${day}`,
      year,
      title: block.content,
    }
  })

  const heatmapData = data.map((item, index) => {
    return [item.date, Math.floor(Math.random() * 10000)];
  });

  const years = Array.from(yearSet).sort((a, b) => b - a);

  const calendar = years.map((year, index) => {
    return {
      range: [`${year}-01-01`, `${year}-12-31`],
      cellSize: ['auto', 13],
      top: 50 + index * 150,
      left: 30,
      yearLabel: { show: true, position: 'top' },
    }
  });

  const series = Array(calendar.length).fill(0).map((_, index) => {
    return {
      type: 'heatmap',
      coordinateSystem: 'calendar',
      calendarIndex: index,
      data: heatmapData
    }
  });

  const option = {
    tooltip: {
      formatter: (params) => {
        const title = data[params.dataIndex].title;
        return `${title}`;
      }
    },
    visualMap: {
      min: 0,
      max: 10000,
      show: false
    },
    calendar,
    series,
  };

  dv.addecharts(option, {
    height: `${calendar.length * 140 + 30}px`,
    events: {
      click: (params) => {
        const item = data[params.dataIndex];
	      Query.Utils.openBlock(item.id);
      }
    }
  });
  dv.render();
}

return query();

热力图(一年分一半)

20250126201819.jpg

当前子文档的 daily note,一年分一半

//!js
const query = async () => {
  let dv = Query.DataView(protyle, item, top);

  const data = []
  let thisYear;
  let childs = await Query.childdoc(dv.root_id);
  for (let child of childs) {
    //获取子文档的子文档
    const subchilds = await Query.childdoc(child.root_id);
    for (let subchild of subchilds) {
      const m = subchild.ial.match(/dailynote-(\d{4})(\d{2})(\d{2})/);
      const [_, year, month, day] = m;
      if (!thisYear) {
        thisYear = year
      }

      data.push({
        id: subchild.id,
        date: `${year}-${month}-${day}`,
        title: subchild.content,
        url: `siyuan://blocks/${subchild.id}`
      })
    }
  }

  const heatmapData = data.map((item, index) => {
    return [item.date, Math.floor(Math.random() * 10000)];
  });

  const option = {
    tooltip: {
      formatter: (params) => {
        const title = data[params.dataIndex].title;
        return `${title}`;
      }
    },
    visualMap: {
      min: 0,
      max: 10000,
      show: false
    },
    calendar: [
      {
        range: [`${thisYear}-01-01`, `${thisYear}-06-30`],
        cellSize: [20, 20],
        top: 50,
      },
      {
        range: [`${thisYear}-07-01`, `${thisYear}-12-31`],
        cellSize: [20, 20],
        top: 250,
      },
    ],
    series: [
      {
        type: 'heatmap',
        coordinateSystem: 'calendar',
        data: heatmapData
      },
      {
        type: 'heatmap',
        coordinateSystem: 'calendar',
        calendarIndex: 1,
        data: heatmapData
      },
    ]
  };

  dv.addecharts(option, {
    height: '420px',
    events: {
      click: (params) => {
        const item = data[params.dataIndex];
	Query.Utils.openBlock(item.id);
      }
    }
  });
  dv.render();
}

return query();

索引

20250126163108.jpg

当前子文档的 daily note

//!js
function getWeekNumber(date) {
  const startOfYear = new Date(date.getFullYear(), 0, 1);
  const pastDaysOfYear = (date - startOfYear) / 86400000; // 计算从年初到当前日期的天数
  return Math.ceil((pastDaysOfYear + startOfYear.getDay() + 1) / 7);
}

const query = async () => {
  let dv = Query.DataView(protyle, item, top);
  const blocks = []
  let childs = await Query.childdoc(dv.root_id);
  for (let child of childs) {
    //获取子文档的子文档
    const subchilds = await Query.childdoc(child.root_id);
    blocks.push(...subchilds)
  }

  // 按月、周分组
  const groupedByMonthAndWeek = blocks.reduce((acc, block) => {
    // 将 created 字符串转换为日期对象
    const m = block.ial.match(/dailynote-(\d{4})(\d{2})(\d{2})/);
    const year = m[1];
    const month = m[2];
    const day = m[3];
    const date = new Date(year, month - 1, day); // 月份从 0 开始

    // 获取该日期所在的周数
    const weekNumber = getWeekNumber(date);

    // 按月分组的键
    const monthKey = `${year}-${month.padStart(2, '0')}`;

    // 按周分组的键
    const weekKey = `W${weekNumber.toString().padStart(2, '0')}`;

    // 如果该月份还没有在累加器中,创建一个空对象
    if (!acc[monthKey]) {
      acc[monthKey] = {};
    }

    // 如果该周还没有在月份分组中,创建一个空数组
    if (!acc[monthKey][weekKey]) {
      acc[monthKey][weekKey] = [];
    }

    const newBlock = {
      id: block.id,
      content: block.content,
      date,
      month,
      day,
      weekNumber: date.getDay(),
      weekCN: ['日', '一', '二', '三', '四', '五', '六'][date.getDay()],
    }

    // 将当前 block 添加到对应的周数组中
    acc[monthKey][weekKey].push(newBlock);

    return acc;
  }, {});

  // 输出 Markdown
  let md = '';
  for (let month in groupedByMonthAndWeek) {
    md += `## ${month}\n\n`;
    for (let week in groupedByMonthAndWeek[month]) {
      md += `- `;
      const blocks = groupedByMonthAndWeek[month][week];
      // 按日期排序
      blocks.sort((a, b) => a.date - b.date);
      for (let block of blocks) {
        const title = `${block.month}-${block.day} (${block.weekCN})`
        const url = `siyuan://blocks/${block.id}`
        md += `    [${title}](${url})`;
      }
      md += '\n';
    }
    md += '\n';
  }

  dv.addmd(md);
  dv.render();
}
return query();

  • 思源笔记

    思源笔记是一款隐私优先的个人知识管理系统,支持完全离线使用,同时也支持端到端加密同步。

    融合块、大纲和双向链接,重构你的思维。

    28446 引用 • 119783 回帖
3 操作
greatYear 在 2025-01-27 15:21:57 更新了该帖
greatYear 在 2025-01-27 15:12:31 更新了该帖
greatYear 在 2025-01-27 12:19:42 更新了该帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
  • GloR

    qv 插件更新后,这串代码似乎无法使用了