fix(v1.11.5): 深渊日历按单周期显示 1/1 或 0/1,工作台与大屏同步
build / build-and-test (push) Successful in 3m26s

- 整段色块计数改为按当前格所在周期:cycleDone → 1/1,否则 0/1;
  不再把全局 used/total 重复到每一格。
- 抽出 blockCellText / blockCellPercent,工作台、大屏、客户自助页共用同一口径;
  通行证保持 0/1 / 1/1,深渊按所在周期 1/1 / 0/1。
- 大屏恢复通行证 / 深渊页签;screenCalSubs 补上缺失的 start(之前为零值,
  导致大屏周期判定和色阶都算错),大屏格子现在显示与工作台一致的 1/1、0/1
  以及 34%→4% 的周期色阶。
- 大屏色块样式:has-block / scr-block,亮暗两套都可读。
- 版本 1.11.5;README 的深渊说明同步,「工作台、大屏、客户自助页同一口径」。

验证:测试数据第一周期完成、第二周期未完成,工作台、 大屏、客户自助页均显示
20–26 为 1/1、27–31 为 0/1;周期浓度 34%/24%/14%/4%;gofmt / go vet /
go test 全绿。
This commit is contained in:
2026-10-20 04:06:39 +08:00
parent 2e2d7d4bdd
commit 0392f44cf1
7 changed files with 88 additions and 44 deletions
+37 -24
View File
@@ -21,6 +21,11 @@ type screenDay struct {
Done int
Urgent int
Heat int
// 通行证 / 深渊整段色块:BlockText 是该周期的 1/1 或 0/1
BlockColor string
BlockText string
BlockTitle string
BlockPercent int
// Strip 打手色竖条(去重)
Strip []string
}
@@ -66,7 +71,13 @@ func (s *Server) screenCalSubs(from, to string, pkgID int64, tag string) ([]calS
warn := s.warnDays()
list := make([]calSub, 0, len(subs))
for _, sub := range subs {
cs := calSub{sub: sub, pauses: pauses[sub.ID], checkins: checkins[sub.ID], eval: sub.Eval(today, warn)}
cs := calSub{
sub: sub,
start: domain.ParseDateOr(sub.StartDate, today),
pauses: pauses[sub.ID],
checkins: checkins[sub.ID],
eval: sub.Eval(today, warn),
}
if sub.EndDate != "" {
cs.hasEnd = true
cs.end = domain.ParseDateOr(sub.EndDate, today)
@@ -138,15 +149,30 @@ func (s *Server) handleScreen(w http.ResponseWriter, r *http.Request) {
count, doneN, urgentN := 0, 0, 0
strip := []string{}
seenColor := map[string]bool{}
sd := screenDay{
Date: ds,
Day: d.Day(),
InMonth: d.Month() == today.Month(),
IsToday: ds == domain.Date(today),
IsPast: d.Before(today),
}
for _, cs := range list {
if heatMode == "due" {
if cs.sub.EndDate == ds {
count++
}
}
// 通行证 / 深渊是整段型:不计入每日待完成热力,但用整段色块显示周期状态。
if cs.isBlock() {
if cs.blockCovers(ds) && sd.BlockText == "" {
sd.BlockColor = cs.sub.PackageColor
sd.BlockText = blockCellText(cs, ds)
sd.BlockTitle = cs.sub.PackageName + " · " + sd.BlockText
sd.BlockPercent = blockCellPercent(cs, d)
}
continue
}
// 通行证 / 深渊是整段型,不计入「每日待完成」热力
if cs.isBlock() {
if heatMode == "due" {
continue
}
if !cs.covers(ds) {
@@ -173,18 +199,12 @@ func (s *Server) handleScreen(w http.ResponseWriter, r *http.Request) {
if d.Month() == today.Month() {
data.HeatTotal += count
}
week = append(week, screenDay{
Date: ds,
Day: d.Day(),
InMonth: d.Month() == today.Month(),
IsToday: ds == domain.Date(today),
IsPast: d.Before(today),
Count: count + doneN,
Done: doneN,
Urgent: urgentN,
Heat: heatLevel(count),
Strip: strip,
})
sd.Count = count + doneN
sd.Done = doneN
sd.Urgent = urgentN
sd.Heat = heatLevel(count)
sd.Strip = strip
week = append(week, sd)
}
data.Weeks = append(data.Weeks, week)
}
@@ -214,16 +234,9 @@ func (s *Server) handleScreen(w http.ResponseWriter, r *http.Request) {
data.Recent = adj
}
// 页签:按标签合并 + 独立显示另开;通行证/深渊不计每日热力,不放大屏页签
// 页签:按标签合并 + 独立显示另开;通行证 / 深渊也放进大屏,用整段色块显示周期状态
pkgs, _ := s.db.ListPackages(true)
screenPkgs := make([]store.Package, 0, len(pkgs))
for _, p := range pkgs {
if p.Season || p.Abyss {
continue
}
screenPkgs = append(screenPkgs, p)
}
data.Tabs, data.HasTabs = buildCalendarTabs(screenPkgs, nil, 0)
data.Tabs, data.HasTabs = buildCalendarTabs(pkgs, nil, 0)
for i := range data.Tabs {
t := &data.Tabs[i]
href := "/screen?heat=" + heatMode