// Package admin_system_login_log 提供管理员登录日志服务:写(Record,登录成功/失败落库)与读(List,分页查询)。 package admin_system_login_log import ( "context" "github.com/gogf/gf/v2/errors/gerror" "service.xpcool.com/internal/dao" "service.xpcool.com/internal/model/do" "service.xpcool.com/internal/model/dto" "service.xpcool.com/internal/model/entity" ) // LoginEvent 管理员登录日志事件。 type LoginEvent struct { Username string IP string UserAgent string Status int // 1 成功, 0 失败 FailReason string // 失败原因(成功时为空) } // IAdminLoginLog 登录日志服务接口:审计写入 + 分页查询。 type IAdminLoginLog interface { Record(context.Context, LoginEvent) error List(context.Context, dto.LoginLogQuery) ([]*dto.LoginLogItem, int, error) } var localAdminLoginLog IAdminLoginLog type adminLoginLog struct{} func AdminLoginLog() IAdminLoginLog { if localAdminLoginLog == nil { panic("AdminLoginLog implementation not registered") } return localAdminLoginLog } func RegisterAdminLoginLog(i IAdminLoginLog) { localAdminLoginLog = i } func NewAdminLoginLog() IAdminLoginLog { return &adminLoginLog{} } // Record 写入一条登录日志(成功或失败)。 func (s *adminLoginLog) Record(ctx context.Context, e LoginEvent) error { _, err := dao.AdminLoginLog.Ctx(ctx).Data(do.AdminLoginLog{ Username: e.Username, Ip: e.IP, UserAgent: e.UserAgent, Status: e.Status, FailReason: e.FailReason, }).Insert() return gerror.Wrap(err, "insert login log") } // List 分页查询管理员登录日志,支持账号与结果过滤(Status 为 nil 时不过滤)。 func (s *adminLoginLog) List(ctx context.Context, q dto.LoginLogQuery) ([]*dto.LoginLogItem, int, error) { m := dao.AdminLoginLog.Ctx(ctx) if q.Username != "" { m = m.WhereLike("username", "%"+q.Username+"%") } if q.Status != nil { m = m.Where(do.AdminLoginLog{Status: *q.Status}) } total, err := m.Count() if err != nil { return nil, 0, gerror.Wrap(err, "count login logs") } if total == 0 { return nil, 0, nil } var list []entity.AdminLoginLog if err = m.Page(q.Page, q.Size).OrderDesc("id").Scan(&list); err != nil { return nil, 0, gerror.Wrap(err, "query login logs") } items := make([]*dto.LoginLogItem, 0, len(list)) for i := range list { l := &list[i] items = append(items, &dto.LoginLogItem{ Id: l.Id, Username: l.Username, IP: l.Ip, UserAgent: l.UserAgent, Status: l.Status, FailReason: l.FailReason, CreatedAt: l.CreatedAt.Layout("2006-01-02 15:04:05"), }) } return items, total, nil }