分享一个项目管理的数据库模板

先上效果图:

PixPin20250721220054.gif

具体功能:

  • 自动统计时间进度
  • 自动统计关联文档中的任务数量,并显示任务进度。任务进度设置了判断条件,若文档中没有任务项,则显示“无任务”(任务数为 0 的时候模板会报错,但是能渲染出“无任务”,错误提醒显示分母为零,但是我已经设置了条件判断,不知道为什么还是会报错 😂。本人代码小白,有没有大佬帮忙修复一下这个 BUG)
  • 状态栏根据计划时间和任务进度设置了:筹备中(计划时间列为空)、未开始(当天日期早于开始时间)、进行中(当天日期位于开始和结束日期之间)、冲刺中(当天日期和结束日期天数差小于 5 天或任务进度大于 80%)、已完成(任务进度 100%)以及过期(当天时间超过截止日期且任务进度小于 100%)

推荐结合 F 大佬的 F“s 工具箱使用动态数据库功能通过标签将任务文档自动汇总进数据库中。

尝试通过查询语句来动态构建数据库 - 链滴

模板文件:

项目管理模板.sy.zip

模板代码:

时间进度列:

.action{$startTime := .计划时间}
.action{$endTime := .计划时间_end}

.action{$totalDuration := 0}
.action{$elapsedDuration := 0}
.action{$percentage := 0.0}
.action{$color := "rgb(45,164,78)"}
.action{$remainingText := ""}

.action{if and (not (eq $startTime nil)) (not (eq $endTime nil))}
    .action{$nowdate := now}

    .action{$endTimeParsed := $endTime}
    .action{$startTimeParsed := $startTime}

    .action{if and (ne $startTimeParsed nil) (ne $endTimeParsed nil)}
        .action{$totalDuration = $endTimeParsed.Sub $startTimeParsed}
        .action{$elapsedDuration = $nowdate.Sub $startTimeParsed}

        .action{$totalDurationHours := divf $totalDuration.Hours 1}
        .action{if gt $totalDurationHours 0.0}
            .action{$percentage = (mulf (divf (div $elapsedDuration.Hours 1) $totalDurationHours) 100.0)}

            .action{$daysLeft := divf ($endTimeParsed.Sub $nowdate).Hours 24}
            .action{if eq 0 $startTimeParsed.Minute $startTimeParsed.Hour $endTimeParsed.Minute $endTimeParsed.Hour }
                .action{$daysLeft = ceil (divf ($endTimeParsed.Sub $nowdate).Hours 24)}
            .action{end}

            .action{if gt $daysLeft 0.0}
                .action{$remainingText = printf "还剩%.0f天" $daysLeft}
            .action{else if eq $daysLeft 0.0}
                .action{$remainingText = "当天"}
            .action{else}
                .action{$remainingText = printf "已过%.0f天" (subf 0.0 $daysLeft)}
            .action{end}
        .action{end}
    .action{end}
.action{end}

.action{$colorGradient_triggerPercentage := list 90.0 70.0 50.0 20.0 0.0}
.action{$colorGradient_baseColor := list "#f94144" "#FF6E34" "#ffcc00" "#2DA44E" "#2571BF"}
.action{range $index, $element := $colorGradient_triggerPercentage}
    .action{if ge $percentage (index $colorGradient_triggerPercentage $index)}
        .action{$color = index $colorGradient_baseColor $index}
        .action{break}
    .action{end}
.action{end}

<span style="background-color: rgba(175,184,193,0.2); width: 100%; display: inline-block;height: 12px;border-radius: 6px;align-self: center;overflow: hidden; position: relative;">
    <!-- 深灰色到浅灰色的渐变背景层 -->
    <span style="
        width: .action{$percentage}%;
        height: 100%;
        background-image: linear-gradient(0deg, #3a3742 0%, #6a6772 100%); /* 深灰色到浅灰色的渐变 */
        display: block;
    "></span>
  
    <!-- 数字层(显示剩余天数) -->
    <span style="
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        font-size: 10px;
        line-height: 12px;
        color: white;
        text-shadow: 0 0 2px rgba(0,0,0,0.5);
    ">
        <span style="font-weight: bold;">.action{$remainingText}</span>
    </span>
</span>

任务进度列:

.action{$todo:=queryBlocks "select * from blocks where root_id in (select root_id from blocks where id='?') and type='i' and subtype='t'" .id}
.action{$all:=len $todo}          <!-- 先取长度 -->
.action{if eq $all 0}
<span style="background-color: rgba(175,184,193,0.2);" data-type='tag'>无任务</span>
.action{else if ne $all 0}
.action{$readytodo:=queryBlocks "select * from blocks where root_id in (select root_id from blocks where id='?') and type='i' and subtype='t' and markdown like '%[x]%'" .id}
.action{$readyall:=len $readytodo}
.action{$d:=div (mul $readyall 100) $all}   <!-- 直接用数字 -->
<span style="background-color:rgba(175,184,193,0.2);width:100%;display:inline-block;height:12px;border-radius:6px;position:relative;overflow:hidden;">
    <span style="width: .action{$d}%;height:100%;background-image:linear-gradient(0deg,#2f3f3a 0%,#5e7a75 100%);display:block;"></span>
    <span style="position:absolute;top:0;left:0;width:100%;text-align:center;font-size:10px;line-height:12px;color:white;text-shadow:0 0 2px rgba(0,0,0,0.5);">
        <span style="font-weight:bold;">.action{floor $d}</span>%
    </span>
</span>
.action{end}

状态列:

.action{$startTime := .计划时间}
.action{$endTime := .计划时间_end}
.action{$today:= (now | date "2006-01-02")}
.action{$nowdate:=(toDate "2006-01-02" $today)}
.action{$delta1 :=(div ($startTime.Sub $nowdate).Hours 24)}
.action{$delta2 :=(div ($endTime.Sub $nowdate).Hours 24)}
.action{$todo:=queryBlocks " select * from blocks where root_id in (select root_id from blocks where id='?') and type='i' and subtype='t' "  .id}
.action{$all:=$todo | len}
.action{$readytodo:=queryBlocks " select * from blocks where root_id in (select root_id from blocks where id='?') and type='i' and subtype='t' and markdown like '%[x]%%' "  .id}
.action{$readyall:=$readytodo | len}
.action{$a:=index $readyall}
.action{$b:=index $all}
.action{$c:= mul $a 100}
.action{$d:= div $c $b}
.action{$a := randInt 1 13}

.action{if empty .计划时间}
<span class="b3-chip" style="background-color:var(--b3-font-background.action{$a});color:var(--b3-font-color.action{$a})">筹备中</span>
  
.action{else if gt $delta1 0}
  <span class="b3-chip" style="background-color:var(--b3-font-background.action{$a});color:var(--b3-font-color.action{$a})">未开始</span>
  
.action{else if and (le $delta1 0) (ge $delta2 0) (ne $a $b)}
  .action{if or (le $delta2 5) (ge $d 80)}
  <span class="b3-chip" style="background-color:var(--b3-font-background.action{$a});color:var(--b3-font-color.action{$a})">冲刺中</span>
  .action{else if and (le $delta1 0) (gt $delta2 5) (lt $d 80)}
  <span class="b3-chip" style="background-color:var(--b3-font-background.action{$a});color:var(--b3-font-color.action{$a})">进行中</span>
  .action{end}
  
.action{else if  and (le $delta1 0) (ge $delta2 0)  (eq $a $b)}
  <span class="b3-chip" style="background-color:var(--b3-font-background.action{$a});color:var(--b3-font-color.action{$a})">已完成</span>
  
.action{else if and (ne $a $b) (lt $delta1 0)  (lt $delta2 0)}
  <span class="b3-chip" style="background-color:var(--b3-font-background.action{$a});color:var(--b3-font-color.action{$a})">过期</span>
.action{end}

分类列:

.action{ $blocks := queryBlocks "select * from blocks where id='?'" .id}
.action{ if not (empty $blocks) }
.action{ $tag := (first $blocks).Tag | replace "#" "" }
.action{$a := randInt 1 13}
<span class="b3-chip" style="background-color:var(--b3-font-background.action{$a});color:var(--b3-font-color.action{$a})">.action{$tag}</span>
.action{ end }

分类列其实就是我将文档的标签单独提取了出来,并设置了一下标签颜色。

因为我使用动态数据库动态查询将带有 OKR 和任务标签的文档都汇总到数据库中,这样通过多维表格单独筛选 OKR 文档和任务文档,就能够直观的看到任务和 OKR 的进度情况。

参考文档

数据库 3 种自动进度条样式的模板。线性进度条、圆环图、表情图案。渐变色

数据库进度条模板

思源模板功能新人指南:模板语法 + 函数 + md 块语法

  • 思源笔记

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

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

    28446 引用 • 119768 回帖
1 操作
Lsywork 在 2025-07-21 22:35:14 更新了该帖

相关帖子

欢迎来到这里!

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

注册 关于
请输入回帖内容 ...
  • Z-QL

    想问问大大这个计划时间进度字段是怎么设置的哇,我只找到了创建和更新时间的字段image.png

    1 回复
  • 其他回帖
  • Lsywork 1 评论

    就是时间字段啦,他里面有选项的

    应该是日期字段,说错了
    Lsywork