一次obsidian dataview插件的使用过程

前言

最近将笔记从notion迁移到obsidian,有些展示的功能需要使用dataview才能实现
花费了很多时间使用这个插件,一开始有一些不太了解的东西,后面就熟悉起来了
想着把这次的过程记录一下吧


背景

现在有一些记录了背诵内容的笔记,有这些属性:

  • date
  • time
  • 当前完成轮次

我要做的是按照艾宾浩斯记忆法的轮次完成情况检索这些记录,最终目标如下:

艾宾浩斯记忆法的轮次有这些:

  1. 第十轮180d
  2. 第九轮90d
  3. 第八轮30d
  4. 第七轮15d
  5. 第六轮7d
  6. 第五轮4d
  7. 第四轮2d
  8. 第三轮1d
  9. 第二轮12h
  10. 第一轮30m
  11. 未开始

比方说,如果某个背诵笔记距date+time已经过了30分钟,那就进入了第一轮,需要背一遍了
当前轮开始时就是刚一进入当前轮的时间,目前进度就是笔记的当前完成轮次属性

实现

其实在notion中倒简单,只需要设置计算属性就行,就有点像vue3的computed

我一开始的思路是,一步步实现dataview的DQL语法

首先先弄框架:

table without id 
	file.link as "背诵任务",
	1 as "当前轮次",
	1 as "当前轮开始时",
	1 as "背了吗",
	当前完成轮次 as "目前进度"
from "背诵"
SORT date

其中table表明查询结果放到表格中, without id出去前面的序号, file.link从page的文件中获取链接形式(点击后可跳转), 当前完成轮次即为page属性了

计算当前轮次首先需要计算文档时间:

date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))

date(now)获取当前时间
regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes")是正则替换, time的格式是形如17:25, 我将它格式化为17 hours 25 minutes
dur()是将格式化的持续时间时间转化为date格式的持续时间
还要用到choice(), 用法和if()是一模一样的, 第一个参数为条件, true则返回第二个参数, 否则返回第三个参数

通过嵌套choice可以完成当前轮次这一列的计算了:


	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(180 day),"第十轮180d",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(90 day),"第九轮90d",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(30 day),"第八轮30d",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(15 day),"第七轮15d",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(7 day),"第六轮7d",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(4 day),"第五轮4d",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(2 day),"第四轮2d",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(1 day),"第三轮1d",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(12 hours),"第二轮12h",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(30 minutes),"第一轮30m",
	"未开始")))))))))) as "当前轮次"

那么背了吗只需要当前轮次这一列的结果等于当前完成轮次这一page属性就行了:


	choice(当前完成轮次=
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(180 day),"第十轮180d",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(90 day),"第九轮90d",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(30 day),"第八轮30d",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(15 day),"第七轮15d",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(7 day),"第六轮7d",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(4 day),"第五轮4d",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(2 day),"第四轮2d",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(1 day),"第三轮1d",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(12 hours),"第二轮12h",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(30 minutes),"第一轮30m",
	"未开始")))))))))),"*完成*","==未完成==") as "背了吗"

当前轮开始时这一列只需要判断一下当前的轮, 然后加上每个轮对应的时间就行, 使用dateformat格式化一下:

dateformat(
    date
    +dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))
    +choice(当前轮次 -> 对应的dur(...)),
    "yyyy年M月d日HH:mm"
)

因为我想要不同的颜色来直观显示背没背,所以加一个choice:
choice(当前轮=当前完成轮次, "*"+dateformat(...)+"*", "=="+dateformat(...)+"==") as "当前轮开始时"

把已有的逻辑硬塞进去是这样的:

(太长了默认收起来)
choice(当前完成轮次=
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(180 day),"第十轮180d",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(90 day),"第九轮90d",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(30 day),"第八轮30d",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(15 day),"第七轮15d",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(7 day),"第六轮7d",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(4 day),"第五轮4d",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(2 day),"第四轮2d",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(1 day),"第三轮1d",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(12 hours),"第二轮12h",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(30 minutes),"第一轮30m",
	"未开始")))))))))),
	"*"+dateformat(date+dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))+choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(180 day),dur(180 day),
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(90 day),dur(90 day),
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(30 day),dur(30 day),
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(15 day),dur(15 day),
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(7 day),dur(7 day),
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(4 day),dur(4 day),
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(2 day),dur(2 day),
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(1 day),dur(1 day),
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(12 hours),dur(12 hours),
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(30 minutes),dur(30 minutes),
	dur(0 minutes))))))))))),"yyyy年M月d日HH:mm")+"*",
	"=="+dateformat(date+dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))+choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(180 day),dur(180 day),
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(90 day),dur(90 day),
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(30 day),dur(30 day),
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(15 day),dur(15 day),
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(7 day),dur(7 day),
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(4 day),dur(4 day),
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(2 day),dur(2 day),
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(1 day),dur(1 day),
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(12 hours),dur(12 hours),
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(30 minutes),dur(30 minutes),
	dur(0 minutes))))))))))),"yyyy年M月d日HH:mm")+"==") as "当前轮开始时"

简直是嵌套地狱, 完整版如下:

(太长了默认收起来)
table without id 
	file.link as "背诵任务",


	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(180 day),"第十轮180d",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(90 day),"第九轮90d",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(30 day),"第八轮30d",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(15 day),"第七轮15d",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(7 day),"第六轮7d",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(4 day),"第五轮4d",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(2 day),"第四轮2d",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(1 day),"第三轮1d",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(12 hours),"第二轮12h",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(30 minutes),"第一轮30m",
	"未开始")))))))))) as "当前轮次",


	choice(当前完成轮次=
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(180 day),"第十轮180d",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(90 day),"第九轮90d",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(30 day),"第八轮30d",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(15 day),"第七轮15d",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(7 day),"第六轮7d",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(4 day),"第五轮4d",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(2 day),"第四轮2d",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(1 day),"第三轮1d",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(12 hours),"第二轮12h",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(30 minutes),"第一轮30m",
	"未开始")))))))))),
	"*"+dateformat(date+dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))+choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(180 day),dur(180 day),
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(90 day),dur(90 day),
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(30 day),dur(30 day),
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(15 day),dur(15 day),
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(7 day),dur(7 day),
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(4 day),dur(4 day),
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(2 day),dur(2 day),
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(1 day),dur(1 day),
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(12 hours),dur(12 hours),
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(30 minutes),dur(30 minutes),
	dur(0 minutes))))))))))),"yyyy年M月d日HH:mm")+"*",
	"=="+dateformat(date+dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))+choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(180 day),dur(180 day),
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(90 day),dur(90 day),
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(30 day),dur(30 day),
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(15 day),dur(15 day),
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(7 day),dur(7 day),
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(4 day),dur(4 day),
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(2 day),dur(2 day),
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(1 day),dur(1 day),
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(12 hours),dur(12 hours),
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(30 minutes),dur(30 minutes),
	dur(0 minutes))))))))))),"yyyy年M月d日HH:mm")+"==") as "当前轮开始时",


	
	choice(当前完成轮次=
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(180 day),"第十轮180d",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(90 day),"第九轮90d",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(30 day),"第八轮30d",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(15 day),"第七轮15d",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(7 day),"第六轮7d",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(4 day),"第五轮4d",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(2 day),"第四轮2d",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(1 day),"第三轮1d",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(12 hours),"第二轮12h",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(30 minutes),"第一轮30m",
	"未开始")))))))))),"*完成*","==未完成==") as "背了吗",


	当前完成轮次 as "目前进度"
from "背诵"
where 当前完成轮次!=
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(180 day),"第十轮180d",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(90 day),"第九轮90d",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(30 day),"第八轮30d",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(15 day),"第七轮15d",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(7 day),"第六轮7d",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(4 day),"第五轮4d",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(2 day),"第四轮2d",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(1 day),"第三轮1d",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(12 hours),"第二轮12h",
	choice(date(now)-dur(regexreplace(time,"(\d*):(\d*)","$1 hours $2 minutes"))-date>dur(30 minutes),"第一轮30m",
	"未开始"))))))))))
SORT date

改进一 使用dataviewjs

后面了解到还有dataviewjs语法, 相当于用js扩展了dataview, 于是乎开始研究

js代码就清晰一点了, 刚好在学vue, 就当练练基本功:

let pagesFolder = '"背诵"'

function getIndex(a) {
    return Number(a.slice(0, 3))
}

let pages = dv.pages(pagesFolder).sort(i => getIndex(i.file.name))

先获取pages, 按照文件名排序, 我的文件名字带序号, 都是001-这样的开头
dvdataview提供的类, dv.pages根据条件获取一批笔记
我这里获取背诵文件夹下的所有笔记, 然后排序

然后处理一下, 生成一个列表, 每一项都是一行的数据:

// 轮次配置数组 [轮次名称, 毫秒持续时间]
const roundConfigs = [
    ["第十轮180d", 180 * 24 * 60 * 60 * 1000],
    ["第九轮90d", 90 * 24 * 60 * 60 * 1000],
    ["第八轮30d", 30 * 24 * 60 * 60 * 1000],
    ["第七轮15d", 15 * 24 * 60 * 60 * 1000],
    ["第六轮7d", 7 * 24 * 60 * 60 * 1000],
    ["第五轮4d", 4 * 24 * 60 * 60 * 1000],
    ["第四轮2d", 2 * 24 * 60 * 60 * 1000],
    ["第三轮1d", 1 * 24 * 60 * 60 * 1000],
    ["第二轮12h", 12 * 60 * 60 * 1000],
    ["第一轮30m", 30 * 60 * 1000],
    ["未开始", 0]
];

// 单次遍历处理所有数据
const tableContent = pages.map(page => {
    // 合并日期时间
    const [h, m] = page.time.split(':').map(Number)
    // 计算文档时间戳(毫秒)
    const date = new Date(page.date)
    date.setHours(h, m, 0, 0)
    const timestamp = date.getTime()
    
    // 计算当前轮次
    const diffMs = now - timestamp
    let currentRound = "未开始"
    let durationMs = 0
    for (const [round, ms] of roundConfigs) {
        if (ms === 0 || diffMs > ms) {
            currentRound = round
            durationMs = ms
            break
        }
    }
    
    // 判断是否完成
    const isCompleted = currentRound === page.当前完成轮次
    if (!isCompleted) return []

    // 计算当前轮开始时间
    const roundStartTime = new Date(timestamp + durationMs)
    const formattedTime = (() => {
        const year = roundStartTime.getFullYear()
        const month = roundStartTime.getMonth() + 1
        const day = roundStartTime.getDate()
        const hours = String(roundStartTime.getHours()).padStart(2, '0')
        const minutes = String(roundStartTime.getMinutes()).padStart(2, '0')
        if(!isCompleted)
	        return `==${year}年${month}月${day}日${hours}:${minutes}==`
	else return `*${year}年${month}月${day}日${hours}:${minutes}*`
    })()
    
    return [
        page.file.link,                  // 背诵任务
        currentRound,                    // 当前轮次
        formattedTime,                   // 当前轮开始时
        isCompleted ? "*完成*" : "==未完成==", // 背了吗
        page.当前完成轮次                // 目前进度
    ]
})

前端这种写法, 一开始不太适应, 但后面还是觉得很舒服:

const 变量 = (()=>{
    ...
    return result
})()

这种创建后立刻调用然后赋值的风格, 其实就相当于包了个代码块, 我们并不关心在里面的有一堆临时变量的实现

最后使用dv.table把表格渲染出来即可:

let pagesFolder = '"背诵"'

function getIndex(a) {
    return Number(a.slice(0, 3))
}

let pages = dv.pages(pagesFolder).sort(i => getIndex(i.file.name))
let now = Date.now()

// 轮次配置数组 [轮次名称, 毫秒持续时间]
const roundConfigs = [
    ["第十轮180d", 180 * 24 * 60 * 60 * 1000],
    ["第九轮90d", 90 * 24 * 60 * 60 * 1000],
    ["第八轮30d", 30 * 24 * 60 * 60 * 1000],
    ["第七轮15d", 15 * 24 * 60 * 60 * 1000],
    ["第六轮7d", 7 * 24 * 60 * 60 * 1000],
    ["第五轮4d", 4 * 24 * 60 * 60 * 1000],
    ["第四轮2d", 2 * 24 * 60 * 60 * 1000],
    ["第三轮1d", 1 * 24 * 60 * 60 * 1000],
    ["第二轮12h", 12 * 60 * 60 * 1000],
    ["第一轮30m", 30 * 60 * 1000],
    ["未开始", 0]
];

// 单次遍历处理所有数据
const tableContent = pages.map(page => {
    // 合并日期时间
    const [h, m] = page.time.split(':').map(Number)
    // 计算文档时间戳(毫秒)
    const date = new Date(page.date)
    date.setHours(h, m, 0, 0)
    const timestamp = date.getTime()
    
    // 计算当前轮次
    const diffMs = now - timestamp
    let currentRound = "未开始"
    let durationMs = 0
    for (const [round, ms] of roundConfigs) {
        if (ms === 0 || diffMs > ms) {
            currentRound = round
            durationMs = ms
            break
        }
    }
    
    // 判断是否完成
    const isCompleted = currentRound === page.当前完成轮次
    if (!isCompleted) return []

    // 计算当前轮开始时间
    const roundStartTime = new Date(timestamp + durationMs)
    const formattedTime = (() => {
        const year = roundStartTime.getFullYear()
        const month = roundStartTime.getMonth() + 1
        const day = roundStartTime.getDate()
        const hours = String(roundStartTime.getHours()).padStart(2, '0')
        const minutes = String(roundStartTime.getMinutes()).padStart(2, '0')
        if(!isCompleted)
	        return `==${year}年${month}月${day}日${hours}:${minutes}==`
	else return `*${year}年${month}月${day}日${hours}:${minutes}*`
    })()

    return [
        page.file.link,                  // 背诵任务
        currentRound,                    // 当前轮次
        formattedTime,                   // 当前轮开始时
        isCompleted ? "*完成*" : "==未完成==", // 背了吗
        page.当前完成轮次                // 目前进度
    ]
})

// 渲染表格
dv.table(
    ["背诵任务", "当前轮次", "当前轮开始时", "背了吗", "目前进度"],
    tableContent
)

改进二 使用flatten

我在一开始的嵌套地狱那块,就在想能不能在DQL语句内部复制变量,但是我也没有查到 。后来我发现使用flatten即可

用法是FLATTEN <value> [AS <name>], 支持多个FLATTEN

这样一来事情就很简单了
定义一下现在的时间到文档时间的时间差:

FLATTEN dur(regexreplace(time, "(\d*):(\d*)", "$1 hours $2 minutes")) AS timeDur
FLATTEN date(now) - date - timeDur AS timeDiff

然后匹配一下轮次即可:

TABLE WITHOUT ID
    file.link AS "背诵任务",
    currentRound AS "当前轮次",
    currentRoundStarted AS "当前轮开始时间",
    choice(当前完成轮次 = currentRound, "*完成*", "==未完成==") AS "背了吗",
    当前完成轮次 AS "目前进度"
FROM "背诵"
FLATTEN dur(regexreplace(time, "(\d*):(\d*)", "$1 hours $2 minutes")) AS timeDur
FLATTEN date(now) - date - timeDur AS timeDiff
FLATTEN choice(
    timeDiff > dur(180 day), "第十轮180d",
    choice(timeDiff > dur(90 day), "第九轮90d",
    choice(timeDiff > dur(30 day), "第八轮30d",
    choice(timeDiff > dur(15 day), "第七轮15d",
    choice(timeDiff > dur(7 day), "第六轮7d",
    choice(timeDiff > dur(4 day), "第五轮4d",
    choice(timeDiff > dur(2 day), "第四轮2d",
    choice(timeDiff > dur(1 day), "第三轮1d",
    choice(timeDiff > dur(12 hours), "第二轮12h",
    choice(timeDiff > dur(30 minutes), "第一轮30m",
    "未开始")))))))))
) AS currentRound
FLATTEN date + timeDur + choice(
    currentRound = "第十轮180d", dur(180 day),
    choice(currentRound = "第九轮90d", dur(90 day),
    choice(currentRound = "第八轮30d", dur(30 day),
    choice(currentRound = "第七轮15d", dur(15 day),
    choice(currentRound = "第六轮7d", dur(7 day),
    choice(currentRound = "第五轮4d", dur(4 day),
    choice(currentRound = "第四轮2d", dur(2 day),
    choice(currentRound = "第三轮1d", dur(1 day),
    choice(currentRound = "第二轮12h", dur(12 hours),
    choice(currentRound = "第一轮30m", dur(30 minutes),
    dur(0 minutes))))))))))) AS startTime
FLATTEN choice(当前完成轮次 = currentRound,
	"*" + dateformat(startTime, "yyyy年M月d日HH:mm") + "*",
	"==" + dateformat(startTime, "yyyy年M月d日HH:mm") + "=="
) AS currentRoundStarted
WHERE 当前完成轮次 != currentRound
SORT date

这样就完成了,比dataviewjs要简单的多了

至此已完成了这个功能,再看看:


杂谈

中文互联网的环境

虽然早就吐槽过了,但是到处转载搬屎的环境还是见一次难受一次

感谢一下高质量的文章以及官方文档:

为什么notion不行?

其数据库不支持中文的文章内容检索,无语

一开始是看中其创建文章数据库足够方便简单,但现在还是算了,果断放弃了

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇