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

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();
  • 思源笔记

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

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

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

相关帖子

欢迎来到这里!

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

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