| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241 |
- package services
- import (
- "context"
- "fmt"
- "fwh-toolbox-server/cache"
- "fwh-toolbox-server/domain"
- "fwh-toolbox-server/repositories"
- "time"
- "go.uber.org/zap"
- )
- // 从数据库获取shutdown统计最新日期
- func GetShutdownStatisticsDate() (*string, error) {
- return getDashboardDate()
- }
- // 从数据库获取shutdown统计
- func GetShutdownStatistics(date *string) (*domain.ShutdownStatisticsDashboard, error) {
- currDate, err := getDashboardDate()
- if err != nil {
- return nil, err
- }
- var weekly *domain.ShutdownStatisticsArea[[7]uint]
- var yearly *domain.ShutdownStatisticsArea[[12]uint]
- if date == nil {
- date = currDate
- }
- weekly, err = getDashboardWeekly(*date)
- if err != nil {
- return nil, err
- }
- yearly, err = getDashboardYearly(*date)
- if err != nil {
- return nil, err
- }
- return &domain.ShutdownStatisticsDashboard{
- Date: *date,
- Weekly: *weekly,
- Yearly: *yearly,
- }, nil
- }
- // 从数据库获取shutdown统计信息详细数据
- func GetShutdownInfoMap(date *string) (*domain.ShutdownStatisticsItem, error) {
- currDate, err := getDashboardDate()
- if err != nil {
- return nil, err
- }
- if date == nil {
- date = currDate
- }
- return repositories.GetStatisticsShutdown(*date)
- }
- // 对Dashboard常规数据做缓存
- const (
- RedisKeyDashboardDate = "fwhtoolbox:dashboard:date"
- RedisKeyDashboardWeekly = "fwhtoolbox:dashboard:weekly"
- RedisKeyDashboardYearly = "fwhtoolbox:dashboard:yearly"
- )
- func getDashboardDate() (*string, error) {
- ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
- defer cancel()
- var date string
- err := cache.GetJSON(ctx, RedisKeyDashboardDate, &date)
- if err == nil {
- return &date, nil // 命中缓存
- }
- // 未命中缓存 → 查询数据库
- shutdownData, err := repositories.GetLatestStatisticsShutdown()
- if err != nil {
- return nil, err
- }
- date = shutdownData.Date
- // 缓存结果 24h
- cache.SetJSON(ctx, RedisKeyDashboardDate, date, time.Hour*24)
- return &date, nil
- }
- func getDashboardWeekly(date string) (*domain.ShutdownStatisticsArea[[7]uint], error) {
- ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
- defer cancel()
- // 未命中缓存 → 查询数据库
- currDate, err := getDashboardDate()
- if err != nil {
- return nil, err
- }
- // 判断给定日期是否最新
- if date == *currDate {
- var data domain.ShutdownStatisticsArea[[7]uint]
- err := cache.GetJSON(ctx, RedisKeyDashboardWeekly, &data)
- if err == nil {
- return &data, nil // 命中缓存
- }
- }
- shutdownDataList, err := handleWeeklyData(*currDate)
- if err != nil {
- return nil, err
- }
- // 缓存结果,只缓存最新日期
- if date == *currDate {
- cache.SetJSON(ctx, RedisKeyDashboardWeekly, shutdownDataList, time.Hour*24*7)
- }
- return shutdownDataList, nil
- }
- func getDashboardYearly(date string) (*domain.ShutdownStatisticsArea[[12]uint], error) {
- ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
- defer cancel()
- // 未命中缓存 → 查询数据库
- currDate, err := getDashboardDate()
- if err != nil {
- return nil, err
- }
- t_currDate, err := time.Parse(time.DateOnly, *currDate)
- if err != nil {
- return nil, err
- }
- t_date, err := time.Parse(time.DateOnly, date)
- if err != nil {
- return nil, err
- }
- // 判断是否同年
- if t_currDate.Year() == t_date.Year() {
- var data domain.ShutdownStatisticsArea[[12]uint]
- err := cache.GetJSON(ctx, RedisKeyDashboardYearly, &data)
- if err == nil {
- return &data, nil // 命中缓存
- }
- }
- currDateTime, err := time.Parse(time.DateOnly, *currDate)
- if err != nil {
- zap.L().Error("getDashboardYearly currDate日期格式错误", zap.String("currDate", *currDate))
- return nil, err
- }
- shutdownDataList, err := handleYearlyData(currDateTime.Year())
- if err != nil {
- return nil, err
- }
- // 缓存结果
- if t_currDate.Year() == t_date.Year() {
- cache.SetJSON(ctx, RedisKeyDashboardYearly, shutdownDataList, time.Hour*24*365)
- }
- return shutdownDataList, nil
- }
- func handleWeeklyData(date string) (*domain.ShutdownStatisticsArea[[7]uint], error) {
- timeDate, err := time.Parse(time.DateOnly, date)
- if err != nil {
- zap.L().Error("handleWeeklyData日期格式错误", zap.String("date", date))
- return nil, err
- }
- // 计算6天前的日期
- startDate := timeDate.AddDate(0, 0, -6).Format(time.DateOnly)
- dataList, err := repositories.GetStatisticsShutdownByDateRange(startDate, date)
- if err != nil {
- zap.L().Error("GetStatisticsShutdownByDateRange error.", zap.String("err", err.Error()))
- return nil, err
- }
- var res domain.ShutdownStatisticsArea[[7]uint]
- for _, d := range dataList {
- t, err := time.Parse(time.DateOnly, d.Date)
- if err != nil {
- zap.L().Error("handleWeeklyData日期格式错误", zap.String("date", d.Date))
- return nil, err
- }
- diff := timeDate.Sub(t)
- // 转为天数(取整)
- days := int(diff.Hours() / 24)
- idx := 6 - days
- if idx < 0 || idx >= 7 {
- continue
- }
- res.ALL[idx] = d.Count.ALL
- res.US[idx] = d.Count.US
- res.AU[idx] = d.Count.AU
- }
- return &res, nil
- }
- func handleYearlyData(year int) (*domain.ShutdownStatisticsArea[[12]uint], error) {
- // 判断年份是否有效
- if year < 2000 || year > (time.Now().Year()+1) {
- return nil, fmt.Errorf("handleYearlyData年份不正确 year = %d", year)
- }
- var yearList domain.ShutdownStatisticsArea[[12]uint]
- for month := 1; month <= 12; month++ {
- // 每个月的第一天
- start := time.Date(year, time.Month(month), 1, 0, 0, 0, 0, time.Local)
- // 下个月的第一天再减1天 = 本月最后一天
- end := start.AddDate(0, 1, -1)
- // 获取月数据
- dataList, err := repositories.GetStatisticsShutdownByDateRange(start.Format(time.DateOnly), end.Format(time.DateOnly))
- if err != nil {
- zap.L().Error("GetStatisticsShutdownByDateRange error.", zap.String("err", err.Error()))
- return nil, err
- }
- // 计算月总数
- var monthCount domain.ShutdownStatisticsArea[uint]
- for _, d := range dataList {
- monthCount.ALL = monthCount.ALL + d.Count.ALL
- monthCount.US = monthCount.US + d.Count.US
- monthCount.AU = monthCount.AU + d.Count.AU
- }
- yearList.ALL[month-1] = monthCount.ALL
- yearList.US[month-1] = monthCount.US
- yearList.AU[month-1] = monthCount.AU
- }
- return &yearList, nil
- }
|