package adminaudit import ( "time" "gorm.io/datatypes" "gorm.io/gorm" ) type Repository struct { db *gorm.DB } func NewRepository(db *gorm.DB) *Repository { return &Repository{db: db} } func (r *Repository) List(query Query) ([]LogDTO, error) { limit := query.Limit if limit <= 0 || limit > 500 { limit = 200 } db := r.db.Table("audit_logs AS al"). Select(`al.id, al.actor_type, al.actor_id, COALESCE(au.username, '') AS actor_username, COALESCE(au.nickname, '') AS actor_nickname, al.action, al.biz_type, al.biz_id, al.ip, al.user_agent, al.detail, al.created_at`). Joins("LEFT JOIN admin_users AS au ON au.id = al.actor_id AND al.actor_type = ?", "admin") if query.ActorID > 0 { db = db.Where("al.actor_id = ?", query.ActorID) } if query.Action != "" { db = db.Where("al.action = ?", query.Action) } if query.BizType != "" { db = db.Where("al.biz_type = ?", query.BizType) } var rows []auditLogRow if err := db.Order("al.id DESC").Limit(limit).Scan(&rows).Error; err != nil { return nil, err } items := make([]LogDTO, 0, len(rows)) for _, row := range rows { items = append(items, row.toDTO()) } return items, nil } type auditLogRow struct { ID uint64 ActorType string ActorID uint64 ActorUsername string ActorNickname string Action string BizType string BizID *uint64 IP string UserAgent string Detail datatypes.JSON CreatedAt time.Time } func (row auditLogRow) toDTO() LogDTO { return LogDTO{ ID: row.ID, ActorType: row.ActorType, ActorID: row.ActorID, ActorUsername: row.ActorUsername, ActorNickname: row.ActorNickname, Action: row.Action, BizType: row.BizType, BizID: row.BizID, IP: row.IP, UserAgent: row.UserAgent, Detail: row.Detail, CreatedAt: row.CreatedAt, } }