service.xpcool.com/internal/service/admin/system/login_log/login_log.go
夏犀麟 4b3c00270f
Some checks failed
Build and Deploy (service.xpcool.com) / build-and-deploy (push) Failing after 31s
feat(i18n): 中文化校验提示与服务层错误信息
将 api 层校验规则提示语、service 层 gerror.Wrap 与 response.Error
错误信息、panic 未注册提示统一改为中文,并同步中文化 cmd 路由注释
与变更记录。仅涉及注释、文档与字符串改动,无业务逻辑变更。
2026-09-13 23:22:46 +08:00

84 lines
2.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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 实现未注册")
}
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, "写入登录日志失败")
}
// 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, "统计登录日志总数失败")
}
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, "查询登录日志列表失败")
}
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
}