package monitor import ( "errors" "git.huangwc.com/pig/pig-farm-controller/internal/app/controller" "git.huangwc.com/pig/pig-farm-controller/internal/app/dto" "git.huangwc.com/pig/pig-farm-controller/internal/app/service" "git.huangwc.com/pig/pig-farm-controller/internal/infra/logs" "git.huangwc.com/pig/pig-farm-controller/internal/infra/models" "git.huangwc.com/pig/pig-farm-controller/internal/infra/repository" "github.com/gin-gonic/gin" ) // Controller 监控控制器,封装了所有与数据监控相关的业务逻辑 type Controller struct { monitorService *service.MonitorService logger *logs.Logger } // NewController 创建一个新的监控控制器实例 func NewController(monitorService *service.MonitorService, logger *logs.Logger) *Controller { return &Controller{ monitorService: monitorService, logger: logger, } } // ListSensorData godoc // @Summary 获取传感器数据列表 // @Description 根据提供的过滤条件,分页获取传感器数据 // @Tags 数据监控 // @Security BearerAuth // @Produce json // @Param query query dto.ListSensorDataRequest true "查询参数" // @Success 200 {object} controller.Response{data=dto.ListSensorDataResponse} // @Router /api/v1/monitor/sensor-data [get] func (c *Controller) ListSensorData(ctx *gin.Context) { const actionType = "获取传感器数据列表" var req dto.ListSensorDataRequest 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.SensorDataListOptions{ DeviceID: req.DeviceID, OrderBy: req.OrderBy, StartTime: req.StartTime, EndTime: req.EndTime, } if req.SensorType != nil { sensorType := models.SensorType(*req.SensorType) opts.SensorType = &sensorType } data, total, err := c.monitorService.ListSensorData(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.NewListSensorDataResponse(data, total, req.Page, req.PageSize) c.logger.Infof("%s: 成功, 获取到 %d 条记录, 总计 %d 条", actionType, len(data), total) controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "获取传感器数据成功", resp, actionType, "获取传感器数据成功", req) } // ListDeviceCommandLogs godoc // @Summary 获取设备命令日志列表 // @Description 根据提供的过滤条件,分页获取设备命令日志 // @Tags 数据监控 // @Security BearerAuth // @Produce json // @Param query query dto.ListDeviceCommandLogRequest true "查询参数" // @Success 200 {object} controller.Response{data=dto.ListDeviceCommandLogResponse} // @Router /api/v1/monitor/device-command-logs [get] func (c *Controller) ListDeviceCommandLogs(ctx *gin.Context) { const actionType = "获取设备命令日志列表" var req dto.ListDeviceCommandLogRequest 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.DeviceCommandLogListOptions{ DeviceID: req.DeviceID, ReceivedSuccess: req.ReceivedSuccess, OrderBy: req.OrderBy, StartTime: req.StartTime, EndTime: req.EndTime, } data, total, err := c.monitorService.ListDeviceCommandLogs(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.NewListDeviceCommandLogResponse(data, total, req.Page, req.PageSize) 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) } // ListTaskExecutionLogs godoc // @Summary 获取任务执行日志列表 // @Description 根据提供的过滤条件,分页获取任务执行日志 // @Tags 数据监控 // @Security BearerAuth // @Produce json // @Param query query dto.ListTaskExecutionLogRequest true "查询参数" // @Success 200 {object} controller.Response{data=dto.ListTaskExecutionLogResponse} // @Router /api/v1/monitor/task-execution-logs [get] func (c *Controller) ListTaskExecutionLogs(ctx *gin.Context) { const actionType = "获取任务执行日志列表" var req dto.ListTaskExecutionLogRequest 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.TaskExecutionLogListOptions{ PlanExecutionLogID: req.PlanExecutionLogID, TaskID: req.TaskID, 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.ListTaskExecutionLogs(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.NewListTaskExecutionLogResponse(data, total, req.Page, req.PageSize) c.logger.Infof("%s: 成功, 获取到 %d 条记录, 总计 %d 条", actionType, len(data), total) controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "获取任务执行日志成功", resp, actionType, "获取任务执行日志成功", req) } // ListPendingCollections godoc // @Summary 获取待采集请求列表 // @Description 根据提供的过滤条件,分页获取待采集请求 // @Tags 数据监控 // @Security BearerAuth // @Produce json // @Param query query dto.ListPendingCollectionRequest true "查询参数" // @Success 200 {object} controller.Response{data=dto.ListPendingCollectionResponse} // @Router /api/v1/monitor/pending-collections [get] func (c *Controller) ListPendingCollections(ctx *gin.Context) { const actionType = "获取待采集请求列表" var req dto.ListPendingCollectionRequest 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.PendingCollectionListOptions{ DeviceID: req.DeviceID, OrderBy: req.OrderBy, StartTime: req.StartTime, EndTime: req.EndTime, } if req.Status != nil { status := models.PendingCollectionStatus(*req.Status) opts.Status = &status } data, total, err := c.monitorService.ListPendingCollections(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.NewListPendingCollectionResponse(data, total, req.Page, req.PageSize) c.logger.Infof("%s: 成功, 获取到 %d 条记录, 总计 %d 条", actionType, len(data), total) controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "获取待采集请求成功", resp, actionType, "获取待采集请求成功", req) } // ListUserActionLogs godoc // @Summary 获取用户操作日志列表 // @Description 根据提供的过滤条件,分页获取用户操作日志 // @Tags 数据监控 // @Security BearerAuth // @Produce json // @Param query query dto.ListUserActionLogRequest true "查询参数" // @Success 200 {object} controller.Response{data=dto.ListUserActionLogResponse} // @Router /api/v1/monitor/user-action-logs [get] func (c *Controller) ListUserActionLogs(ctx *gin.Context) { const actionType = "获取用户操作日志列表" var req dto.ListUserActionLogRequest 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.UserActionLogListOptions{ UserID: req.UserID, Username: req.Username, ActionType: req.ActionType, OrderBy: req.OrderBy, StartTime: req.StartTime, EndTime: req.EndTime, } if req.Status != nil { status := models.AuditStatus(*req.Status) opts.Status = &status } data, total, err := c.monitorService.ListUserActionLogs(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.NewListUserActionLogResponse(data, total, req.Page, req.PageSize) c.logger.Infof("%s: 成功, 获取到 %d 条记录, 总计 %d 条", actionType, len(data), total) controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "获取用户操作日志成功", resp, actionType, "获取用户操作日志成功", req) } // ListRawMaterialPurchases godoc // @Summary 获取原料采购记录列表 // @Description 根据提供的过滤条件,分页获取原料采购记录 // @Tags 数据监控 // @Security BearerAuth // @Produce json // @Param query query dto.ListRawMaterialPurchaseRequest true "查询参数" // @Success 200 {object} controller.Response{data=dto.ListRawMaterialPurchaseResponse} // @Router /api/v1/monitor/raw-material-purchases [get] func (c *Controller) ListRawMaterialPurchases(ctx *gin.Context) { const actionType = "获取原料采购记录列表" var req dto.ListRawMaterialPurchaseRequest 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.RawMaterialPurchaseListOptions{ RawMaterialID: req.RawMaterialID, Supplier: req.Supplier, OrderBy: req.OrderBy, StartTime: req.StartTime, EndTime: req.EndTime, } data, total, err := c.monitorService.ListRawMaterialPurchases(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.NewListRawMaterialPurchaseResponse(data, total, req.Page, req.PageSize) c.logger.Infof("%s: 成功, 获取到 %d 条记录, 总计 %d 条", actionType, len(data), total) controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "获取原料采购记录成功", resp, actionType, "获取原料采购记录成功", req) }