很早之前,就想做一个简单的进度管理应用,也跟朋友讨论过这件事,但无奈手上的事情太多便搁置了。

而最近刚好在研究 Notion,发现基于 Notion 提供的一些内置函数应该也是可以实现进度条功能的,而经过一个晚上的折腾,终于搞定了一个粗略的版本,下图即最终的效果,还可以看得过去。

实现过程

进度 = (当前 / 目标) * 100%

进度的计算公式很简单

第一步

新建一个 Table 类型的 Database

根据自己的需要设定列,这里演示就设定了四列,分别是 目标名称、当前、目标、进度,其中要注意的是 当前 和 目标 的类型是数字(Number),而 进度 的类型是 公式(Formula)

进度的显示情况有 当前 和 目标 这两个因子所决定,那么我们根据上面的公式就知道要选择一个除法运算,divide,第一个参数是除数,第二个参数是被除数,调用这个运算函数即可得出结果

divide(prop("当前"), prop("目标"))

如果要计算百分比,需将上面的结果乘以 100,因此需要选择乘法运算,multiply

multiply(divide(prop("当前"), prop("目标")), 100)

由于我们是用月亮的阴晴来作为进度的表达方式,所以我们要做的其实计算最终要显示多少个月亮,这里为了简化,方法比较粗暴,10% 显示一个晴月(🌕),20% 显示两个晴月,以此类推,剩下的以阴月表示(🌑)。因此将前面计算的百分比除以 10,再向下取整,即可算出最终要显示的晴月数量,用公式来表达就是

floor(divide(multiply(divide(prop("当前"), prop("目标")), 100), 10))

因为结果乘以 100,又除以 10,所以最终是乘以 10,简化一下就是

floor(multiply(divide(prop("当前"), prop("目标")), 10))

上面的 floor 是一个向下取整函数,比如如果结果是 4.2、4.8、4.5,向下取整后最后结果都是 4。

一个晴月就代表 10% 的份额,那么需要 10 个晴月就是 100%,幸运地是,emoji 本质上就是字符,一个emoji由两个字符构成,而 Notion 居然提供了一个字符截取函数,slice,这就好玩了。

这个函数有两种调用方式,第一个参数是初始字符串,第二个参数是截取的开始位置,第三个参数是截取终止位置(不包含),第三个参数若省略,则截取由开始位置之后的所有字符,具体看上图的例子。

前面我们已经知道晴月数量的计算方式

floor(divide(multiply(divide(prop("当前"), prop("目标")), 100), 10))

初始晴月字符串我们这样表示 “🌕🌕🌕🌕🌕🌕🌕🌕🌕🌕”

slice(“🌕🌕🌕🌕🌕🌕🌕🌕🌕🌕”, 截取初始位置, 截取终止位置)

slice("🌕🌕🌕🌕🌕🌕🌕🌕🌕🌕", 0, multiply(floor(divide(multiply(divide(prop("当前"), prop("目标")), 100), 10)), 2))

初始位置为 0 可以理解,可能会有人好奇,为什么截止位置要乘以 2,因为前面我们提到一个 emoji 是由两个字符表示的,所以要乘以 2。

到这里,大家应该明白为什么我会花了一个晚上这么长时间写这么一个功能了,这嵌套看得真是眼花。

那么显示晴月的功能实现了,为了让格式看起来正解一点,如果晴月的数量不满10个,则后面用阴月补上,这里直接给出代码。

slice("🌑🌑🌑🌑🌑🌑🌑🌑🌑🌑", 0, multiply(ceil(multiply(divide(subtract(prop("目标数"), prop("完成数")), prop("目标数")), 10)), 2))

subtract 是减法函数,ceil 是向上取整函数。

显示晴月的条件就是进度超过或等于 10%,Notion 也提供了 if 函数

if 函数包含三个参数,第一个参数是条件,如果条件为真,则结果为第二个参数,否则为第三个参数,根据前面的分析,显示晴月的最终代码为

if(largerEq(multiply(divide(prop("完成数"), prop("目标数")), 100), 10), slice("🌕🌕🌕🌕🌕🌕🌕🌕🌕🌕", 0, multiply(floor(divide(multiply(divide(prop("当前"), prop("目标")), 100), 10)), 2)), "")

第三个参数为空 “”,即什么也不显示,同理显示阴月的代码为

if(largerEq(multiply(divide(subtract(prop("目标数"), prop("完成数")), prop("目标数")), 100), 10), slice("🌑🌑🌑🌑🌑🌑🌑🌑🌑🌑", 0, multiply(ceil(multiply(divide(subtract(prop("目标数"), prop("完成数")), prop("目标数")), 10)), 2)), "")

最后,我们将晴月和阴月的显示结果做个字符串连接(concat),但由于还要在末尾添加百分比结果,所以最终要连接的字符串不止两个,而 concat 函数只能处理两个字符串,因此我这里用 join 来实现

join 是可以将任意多个字符串以指定的分隔符分隔的函数,效果如上图,由于这里我们不需要分隔符,所以第一个参数用空字符表示即可,最终的代码如下

join("", if(largerEq(multiply(divide(prop("当前"), prop("目标")), 100), 10), slice("🌕🌕🌕🌕🌕🌕🌕🌕🌕🌕", 0, multiply(floor(divide(multiply(divide(prop("当前"), prop("目标")), 100), 10)), 2)), ""), if(largerEq(multiply(divide(subtract(prop("目标"), prop("当前")), prop("目标")), 100), 10), slice("🌑🌑🌑🌑🌑🌑🌑🌑🌑🌑", 0, multiply(ceil(multiply(divide(subtract(prop("目标"), prop("当前")), prop("目标")), 10)), 2)), ""), " ", slice(format(multiply(divide(prop("当前"), prop("目标")), 100)), 0, 5), "%")

其中百分比的公式为

slice(format(multiply(divide(prop("完成数"), prop("目标数")), 100)), 0, 5)

format 可以将结果转变为字符串的函数

然后因为可能会出现计算结果小数位数太多的情况,可以用 slice 函数进行处理。

至此,一个简单的进度条功能就实现了。当然优化的地方还是很多的,毕竟你看看月亮的 emoji 可不止两个,艰巨的任务交给你们了。

🌕🌕🌕🌕🌖🌗🌘🌑 🌑🌑

如果你还没有注册 Notion,欢迎使用我的推荐链接进行注册,这样我将可获得 $5 的额度,而你可以获得 $10 的额度。

Tagged in:

,