增加两个批量查询接口

This commit is contained in:
2025-11-16 16:30:26 +08:00
parent bf747e22ce
commit bf1600b385
10 changed files with 1041 additions and 11 deletions

View File

@@ -38,6 +38,29 @@ type ListPlansOptions struct {
PlanType PlanTypeFilter
}
// TaskListOptions 定义了查询任务时的可选参数
type TaskListOptions struct {
// --- 通用筛选 ---
Name *string // 按任务名称进行模糊查询
PlanID *uint32 // 按所属的计划ID进行精确查询
Type *models.TaskType // 按任务类型精确查询
// --- 关联筛选 ---
// 用于通过 device_tasks 关联表筛选与特定设备ID关联的任务
DeviceID *uint32
// --- JSON 参数内筛选 (仅对特定任务类型有效) ---
// 用于筛选 TaskTypeAreaCollectorThresholdCheck 类型的任务
AreaControllerID *uint32
// 用于筛选 TaskTypeDeviceThresholdCheck 和 TaskTypeAreaCollectorThresholdCheck 类型的任务
SensorType *models.SensorType
// 用于筛选 TaskTypeDeviceThresholdCheck 和 TaskTypeAreaCollectorThresholdCheck 类型的任务
Level *models.SeverityLevel
// --- 排序 ---
OrderBy string // 例如 "id desc"
}
// PlanRepository 定义了与计划模型相关的数据库操作接口
// 这是为了让业务逻辑层依赖于抽象,而不是具体的数据库实现
type PlanRepository interface {
@@ -89,6 +112,8 @@ type PlanRepository interface {
UpdatePlanStateAfterExecution(ctx context.Context, planID uint32, newCount uint32, newStatus models.PlanStatus) error
// ListTasksByDeviceID 根据设备ID获取关联任务列表
ListTasksByDeviceID(ctx context.Context, deviceID uint32) ([]*models.Task, error)
// ListTasks 支持分页和过滤的任务列表查询
ListTasks(ctx context.Context, opts TaskListOptions, page, pageSize int) ([]models.Task, int64, error)
}
// gormPlanRepository 是 PlanRepository 的 GORM 实现
@@ -896,3 +921,74 @@ func (r *gormPlanRepository) ListTasksByDeviceID(ctx context.Context, deviceID u
return tasks, nil
}
// ListTasks 实现了分页和过滤查询任务的功能,并优化了 JOIN 后的计数逻辑
func (r *gormPlanRepository) ListTasks(ctx context.Context, opts TaskListOptions, page, pageSize int) ([]models.Task, int64, error) {
repoCtx := logs.AddFuncName(ctx, r.ctx, "ListTasks")
if page <= 0 || pageSize <= 0 {
return nil, 0, ErrInvalidPagination
}
var results []models.Task
var total int64
// 1. 构建基础查询,应用所有筛选条件
query := r.db.WithContext(repoCtx).Model(&models.Task{})
if opts.Name != nil && *opts.Name != "" {
query = query.Where("tasks.name LIKE ?", "%"+*opts.Name+"%")
}
if opts.PlanID != nil {
query = query.Where("tasks.plan_id = ?", *opts.PlanID)
}
if opts.Type != nil {
query = query.Where("tasks.type = ?", *opts.Type)
}
// --- JSON 字段查询 ---
if opts.AreaControllerID != nil {
// 使用 ->> 操作符查询 JSON 字段的值(作为文本)
query = query.Where("parameters->>'area_controller_id' = ?", *opts.AreaControllerID)
}
if opts.SensorType != nil {
query = query.Where("parameters->>'sensor_type' = ?", *opts.SensorType)
}
if opts.Level != nil {
query = query.Where("parameters->>'level' = ?", *opts.Level)
}
// --- 结束 ---
if opts.DeviceID != nil {
query = query.Joins("JOIN device_tasks ON device_tasks.task_id = tasks.id").Where("device_tasks.device_id = ?", *opts.DeviceID)
}
// 2. 执行计数查询
countQuery := query
if opts.DeviceID != nil {
if err := countQuery.Distinct("tasks.id").Count(&total).Error; err != nil {
return nil, 0, err
}
} else {
if err := countQuery.Count(&total).Error; err != nil {
return nil, 0, err
}
}
if total == 0 {
return []models.Task{}, 0, nil
}
// 3. 为数据查询应用排序、分页和预加载
orderBy := "tasks.id DESC"
if opts.OrderBy != "" {
orderBy = opts.OrderBy
}
err := query.Order(orderBy).
Limit(pageSize).
Offset((page - 1) * pageSize).
Preload("Devices").
Find(&results).Error
return results, total, err
}