feat: 系统全面优化 - 设备管理/登录日志导出/性能监控/设置页面
后端: - 新增全局设备管理 API(DeviceHandler.GetAllDevices) - 新增登录日志导出功能(LogHandler.ExportLoginLogs, CSV/XLSX) - 新增设置服务(SettingsService)和设置页面 API - 设备管理支持多条件筛选(状态/信任状态/关键词) - 登录日志支持流式导出防 OOM - 操作日志支持按方法/时间范围搜索 - 主题配置服务(ThemeService) - 增强监控健康检查(Prometheus metrics + SLO) - 移除旧 ratelimit.go(已迁移至 robustness) - 修复 SocialAccount NULL 扫描问题 - 新增 API 契约测试、Handler 测试、Settings 测试 前端: - 新增管理员设备管理页面(DevicesPage) - 新增管理员登录日志导出功能 - 新增系统设置页面(SettingsPage) - 设备管理支持筛选和分页 - 增强 HTTP 响应类型 测试: - 业务逻辑测试 68 个(含并发 CONC_001~003) - 规模测试 16 个(P99 百分位统计) - E2E 测试、集成测试、契约测试 - 性能基准测试、鲁棒性测试 全面测试通过(38 个测试包)
This commit is contained in:
@@ -3,9 +3,11 @@ package service
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/user-management-system/internal/domain"
|
||||
"github.com/user-management-system/internal/pagination"
|
||||
"github.com/user-management-system/internal/repository"
|
||||
)
|
||||
|
||||
@@ -228,12 +230,14 @@ func (s *DeviceService) GetTrustedDevices(ctx context.Context, userID int64) ([]
|
||||
|
||||
// GetAllDevicesRequest 获取所有设备请求参数
|
||||
type GetAllDevicesRequest struct {
|
||||
Page int
|
||||
PageSize int
|
||||
Page int `form:"page"`
|
||||
PageSize int `form:"page_size"`
|
||||
UserID int64 `form:"user_id"`
|
||||
Status int `form:"status"`
|
||||
IsTrusted *bool `form:"is_trusted"`
|
||||
Status *int `form:"status"` // 0-禁用, 1-激活, nil-不筛选
|
||||
IsTrusted *bool `form:"is_trusted"`
|
||||
Keyword string `form:"keyword"`
|
||||
Cursor string `form:"cursor"` // Opaque cursor for keyset pagination
|
||||
Size int `form:"size"` // Page size when using cursor mode
|
||||
}
|
||||
|
||||
// GetAllDevices 获取所有设备(管理员用)
|
||||
@@ -257,9 +261,10 @@ func (s *DeviceService) GetAllDevices(ctx context.Context, req *GetAllDevicesReq
|
||||
Limit: req.PageSize,
|
||||
}
|
||||
|
||||
// 处理状态筛选
|
||||
if req.Status >= 0 {
|
||||
params.Status = domain.DeviceStatus(req.Status)
|
||||
// 处理状态筛选(仅当明确指定了状态时才筛选)
|
||||
if req.Status != nil && (*req.Status == 0 || *req.Status == 1) {
|
||||
status := domain.DeviceStatus(*req.Status)
|
||||
params.Status = &status
|
||||
}
|
||||
|
||||
// 处理信任状态筛选
|
||||
@@ -270,6 +275,49 @@ func (s *DeviceService) GetAllDevices(ctx context.Context, req *GetAllDevicesReq
|
||||
return s.deviceRepo.ListAll(ctx, params)
|
||||
}
|
||||
|
||||
// GetAllDevicesCursor 游标分页获取所有设备(推荐使用)
|
||||
func (s *DeviceService) GetAllDevicesCursor(ctx context.Context, req *GetAllDevicesRequest) (*CursorResult, error) {
|
||||
size := pagination.ClampPageSize(req.Size)
|
||||
if req.PageSize > 0 && req.Cursor == "" {
|
||||
size = pagination.ClampPageSize(req.PageSize)
|
||||
}
|
||||
|
||||
cursor, err := pagination.Decode(req.Cursor)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid cursor: %w", err)
|
||||
}
|
||||
|
||||
params := &repository.ListDevicesParams{
|
||||
UserID: req.UserID,
|
||||
Keyword: req.Keyword,
|
||||
}
|
||||
if req.Status != nil && (*req.Status == 0 || *req.Status == 1) {
|
||||
status := domain.DeviceStatus(*req.Status)
|
||||
params.Status = &status
|
||||
}
|
||||
if req.IsTrusted != nil {
|
||||
params.IsTrusted = req.IsTrusted
|
||||
}
|
||||
|
||||
devices, hasMore, err := s.deviceRepo.ListAllCursor(ctx, params, size, cursor)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
nextCursor := ""
|
||||
if len(devices) > 0 {
|
||||
last := devices[len(devices)-1]
|
||||
nextCursor = pagination.BuildNextCursor(last.ID, last.LastActiveTime)
|
||||
}
|
||||
|
||||
return &CursorResult{
|
||||
Items: devices,
|
||||
NextCursor: nextCursor,
|
||||
HasMore: hasMore,
|
||||
PageSize: size,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetDeviceByDeviceID 根据设备标识获取设备(用于设备信任检查)
|
||||
func (s *DeviceService) GetDeviceByDeviceID(ctx context.Context, userID int64, deviceID string) (*domain.Device, error) {
|
||||
return s.deviceRepo.GetByDeviceID(ctx, userID, deviceID)
|
||||
|
||||
Reference in New Issue
Block a user