feat: backend core - auth, user, role, permission, device, webhook, monitoring, cache, repository, service, middleware, API handlers
2026-04-02 11:19:50 +08:00
|
|
|
package repository
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"context"
|
|
|
|
|
"time"
|
|
|
|
|
|
|
|
|
|
"gorm.io/gorm"
|
|
|
|
|
|
|
|
|
|
"github.com/user-management-system/internal/domain"
|
2026-04-07 12:08:16 +08:00
|
|
|
"github.com/user-management-system/internal/pagination"
|
feat: backend core - auth, user, role, permission, device, webhook, monitoring, cache, repository, service, middleware, API handlers
2026-04-02 11:19:50 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// OperationLogRepository 操作日志仓储
|
|
|
|
|
type OperationLogRepository struct {
|
|
|
|
|
db *gorm.DB
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// NewOperationLogRepository 创建操作日志仓储
|
|
|
|
|
func NewOperationLogRepository(db *gorm.DB) *OperationLogRepository {
|
|
|
|
|
return &OperationLogRepository{db: db}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Create 创建操作日志
|
|
|
|
|
func (r *OperationLogRepository) Create(ctx context.Context, log *domain.OperationLog) error {
|
|
|
|
|
return r.db.WithContext(ctx).Create(log).Error
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GetByID 根据ID获取操作日志
|
|
|
|
|
func (r *OperationLogRepository) GetByID(ctx context.Context, id int64) (*domain.OperationLog, error) {
|
|
|
|
|
var log domain.OperationLog
|
|
|
|
|
if err := r.db.WithContext(ctx).First(&log, id).Error; err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
return &log, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ListByUserID 获取用户的操作日志列表
|
|
|
|
|
func (r *OperationLogRepository) ListByUserID(ctx context.Context, userID int64, offset, limit int) ([]*domain.OperationLog, int64, error) {
|
|
|
|
|
var logs []*domain.OperationLog
|
|
|
|
|
var total int64
|
|
|
|
|
query := r.db.WithContext(ctx).Model(&domain.OperationLog{}).Where("user_id = ?", userID)
|
|
|
|
|
if err := query.Count(&total).Error; err != nil {
|
|
|
|
|
return nil, 0, err
|
|
|
|
|
}
|
|
|
|
|
if err := query.Order("created_at DESC").Offset(offset).Limit(limit).Find(&logs).Error; err != nil {
|
|
|
|
|
return nil, 0, err
|
|
|
|
|
}
|
|
|
|
|
return logs, total, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// List 获取操作日志列表(管理员用)
|
|
|
|
|
func (r *OperationLogRepository) List(ctx context.Context, offset, limit int) ([]*domain.OperationLog, int64, error) {
|
|
|
|
|
var logs []*domain.OperationLog
|
|
|
|
|
var total int64
|
|
|
|
|
query := r.db.WithContext(ctx).Model(&domain.OperationLog{})
|
|
|
|
|
if err := query.Count(&total).Error; err != nil {
|
|
|
|
|
return nil, 0, err
|
|
|
|
|
}
|
|
|
|
|
if err := query.Order("created_at DESC").Offset(offset).Limit(limit).Find(&logs).Error; err != nil {
|
|
|
|
|
return nil, 0, err
|
|
|
|
|
}
|
|
|
|
|
return logs, total, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ListByMethod 按HTTP方法查询操作日志
|
|
|
|
|
func (r *OperationLogRepository) ListByMethod(ctx context.Context, method string, offset, limit int) ([]*domain.OperationLog, int64, error) {
|
|
|
|
|
var logs []*domain.OperationLog
|
|
|
|
|
var total int64
|
|
|
|
|
query := r.db.WithContext(ctx).Model(&domain.OperationLog{}).Where("request_method = ?", method)
|
|
|
|
|
if err := query.Count(&total).Error; err != nil {
|
|
|
|
|
return nil, 0, err
|
|
|
|
|
}
|
|
|
|
|
if err := query.Order("created_at DESC").Offset(offset).Limit(limit).Find(&logs).Error; err != nil {
|
|
|
|
|
return nil, 0, err
|
|
|
|
|
}
|
|
|
|
|
return logs, total, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ListByTimeRange 按时间范围查询操作日志
|
|
|
|
|
func (r *OperationLogRepository) ListByTimeRange(ctx context.Context, start, end time.Time, offset, limit int) ([]*domain.OperationLog, int64, error) {
|
|
|
|
|
var logs []*domain.OperationLog
|
|
|
|
|
var total int64
|
|
|
|
|
query := r.db.WithContext(ctx).Model(&domain.OperationLog{}).
|
|
|
|
|
Where("created_at >= ? AND created_at <= ?", start, end)
|
|
|
|
|
if err := query.Count(&total).Error; err != nil {
|
|
|
|
|
return nil, 0, err
|
|
|
|
|
}
|
|
|
|
|
if err := query.Order("created_at DESC").Offset(offset).Limit(limit).Find(&logs).Error; err != nil {
|
|
|
|
|
return nil, 0, err
|
|
|
|
|
}
|
|
|
|
|
return logs, total, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// DeleteOlderThan 删除指定天数前的日志
|
|
|
|
|
func (r *OperationLogRepository) DeleteOlderThan(ctx context.Context, days int) error {
|
|
|
|
|
cutoff := time.Now().AddDate(0, 0, -days)
|
|
|
|
|
return r.db.WithContext(ctx).Where("created_at < ?", cutoff).Delete(&domain.OperationLog{}).Error
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Search 按关键词搜索操作日志
|
|
|
|
|
func (r *OperationLogRepository) Search(ctx context.Context, keyword string, offset, limit int) ([]*domain.OperationLog, int64, error) {
|
|
|
|
|
var logs []*domain.OperationLog
|
|
|
|
|
var total int64
|
|
|
|
|
query := r.db.WithContext(ctx).Model(&domain.OperationLog{}).
|
|
|
|
|
Where("operation_name LIKE ? OR request_path LIKE ? OR operation_type LIKE ?",
|
|
|
|
|
"%"+keyword+"%", "%"+keyword+"%", "%"+keyword+"%")
|
|
|
|
|
if err := query.Count(&total).Error; err != nil {
|
|
|
|
|
return nil, 0, err
|
|
|
|
|
}
|
|
|
|
|
if err := query.Order("created_at DESC").Offset(offset).Limit(limit).Find(&logs).Error; err != nil {
|
|
|
|
|
return nil, 0, err
|
|
|
|
|
}
|
|
|
|
|
return logs, total, nil
|
|
|
|
|
}
|
2026-04-07 12:08:16 +08:00
|
|
|
|
|
|
|
|
// ListCursor 游标分页查询操作日志(管理员用)
|
|
|
|
|
// Uses keyset pagination: WHERE (created_at < ? OR (created_at = ? AND id < ?))
|
|
|
|
|
func (r *OperationLogRepository) ListCursor(ctx context.Context, limit int, cursor *pagination.Cursor) ([]*domain.OperationLog, bool, error) {
|
|
|
|
|
var logs []*domain.OperationLog
|
|
|
|
|
|
|
|
|
|
query := r.db.WithContext(ctx).Model(&domain.OperationLog{})
|
|
|
|
|
|
|
|
|
|
if cursor != nil && cursor.LastID > 0 {
|
|
|
|
|
query = query.Where(
|
|
|
|
|
"(created_at < ? OR (created_at = ? AND id < ?))",
|
|
|
|
|
cursor.LastValue, cursor.LastValue, cursor.LastID,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if err := query.Order("created_at DESC, id DESC").Limit(limit + 1).Find(&logs).Error; err != nil {
|
|
|
|
|
return nil, false, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
hasMore := len(logs) > limit
|
|
|
|
|
if hasMore {
|
|
|
|
|
logs = logs[:limit]
|
|
|
|
|
}
|
|
|
|
|
return logs, hasMore, nil
|
|
|
|
|
}
|