@@ -0,0 +1,134 @@
|
||||
package web
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"daili/internal/domain"
|
||||
"daili/internal/store"
|
||||
)
|
||||
|
||||
type screenDay struct {
|
||||
Date string
|
||||
Day int
|
||||
InMonth bool
|
||||
IsToday bool
|
||||
IsPast bool
|
||||
Due int
|
||||
Heat int
|
||||
}
|
||||
|
||||
type screenData struct {
|
||||
Stats *store.Stats
|
||||
MonthTitle string
|
||||
Year, Month int
|
||||
Weeks [][]screenDay
|
||||
Weekdays []string
|
||||
Top []SubView
|
||||
DueToday []SubView
|
||||
TodayList []SubView
|
||||
Recent []store.Adjustment
|
||||
TodayTasks int
|
||||
TodayDone int
|
||||
Refresh int
|
||||
Version string
|
||||
}
|
||||
|
||||
func (s *Server) handleScreen(w http.ResponseWriter, r *http.Request) {
|
||||
today := domain.Today()
|
||||
warn := s.warnDays()
|
||||
stats, err := s.db.ScreenStats(today, warn)
|
||||
if err != nil {
|
||||
http.Error(w, "读取大屏数据失败", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
data := &screenData{
|
||||
Stats: stats,
|
||||
MonthTitle: fmt.Sprintf("%d 年 %d 月", today.Year(), int(today.Month())),
|
||||
Year: today.Year(),
|
||||
Month: int(today.Month()),
|
||||
Weekdays: []string{"一", "二", "三", "四", "五", "六", "日"},
|
||||
Top: subViews(stats.Top, today, warn),
|
||||
DueToday: subViews(stats.DueTodaySubs, today, warn),
|
||||
Refresh: s.screenRefresh(),
|
||||
Version: s.cfg.Version,
|
||||
}
|
||||
if len(data.DueToday) > 6 {
|
||||
data.DueToday = data.DueToday[:6]
|
||||
}
|
||||
|
||||
// 本月热力
|
||||
monthStart := domain.MonthStart(today.Year(), today.Month())
|
||||
monthEnd := domain.MonthEnd(today.Year(), today.Month())
|
||||
gridStart := domain.AddDays(monthStart, -domain.WeekdayIndex(monthStart))
|
||||
weeks := (domain.WeekdayIndex(monthStart) + monthEnd.Day() + 6) / 7
|
||||
for wi := 0; wi < weeks; wi++ {
|
||||
week := make([]screenDay, 0, 7)
|
||||
for di := 0; di < 7; di++ {
|
||||
d := domain.AddDays(gridStart, wi*7+di)
|
||||
ds := domain.Date(d)
|
||||
due := stats.Heat[ds]
|
||||
week = append(week, screenDay{
|
||||
Date: ds,
|
||||
Day: d.Day(),
|
||||
InMonth: d.Month() == today.Month(),
|
||||
IsToday: ds == domain.Date(today),
|
||||
IsPast: d.Before(today),
|
||||
Due: due,
|
||||
Heat: heatLevel(due),
|
||||
})
|
||||
}
|
||||
data.Weeks = append(data.Weeks, week)
|
||||
}
|
||||
|
||||
if adj, err := s.db.RecentAdjustments(6); err == nil {
|
||||
data.Recent = adj
|
||||
}
|
||||
list, done := s.todayTaskList(today)
|
||||
data.TodayTasks = len(list)
|
||||
data.TodayDone = done
|
||||
data.TodayList = subViews(list, today, warn)
|
||||
|
||||
p := s.newPage(r, "大屏", "screen")
|
||||
p.D = data
|
||||
s.render(w, r, "screen", p)
|
||||
}
|
||||
|
||||
// todayTaskList 返回今天应服务的订阅与已完成数量。
|
||||
func (s *Server) todayTaskList(today time.Time) ([]store.Subscription, int) {
|
||||
ts := domain.Date(today)
|
||||
subs, err := s.db.CalendarSubs(ts, ts)
|
||||
if err != nil {
|
||||
return nil, 0
|
||||
}
|
||||
ids := make([]int64, 0, len(subs))
|
||||
for _, sub := range subs {
|
||||
ids = append(ids, sub.ID)
|
||||
}
|
||||
pauses, _ := s.db.PausesForSubs(ids)
|
||||
checkins, _ := s.db.CheckinsBetween(ts, ts)
|
||||
warn := s.warnDays()
|
||||
out := []store.Subscription{}
|
||||
done := 0
|
||||
for _, sub := range subs {
|
||||
if sub.Status == domain.StatusClosed {
|
||||
continue
|
||||
}
|
||||
if sub.StartDate > ts || sub.EndDate == "" || sub.EndDate < ts {
|
||||
continue
|
||||
}
|
||||
cs := calSub{sub: sub, pauses: pauses[sub.ID], hasEnd: true, eval: sub.Eval(today, warn)}
|
||||
if sub.Unit == domain.UnitCount && cs.eval.RemainingCount <= 0 {
|
||||
continue
|
||||
}
|
||||
if cs.pausedOn(ts) {
|
||||
continue
|
||||
}
|
||||
out = append(out, sub)
|
||||
if ci, ok := checkins[sub.ID][ts]; ok && ci.Status == "done" {
|
||||
done++
|
||||
}
|
||||
}
|
||||
return out, done
|
||||
}
|
||||
Reference in New Issue
Block a user