ListPlanExecutionLogs
This commit is contained in:
		| @@ -118,3 +118,51 @@ func (c *Controller) ListDeviceCommandLogs(ctx *gin.Context) { | ||||
| 	c.logger.Infof("%s: 成功, 获取到 %d 条记录, 总计 %d 条", actionType, len(data), total) | ||||
| 	controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "获取设备命令日志成功", resp, actionType, "获取设备命令日志成功", req) | ||||
| } | ||||
|  | ||||
| // ListPlanExecutionLogs godoc | ||||
| // @Summary      获取计划执行日志列表 | ||||
| // @Description  根据提供的过滤条件,分页获取计划执行日志 | ||||
| // @Tags         数据监控 | ||||
| // @Security     BearerAuth | ||||
| // @Produce      json | ||||
| // @Param        query query dto.ListPlanExecutionLogRequest true "查询参数" | ||||
| // @Success      200 {object} controller.Response{data=dto.ListPlanExecutionLogResponse} | ||||
| // @Router       /api/v1/monitor/plan-execution-logs [get] | ||||
| func (c *Controller) ListPlanExecutionLogs(ctx *gin.Context) { | ||||
| 	const actionType = "获取计划执行日志列表" | ||||
|  | ||||
| 	var req dto.ListPlanExecutionLogRequest | ||||
| 	if err := ctx.ShouldBindQuery(&req); err != nil { | ||||
| 		c.logger.Errorf("%s: 参数绑定失败: %v", actionType, err) | ||||
| 		controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的查询参数: "+err.Error(), actionType, "参数绑定失败", req) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	opts := repository.PlanExecutionLogListOptions{ | ||||
| 		PlanID:    req.PlanID, | ||||
| 		OrderBy:   req.OrderBy, | ||||
| 		StartTime: req.StartTime, | ||||
| 		EndTime:   req.EndTime, | ||||
| 	} | ||||
| 	if req.Status != nil { | ||||
| 		status := models.ExecutionStatus(*req.Status) | ||||
| 		opts.Status = &status | ||||
| 	} | ||||
|  | ||||
| 	data, total, err := c.monitorService.ListPlanExecutionLogs(opts, req.Page, req.PageSize) | ||||
| 	if err != nil { | ||||
| 		if errors.Is(err, repository.ErrInvalidPagination) { | ||||
| 			c.logger.Warnf("%s: 无效的分页参数: %v", actionType, err) | ||||
| 			controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的分页参数: "+err.Error(), actionType, "无效分页参数", req) | ||||
| 			return | ||||
| 		} | ||||
|  | ||||
| 		c.logger.Errorf("%s: 服务层查询失败: %v", actionType, err) | ||||
| 		controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取计划执行日志失败: "+err.Error(), actionType, "服务层查询失败", req) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	resp := dto.NewListPlanExecutionLogResponse(data, total, req.Page, req.PageSize) | ||||
| 	c.logger.Infof("%s: 成功, 获取到 %d 条记录, 总计 %d 条", actionType, len(data), total) | ||||
| 	controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "获取计划执行日志成功", resp, actionType, "获取计划执行日志成功", req) | ||||
| } | ||||
|   | ||||
| @@ -117,3 +117,60 @@ func NewListDeviceCommandLogResponse(data []models.DeviceCommandLog, total int64 | ||||
| 		}, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // --- PlanExecutionLog --- | ||||
|  | ||||
| // ListPlanExecutionLogRequest 定义了获取计划执行日志列表的请求参数 | ||||
| type ListPlanExecutionLogRequest struct { | ||||
| 	Page      int        `form:"page,default=1"` | ||||
| 	PageSize  int        `form:"pageSize,default=10"` | ||||
| 	PlanID    *uint      `form:"plan_id"` | ||||
| 	Status    *string    `form:"status"` | ||||
| 	StartTime *time.Time `form:"start_time" time_format:"rfc3339"` | ||||
| 	EndTime   *time.Time `form:"end_time" time_format:"rfc3339"` | ||||
| 	OrderBy   string     `form:"order_by"` | ||||
| } | ||||
|  | ||||
| // PlanExecutionLogDTO 是用于API响应的计划执行日志结构 | ||||
| type PlanExecutionLogDTO struct { | ||||
| 	ID        uint                   `json:"id"` | ||||
| 	CreatedAt time.Time              `json:"created_at"` | ||||
| 	UpdatedAt time.Time              `json:"updated_at"` | ||||
| 	PlanID    uint                   `json:"plan_id"` | ||||
| 	Status    models.ExecutionStatus `json:"status"` | ||||
| 	StartedAt time.Time              `json:"started_at"` | ||||
| 	EndedAt   time.Time              `json:"ended_at"` | ||||
| 	Error     string                 `json:"error"` | ||||
| } | ||||
|  | ||||
| // ListPlanExecutionLogResponse 是获取计划执行日志列表的响应结构 | ||||
| type ListPlanExecutionLogResponse struct { | ||||
| 	List       []PlanExecutionLogDTO `json:"list"` | ||||
| 	Pagination PaginationDTO         `json:"pagination"` | ||||
| } | ||||
|  | ||||
| // NewListPlanExecutionLogResponse 从模型数据创建列表响应 DTO | ||||
| func NewListPlanExecutionLogResponse(data []models.PlanExecutionLog, total int64, page, pageSize int) *ListPlanExecutionLogResponse { | ||||
| 	dtos := make([]PlanExecutionLogDTO, len(data)) | ||||
| 	for i, item := range data { | ||||
| 		dtos[i] = PlanExecutionLogDTO{ | ||||
| 			ID:        item.ID, | ||||
| 			CreatedAt: item.CreatedAt, | ||||
| 			UpdatedAt: item.UpdatedAt, | ||||
| 			PlanID:    item.PlanID, | ||||
| 			Status:    item.Status, | ||||
| 			StartedAt: item.StartedAt, | ||||
| 			EndedAt:   item.EndedAt, | ||||
| 			Error:     item.Error, | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return &ListPlanExecutionLogResponse{ | ||||
| 		List: dtos, | ||||
| 		Pagination: PaginationDTO{ | ||||
| 			Total:    total, | ||||
| 			Page:     page, | ||||
| 			PageSize: pageSize, | ||||
| 		}, | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -9,6 +9,7 @@ import ( | ||||
| type MonitorService struct { | ||||
| 	sensorDataRepo       repository.SensorDataRepository | ||||
| 	deviceCommandLogRepo repository.DeviceCommandLogRepository | ||||
| 	executionLogRepo     repository.ExecutionLogRepository | ||||
| 	// 在这里可以添加其他超表模型的仓库依赖 | ||||
| } | ||||
|  | ||||
| @@ -16,10 +17,12 @@ type MonitorService struct { | ||||
| func NewMonitorService( | ||||
| 	sensorDataRepo repository.SensorDataRepository, | ||||
| 	deviceCommandLogRepo repository.DeviceCommandLogRepository, | ||||
| 	executionLogRepo repository.ExecutionLogRepository, | ||||
| ) *MonitorService { | ||||
| 	return &MonitorService{ | ||||
| 		sensorDataRepo:       sensorDataRepo, | ||||
| 		deviceCommandLogRepo: deviceCommandLogRepo, | ||||
| 		executionLogRepo:     executionLogRepo, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -32,3 +35,8 @@ func (s *MonitorService) ListSensorData(opts repository.SensorDataListOptions, p | ||||
| func (s *MonitorService) ListDeviceCommandLogs(opts repository.DeviceCommandLogListOptions, page, pageSize int) ([]models.DeviceCommandLog, int64, error) { | ||||
| 	return s.deviceCommandLogRepo.List(opts, page, pageSize) | ||||
| } | ||||
|  | ||||
| // ListPlanExecutionLogs 负责处理查询计划执行日志列表的业务逻辑 | ||||
| func (s *MonitorService) ListPlanExecutionLogs(opts repository.PlanExecutionLogListOptions, page, pageSize int) ([]models.PlanExecutionLog, int64, error) { | ||||
| 	return s.executionLogRepo.ListPlanExecutionLogs(opts, page, pageSize) | ||||
| } | ||||
|   | ||||
| @@ -8,9 +8,18 @@ import ( | ||||
| 	"gorm.io/gorm" | ||||
| ) | ||||
|  | ||||
| // PlanExecutionLogListOptions 定义了查询计划执行日志时的可选参数 | ||||
| type PlanExecutionLogListOptions struct { | ||||
| 	PlanID    *uint | ||||
| 	Status    *models.ExecutionStatus | ||||
| 	StartTime *time.Time // 基于 created_at 字段 | ||||
| 	EndTime   *time.Time // 基于 created_at 字段 | ||||
| 	OrderBy   string     // 例如 "created_at asc" | ||||
| } | ||||
|  | ||||
| // ExecutionLogRepository 定义了与执行日志交互的接口。 | ||||
| // 这为服务层提供了一个清晰的契约,并允许在测试中轻松地进行模拟。 | ||||
| type ExecutionLogRepository interface { | ||||
| 	// --- Existing methods --- | ||||
| 	UpdateTaskExecutionLogStatusByIDs(logIDs []uint, status models.ExecutionStatus) error | ||||
| 	UpdateTaskExecutionLogStatus(logID uint, status models.ExecutionStatus) error | ||||
| 	CreateTaskExecutionLog(log *models.TaskExecutionLog) error | ||||
| @@ -48,6 +57,9 @@ type ExecutionLogRepository interface { | ||||
|  | ||||
| 	// CancelIncompleteTasksByPlanLogID 取消一个计划执行中的所有未完成任务 | ||||
| 	CancelIncompleteTasksByPlanLogID(planLogID uint, reason string) error | ||||
|  | ||||
| 	// --- New method --- | ||||
| 	ListPlanExecutionLogs(opts PlanExecutionLogListOptions, page, pageSize int) ([]models.PlanExecutionLog, int64, error) | ||||
| } | ||||
|  | ||||
| // gormExecutionLogRepository 是使用 GORM 的具体实现。 | ||||
| @@ -56,18 +68,57 @@ type gormExecutionLogRepository struct { | ||||
| } | ||||
|  | ||||
| // NewGormExecutionLogRepository 创建一个新的执行日志仓库。 | ||||
| // 它接收一个 GORM DB 实例作为依赖。 | ||||
| func NewGormExecutionLogRepository(db *gorm.DB) ExecutionLogRepository { | ||||
| 	return &gormExecutionLogRepository{db: db} | ||||
| } | ||||
|  | ||||
| // ListPlanExecutionLogs 实现了分页和过滤查询计划执行日志的功能 | ||||
| func (r *gormExecutionLogRepository) ListPlanExecutionLogs(opts PlanExecutionLogListOptions, page, pageSize int) ([]models.PlanExecutionLog, int64, error) { | ||||
| 	if page <= 0 || pageSize <= 0 { | ||||
| 		return nil, 0, ErrInvalidPagination | ||||
| 	} | ||||
|  | ||||
| 	var results []models.PlanExecutionLog | ||||
| 	var total int64 | ||||
|  | ||||
| 	query := r.db.Model(&models.PlanExecutionLog{}) | ||||
|  | ||||
| 	if opts.PlanID != nil { | ||||
| 		query = query.Where("plan_id = ?", *opts.PlanID) | ||||
| 	} | ||||
| 	if opts.Status != nil { | ||||
| 		query = query.Where("status = ?", *opts.Status) | ||||
| 	} | ||||
| 	if opts.StartTime != nil { | ||||
| 		query = query.Where("created_at >= ?", *opts.StartTime) | ||||
| 	} | ||||
| 	if opts.EndTime != nil { | ||||
| 		query = query.Where("created_at <= ?", *opts.EndTime) | ||||
| 	} | ||||
|  | ||||
| 	if err := query.Count(&total).Error; err != nil { | ||||
| 		return nil, 0, err | ||||
| 	} | ||||
|  | ||||
| 	orderBy := "created_at DESC" | ||||
| 	if opts.OrderBy != "" { | ||||
| 		orderBy = opts.OrderBy | ||||
| 	} | ||||
| 	query = query.Order(orderBy) | ||||
|  | ||||
| 	offset := (page - 1) * pageSize | ||||
| 	err := query.Limit(pageSize).Offset(offset).Find(&results).Error | ||||
|  | ||||
| 	return results, total, err | ||||
| } | ||||
|  | ||||
| // --- Existing method implementations --- | ||||
|  | ||||
| func (r *gormExecutionLogRepository) UpdateTaskExecutionLogStatusByIDs(logIDs []uint, status models.ExecutionStatus) error { | ||||
| 	if len(logIDs) == 0 { | ||||
| 		return nil | ||||
| 	} | ||||
| 	return r.db.Model(&models.TaskExecutionLog{}). | ||||
| 		Where("id IN ?", logIDs). | ||||
| 		Update("status", status).Error | ||||
| 	return r.db.Model(&models.TaskExecutionLog{}).Where("id IN ?", logIDs).Update("status", status).Error | ||||
| } | ||||
|  | ||||
| func (r *gormExecutionLogRepository) UpdateTaskExecutionLogStatus(logID uint, status models.ExecutionStatus) error { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user