package admin import ( "time" "github.com/cloudreve/Cloudreve/v4/application/dependency" "github.com/cloudreve/Cloudreve/v4/inventory" "github.com/gin-gonic/gin" ) type ( LoginAuditListService struct { Page int `json:"page"` PageSize int `json:"page_size"` UserID *int `json:"user_id,omitempty"` IP string `json:"ip"` Status string `json:"status"` // success / fail / 空 全部 Username string `json:"username"` StartTime string `json:"start_time"` // RFC3339 EndTime string `json:"end_time"` // RFC3339 } LoginAuditListParamCtx struct{} LoginAuditDailyStatsService struct { Start string `json:"start" form:"start"` // RFC3339 或 YYYY-MM-DD End string `json:"end" form:"end"` Days int `json:"days" form:"days"` // 优先用此参数,默认7天 } LoginAuditDailyStatsParamCtx struct{} ) func parseTimeRange(start, end string, defaultDays int) (time.Time, time.Time) { now := time.Now().Truncate(24 * time.Hour) endTime := now startTime := endTime.AddDate(0, 0, -(defaultDays - 1)) if start != "" { if t, err := time.ParseInLocation(time.RFC3339, start, time.Local); err == nil { startTime = t.Truncate(24 * time.Hour) } else if t, err := time.ParseInLocation("2006-01-02", start, time.Local); err == nil { startTime = t } } if end != "" { if t, err := time.ParseInLocation(time.RFC3339, end, time.Local); err == nil { endTime = t.Truncate(24 * time.Hour) } else if t, err := time.ParseInLocation("2006-01-02", end, time.Local); err == nil { endTime = t } } // 如果 days > 0 优先 if defaultDays > 0 && start == "" && end == "" { endTime = now startTime = endTime.AddDate(0, 0, -(defaultDays - 1)) } return startTime, endTime } // List 分页查询登录审计 func (s *LoginAuditListService) List(c *gin.Context) (*inventory.LoginAuditListResult, error) { dep := dependency.FromContext(c) client := dep.LoginAuditClient() page := s.Page if page < 1 { page = 1 } pageSize := s.PageSize if pageSize < 1 { pageSize = 20 } if pageSize > 500 { pageSize = 500 } args := &inventory.LoginAuditListArgs{ Page: page, PageSize: pageSize, UserID: s.UserID, IP: s.IP, Username: s.Username, } switch s.Status { case "success": st := inventory.LoginAuditStatusSuccess args.Status = &st case "fail": st := inventory.LoginAuditStatusFail args.Status = &st } if s.StartTime != "" { if t, err := time.ParseInLocation(time.RFC3339, s.StartTime, time.Local); err == nil { args.StartTime = &t } else if t, err := time.ParseInLocation("2006-01-02", s.StartTime, time.Local); err == nil { args.StartTime = &t } } if s.EndTime != "" { if t, err := time.ParseInLocation(time.RFC3339, s.EndTime, time.Local); err == nil { args.EndTime = &t } else if t, err := time.ParseInLocation("2006-01-02", s.EndTime, time.Local); err == nil { // end_time 是该日的结束(+1 day,左闭右开) t = t.AddDate(0, 0, 1) args.EndTime = &t } } return client.List(c.Request.Context(), args) } // DailyStats 每日登录统计 func (s *LoginAuditDailyStatsService) DailyStats(c *gin.Context) ([]inventory.LoginAuditDailyItem, error) { dep := dependency.FromContext(c) client := dep.LoginAuditClient() days := s.Days if days < 1 { days = 7 } if days > 365 { days = 365 } start, end := parseTimeRange(s.Start, s.End, days) return client.DailyStats(c.Request.Context(), start, end) }