diff --git a/internal/app/controller/device/device_controller.go b/internal/app/controller/device/device_controller.go index 92d6c6f..41ac035 100644 --- a/internal/app/controller/device/device_controller.go +++ b/internal/app/controller/device/device_controller.go @@ -123,14 +123,14 @@ func (c *Controller) CreateDevice(ctx *gin.Context) { const actionType = "创建设备" var req CreateDeviceRequest if err := ctx.ShouldBindJSON(&req); err != nil { - c.logger.Errorf("创建设备: 参数绑定失败: %v", err) + c.logger.Errorf("%s: 参数绑定失败: %v", actionType, err) controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的请求体: "+err.Error(), actionType, "请求体绑定失败", req) return } propertiesJSON, err := json.Marshal(req.Properties) if err != nil { - c.logger.Errorf("创建设备: 序列化属性失败: %v", err) + c.logger.Errorf("%s: 序列化属性失败: %v", actionType, err) controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "属性字段格式错误", actionType, "属性序列化失败", req.Properties) return } @@ -146,24 +146,25 @@ func (c *Controller) CreateDevice(ctx *gin.Context) { // 在创建设备前进行自检 if !device.SelfCheck() { - c.logger.Errorf("创建设备: 设备属性自检失败: %v", device) + c.logger.Errorf("%s: 设备属性自检失败: %v", actionType, device) controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "设备属性不符合要求", actionType, "设备属性自检失败", device) return } if err := c.repo.Create(device); err != nil { - c.logger.Errorf("创建设备: 数据库操作失败: %v", err) + c.logger.Errorf("%s: 数据库操作失败: %v", actionType, err) controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "创建设备失败: "+err.Error(), actionType, "数据库创建失败", device) return } resp, err := newDeviceResponse(device) if err != nil { - c.logger.Errorf("创建设备: 序列化响应失败: %v", err) + c.logger.Errorf("%s: 序列化响应失败: %v", actionType, err) controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "设备创建成功,但响应生成失败", actionType, "响应序列化失败", device) return } + c.logger.Infof("%s: 设备创建成功, ID: %d", actionType, device.ID) controller.SendSuccessWithAudit(ctx, controller.CodeCreated, "设备创建成功", resp, actionType, "设备创建成功", resp) } @@ -179,28 +180,37 @@ func (c *Controller) GetDevice(ctx *gin.Context) { const actionType = "获取设备" deviceID := ctx.Param("id") + if deviceID == "" { + c.logger.Errorf("%s: 设备ID为空", actionType) + controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "设备ID不能为空", actionType, "设备ID为空", nil) + return + } + device, err := c.repo.FindByIDString(deviceID) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { + c.logger.Warnf("%s: 设备不存在, ID: %s", actionType, deviceID) controller.SendErrorWithAudit(ctx, controller.CodeNotFound, "设备未找到", actionType, "设备不存在", deviceID) return } if strings.Contains(err.Error(), "无效的设备ID格式") { + c.logger.Errorf("%s: 设备ID格式错误: %v, ID: %s", actionType, err, deviceID) controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, err.Error(), actionType, "设备ID格式错误", deviceID) return } - c.logger.Errorf("获取设备: 数据库操作失败: %v", err) + c.logger.Errorf("%s: 数据库查询失败: %v, ID: %s", actionType, err, deviceID) controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取设备信息失败: "+err.Error(), actionType, "数据库查询失败", deviceID) return } resp, err := newDeviceResponse(device) if err != nil { - c.logger.Errorf("获取设备: 序列化响应失败: %v", err) + c.logger.Errorf("%s: 序列化响应失败: %v, Device: %+v", actionType, err, device) controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取设备信息失败: 内部数据格式错误", actionType, "响应序列化失败", device) return } + c.logger.Infof("%s: 获取设备信息成功, ID: %d", actionType, device.ID) controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "获取设备信息成功", resp, actionType, "获取设备信息成功", resp) } @@ -215,18 +225,19 @@ func (c *Controller) ListDevices(ctx *gin.Context) { const actionType = "获取设备列表" devices, err := c.repo.ListAll() if err != nil { - c.logger.Errorf("获取设备列表: 数据库操作失败: %v", err) + c.logger.Errorf("%s: 数据库查询失败: %v", actionType, err) controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取设备列表失败: "+err.Error(), actionType, "数据库查询失败", nil) return } resp, err := newListDeviceResponse(devices) if err != nil { - c.logger.Errorf("获取设备列表: 序列化响应失败: %v", err) + c.logger.Errorf("%s: 序列化响应失败: %v, Devices: %+v", actionType, err, devices) controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取设备列表失败: 内部数据格式错误", actionType, "响应序列化失败", devices) return } + c.logger.Infof("%s: 获取设备列表成功, 数量: %d", actionType, len(devices)) controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "获取设备列表成功", resp, actionType, "获取设备列表成功", resp) } @@ -248,14 +259,16 @@ func (c *Controller) UpdateDevice(ctx *gin.Context) { existingDevice, err := c.repo.FindByIDString(deviceID) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { + c.logger.Warnf("%s: 设备不存在, ID: %s", actionType, deviceID) controller.SendErrorWithAudit(ctx, controller.CodeNotFound, "设备未找到", actionType, "设备不存在", deviceID) return } if strings.Contains(err.Error(), "无效的设备ID格式") { + c.logger.Errorf("%s: 设备ID格式错误: %v, ID: %s", actionType, err, deviceID) controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, err.Error(), actionType, "设备ID格式错误", deviceID) return } - c.logger.Errorf("更新设备: 查找设备失败: %v", err) + c.logger.Errorf("%s: 数据库查询失败: %v, ID: %s", actionType, err, deviceID) controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "更新设备失败: "+err.Error(), actionType, "数据库查询失败", deviceID) return } @@ -263,14 +276,14 @@ func (c *Controller) UpdateDevice(ctx *gin.Context) { // 2. 绑定请求参数 var req UpdateDeviceRequest if err := ctx.ShouldBindJSON(&req); err != nil { - c.logger.Errorf("更新设备: 参数绑定失败: %v", err) + c.logger.Errorf("%s: 参数绑定失败: %v", actionType, err) controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的请求体: "+err.Error(), actionType, "请求体绑定失败", req) return } propertiesJSON, err := json.Marshal(req.Properties) if err != nil { - c.logger.Errorf("更新设备: 序列化属性失败: %v", err) + c.logger.Errorf("%s: 序列化属性失败: %v", actionType, err) controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "属性字段格式错误", actionType, "属性序列化失败", req.Properties) return } @@ -285,25 +298,26 @@ func (c *Controller) UpdateDevice(ctx *gin.Context) { // 在更新设备前进行自检 if !existingDevice.SelfCheck() { - c.logger.Errorf("更新设备: 设备属性自检失败: %v", existingDevice) + c.logger.Errorf("%s: 设备属性自检失败: %v", actionType, existingDevice) controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "设备属性不符合要求", actionType, "设备属性自检失败", existingDevice) return } // 4. 将修改后的 existingDevice 对象保存回数据库 if err := c.repo.Update(existingDevice); err != nil { - c.logger.Errorf("更新设备: 数据库操作失败: %v", err) + c.logger.Errorf("%s: 数据库更新失败: %v, Device: %+v", actionType, err, existingDevice) controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "更新设备失败: "+err.Error(), actionType, "数据库更新失败", existingDevice) return } resp, err := newDeviceResponse(existingDevice) if err != nil { - c.logger.Errorf("更新设备: 序列化响应失败: %v", err) + c.logger.Errorf("%s: 序列化响应失败: %v, Device: %+v", actionType, err, existingDevice) controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "设备更新成功,但响应生成失败", actionType, "响应序列化失败", existingDevice) return } + c.logger.Infof("%s: 设备更新成功, ID: %d", actionType, existingDevice.ID) controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "设备更新成功", resp, actionType, "设备更新成功", resp) } @@ -322,15 +336,30 @@ func (c *Controller) DeleteDevice(ctx *gin.Context) { // 我们需要先将字符串ID转换为uint,因为Delete方法需要uint类型 idUint, err := strconv.ParseUint(deviceID, 10, 64) if err != nil { + c.logger.Errorf("%s: 设备ID格式错误: %v, ID: %s", actionType, err, deviceID) controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的设备ID格式", actionType, "设备ID格式错误", deviceID) return } + // 检查设备是否存在(可选,但通常在删除前会检查) + _, err = c.repo.FindByIDString(deviceID) + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + c.logger.Warnf("%s: 设备不存在, ID: %s", actionType, deviceID) + controller.SendErrorWithAudit(ctx, controller.CodeNotFound, "设备不存在", actionType, "设备不存在", deviceID) + return + } + c.logger.Errorf("%s: 查找设备失败: %v, ID: %s", actionType, err, deviceID) + controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "删除设备失败: 查找设备时发生内部错误", actionType, "数据库查询失败", deviceID) + return + } + if err := c.repo.Delete(uint(idUint)); err != nil { - c.logger.Errorf("删除设备: 数据库操作失败: %v", err) + c.logger.Errorf("%s: 数据库删除失败: %v, ID: %d", actionType, err, idUint) controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "删除设备失败: "+err.Error(), actionType, "数据库删除失败", deviceID) return } + c.logger.Infof("%s: 设备删除成功, ID: %d", actionType, idUint) controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "设备删除成功", nil, actionType, "设备删除成功", deviceID) } diff --git a/internal/app/controller/plan/plan_controller.go b/internal/app/controller/plan/plan_controller.go index 63682ec..6956e6a 100644 --- a/internal/app/controller/plan/plan_controller.go +++ b/internal/app/controller/plan/plan_controller.go @@ -120,6 +120,7 @@ func (c *Controller) CreatePlan(ctx *gin.Context) { var req CreatePlanRequest const actionType = "创建计划" if err := ctx.ShouldBindJSON(&req); err != nil { + c.logger.Errorf("%s: 参数绑定失败: %v", actionType, err) controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的请求体: "+err.Error(), actionType, "请求体绑定失败", req) return } @@ -127,6 +128,7 @@ func (c *Controller) CreatePlan(ctx *gin.Context) { // 使用已有的转换函数,它已经包含了验证和重排逻辑 planToCreate, err := PlanFromCreateRequest(&req) if err != nil { + c.logger.Errorf("%s: 计划数据校验失败: %v", actionType, err) controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "计划数据校验失败: "+err.Error(), actionType, "计划数据校验失败", req) return } @@ -141,6 +143,7 @@ func (c *Controller) CreatePlan(ctx *gin.Context) { // 调用仓库方法创建计划 if err := c.planRepo.CreatePlan(planToCreate); err != nil { + c.logger.Errorf("%s: 数据库创建计划失败: %v", actionType, err) controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "创建计划失败: "+err.Error(), actionType, "数据库创建计划失败", planToCreate) return } @@ -154,12 +157,13 @@ func (c *Controller) CreatePlan(ctx *gin.Context) { // 使用已有的转换函数将创建后的模型转换为响应对象 resp, err := PlanToResponse(planToCreate) if err != nil { - c.logger.Errorf("创建计划: 序列化响应失败: %v", err) + c.logger.Errorf("%s: 序列化响应失败: %v", actionType, err) controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "计划创建成功,但响应生成失败", actionType, "响应序列化失败", planToCreate) return } // 使用统一的成功响应函数 + c.logger.Infof("%s: 计划创建成功, ID: %d", actionType, planToCreate.ID) controller.SendSuccessWithAudit(ctx, controller.CodeCreated, "计划创建成功", resp, actionType, "计划创建成功", resp) } @@ -177,6 +181,7 @@ func (c *Controller) GetPlan(ctx *gin.Context) { idStr := ctx.Param("id") id, err := strconv.ParseUint(idStr, 10, 32) if err != nil { + c.logger.Errorf("%s: 计划ID格式错误: %v, ID: %s", actionType, err, idStr) controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的计划ID格式", actionType, "计划ID格式错误", idStr) return } @@ -186,11 +191,12 @@ func (c *Controller) GetPlan(ctx *gin.Context) { if err != nil { // 判断是否为“未找到”错误 if errors.Is(err, gorm.ErrRecordNotFound) { + c.logger.Warnf("%s: 计划不存在, ID: %d", actionType, id) controller.SendErrorWithAudit(ctx, controller.CodeNotFound, "计划不存在", actionType, "计划不存在", id) return } // 其他数据库错误视为内部错误 - c.logger.Errorf("获取计划详情失败: %v", err) + c.logger.Errorf("%s: 数据库查询失败: %v, ID: %d", actionType, err, id) controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取计划详情时发生内部错误", actionType, "数据库查询失败", id) return } @@ -198,12 +204,13 @@ func (c *Controller) GetPlan(ctx *gin.Context) { // 3. 将模型转换为响应 DTO resp, err := PlanToResponse(plan) if err != nil { - c.logger.Errorf("获取计划详情: 序列化响应失败: %v", err) + c.logger.Errorf("%s: 序列化响应失败: %v, Plan: %+v", actionType, err, plan) controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取计划详情失败: 内部数据格式错误", actionType, "响应序列化失败", plan) return } // 4. 发送成功响应 + c.logger.Infof("%s: 获取计划详情成功, ID: %d", actionType, id) controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "获取计划详情成功", resp, actionType, "获取计划详情成功", resp) } @@ -219,7 +226,7 @@ func (c *Controller) ListPlans(ctx *gin.Context) { // 1. 调用仓库层获取所有计划 plans, err := c.planRepo.ListBasicPlans() if err != nil { - c.logger.Errorf("获取计划列表失败: %v", err) + c.logger.Errorf("%s: 数据库查询失败: %v", actionType, err) controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取计划列表时发生内部错误", actionType, "数据库查询失败", nil) return } @@ -229,7 +236,7 @@ func (c *Controller) ListPlans(ctx *gin.Context) { for _, p := range plans { resp, err := PlanToResponse(&p) if err != nil { - c.logger.Errorf("获取计划列表: 序列化响应失败: %v", err) + c.logger.Errorf("%s: 序列化响应失败: %v, Plan: %+v", actionType, err, p) controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取计划列表失败: 内部数据格式错误", actionType, "响应序列化失败", p) return } @@ -241,6 +248,7 @@ func (c *Controller) ListPlans(ctx *gin.Context) { Plans: planResponses, Total: len(planResponses), } + c.logger.Infof("%s: 获取计划列表成功, 数量: %d", actionType, len(planResponses)) controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "获取计划列表成功", resp, actionType, "获取计划列表成功", resp) } @@ -260,6 +268,7 @@ func (c *Controller) UpdatePlan(ctx *gin.Context) { idStr := ctx.Param("id") id, err := strconv.ParseUint(idStr, 10, 32) if err != nil { + c.logger.Errorf("%s: 计划ID格式错误: %v, ID: %s", actionType, err, idStr) controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的计划ID格式", actionType, "计划ID格式错误", idStr) return } @@ -267,6 +276,7 @@ func (c *Controller) UpdatePlan(ctx *gin.Context) { // 2. 绑定请求体 var req UpdatePlanRequest if err := ctx.ShouldBindJSON(&req); err != nil { + c.logger.Errorf("%s: 参数绑定失败: %v", actionType, err) controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的请求体: "+err.Error(), actionType, "请求体绑定失败", req) return } @@ -274,6 +284,7 @@ func (c *Controller) UpdatePlan(ctx *gin.Context) { // 3. 将请求转换为模型(转换函数带校验) planToUpdate, err := PlanFromUpdateRequest(&req) if err != nil { + c.logger.Errorf("%s: 计划数据校验失败: %v", actionType, err) controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "计划数据校验失败: "+err.Error(), actionType, "计划数据校验失败", req) return } @@ -291,10 +302,11 @@ func (c *Controller) UpdatePlan(ctx *gin.Context) { _, err = c.planRepo.GetBasicPlanByID(uint(id)) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { + c.logger.Warnf("%s: 计划不存在, ID: %d", actionType, id) controller.SendErrorWithAudit(ctx, controller.CodeNotFound, "计划不存在", actionType, "计划不存在", id) return } - c.logger.Errorf("获取计划详情失败: %v", err) + c.logger.Errorf("%s: 获取计划详情失败: %v, ID: %d", actionType, err, id) controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取计划详情时发生内部错误", actionType, "数据库查询失败", id) return } @@ -305,6 +317,7 @@ func (c *Controller) UpdatePlan(ctx *gin.Context) { c.logger.Infof("计划 #%d 被更新,执行计数器已重置为 0。", planToUpdate.ID) if err := c.planRepo.UpdatePlan(planToUpdate); err != nil { + c.logger.Errorf("%s: 数据库更新计划失败: %v, Plan: %+v", actionType, err, planToUpdate) controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "更新计划失败: "+err.Error(), actionType, "数据库更新计划失败", planToUpdate) return } @@ -318,7 +331,7 @@ func (c *Controller) UpdatePlan(ctx *gin.Context) { // 6. 获取更新后的完整计划用于响应 updatedPlan, err := c.planRepo.GetPlanByID(uint(id)) if err != nil { - c.logger.Errorf("获取更新后的计划详情失败: %v", err) + c.logger.Errorf("%s: 获取更新后计划详情失败: %v, ID: %d", actionType, err, id) controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取更新后计划详情时发生内部错误", actionType, "获取更新后计划详情失败", id) return } @@ -326,18 +339,19 @@ func (c *Controller) UpdatePlan(ctx *gin.Context) { // 7. 将模型转换为响应 DTO resp, err := PlanToResponse(updatedPlan) if err != nil { - c.logger.Errorf("更新计划: 序列化响应失败: %v", err) + c.logger.Errorf("%s: 序列化响应失败: %v, Updated Plan: %+v", actionType, err, updatedPlan) controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "计划更新成功,但响应生成失败", actionType, "响应序列化失败", updatedPlan) return } // 8. 发送成功响应 + c.logger.Infof("%s: 计划更新成功, ID: %d", actionType, updatedPlan.ID) controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "计划更新成功", resp, actionType, "计划更新成功", resp) } // DeletePlan godoc // @Summary 删除计划 -// @Description 根据计划ID删除计划。 +// @Description 根据计划ID删除计划。(软删除) // @Tags 计划管理 // @Produce json // @Param id path int true "计划ID" @@ -349,6 +363,7 @@ func (c *Controller) DeletePlan(ctx *gin.Context) { idStr := ctx.Param("id") id, err := strconv.ParseUint(idStr, 10, 32) if err != nil { + c.logger.Errorf("%s: 计划ID格式错误: %v, ID: %s", actionType, err, idStr) controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的计划ID格式", actionType, "计划ID格式错误", idStr) return } @@ -357,10 +372,11 @@ func (c *Controller) DeletePlan(ctx *gin.Context) { plan, err := c.planRepo.GetBasicPlanByID(uint(id)) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { + c.logger.Warnf("%s: 计划不存在, ID: %d", actionType, id) controller.SendErrorWithAudit(ctx, controller.CodeNotFound, "计划不存在", actionType, "计划不存在", id) return } - c.logger.Errorf("启动计划时获取计划信息失败: %v", err) + c.logger.Errorf("%s: 获取计划信息失败: %v, ID: %d", actionType, err, id) controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取计划信息时发生内部错误", actionType, "数据库查询失败", id) return } @@ -368,7 +384,7 @@ func (c *Controller) DeletePlan(ctx *gin.Context) { // 3. 停止这个计划 if plan.Status == models.PlanStatusEnabled { if err := c.planRepo.StopPlanTransactionally(uint(id)); err != nil { - c.logger.Errorf("停止计划 #%d 失败: %v", id, err) + c.logger.Errorf("%s: 停止计划失败: %v, ID: %d", actionType, err, id) controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "停止计划时发生内部错误: "+err.Error(), actionType, "停止计划失败", id) return } @@ -376,12 +392,13 @@ func (c *Controller) DeletePlan(ctx *gin.Context) { // 4. 调用仓库层删除计划 if err := c.planRepo.DeletePlan(uint(id)); err != nil { - c.logger.Errorf("删除计划: 数据库操作失败: %v", err) + c.logger.Errorf("%s: 数据库删除失败: %v, ID: %d", actionType, err, id) controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "删除计划时发生内部错误", actionType, "数据库删除失败", id) return } // 5. 发送成功响应 + c.logger.Infof("%s: 计划删除成功, ID: %d", actionType, id) controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "计划删除成功", nil, actionType, "计划删除成功", id) } @@ -399,6 +416,7 @@ func (c *Controller) StartPlan(ctx *gin.Context) { idStr := ctx.Param("id") id, err := strconv.ParseUint(idStr, 10, 32) if err != nil { + c.logger.Errorf("%s: 计划ID格式错误: %v, ID: %s", actionType, err, idStr) controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的计划ID格式", actionType, "计划ID格式错误", idStr) return } @@ -407,16 +425,18 @@ func (c *Controller) StartPlan(ctx *gin.Context) { plan, err := c.planRepo.GetBasicPlanByID(uint(id)) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { + c.logger.Warnf("%s: 计划不存在, ID: %d", actionType, id) controller.SendErrorWithAudit(ctx, controller.CodeNotFound, "计划不存在", actionType, "计划不存在", id) return } - c.logger.Errorf("启动计划时获取计划信息失败: %v", err) + c.logger.Errorf("%s: 获取计划信息失败: %v, ID: %d", actionType, err, id) controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取计划信息时发生内部错误", actionType, "数据库查询失败", id) return } // 3. 检查计划当前状态 if plan.Status == models.PlanStatusEnabled { + c.logger.Warnf("%s: 计划已处于启动状态,无需重复操作, ID: %d", actionType, id) controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "计划已处于启动状态,无需重复操作", actionType, "计划已处于启动状态", id) return } @@ -427,7 +447,7 @@ func (c *Controller) StartPlan(ctx *gin.Context) { // 如果计划是从停止或失败状态重新启动,且计数器不为0,则重置执行计数 if plan.ExecuteCount > 0 { if err := c.planRepo.UpdateExecuteCount(plan.ID, 0); err != nil { - c.logger.Errorf("重置计划 #%d 执行计数失败: %v", plan.ID, err) + c.logger.Errorf("%s: 重置计划执行计数失败: %v, ID: %d", actionType, err, plan.ID) controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "重置计划执行计数失败", actionType, "重置执行计数失败", plan.ID) return } @@ -436,7 +456,7 @@ func (c *Controller) StartPlan(ctx *gin.Context) { // 更新计划状态为“已启动” if err := c.planRepo.UpdatePlanStatus(plan.ID, models.PlanStatusEnabled); err != nil { - c.logger.Errorf("更新计划 #%d 状态失败: %v", plan.ID, err) + c.logger.Errorf("%s: 更新计划状态失败: %v, ID: %d", actionType, err, plan.ID) controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "更新计划状态失败", actionType, "更新计划状态失败", plan.ID) return } @@ -451,12 +471,13 @@ func (c *Controller) StartPlan(ctx *gin.Context) { // 5. 为计划创建或更新触发器 if err := c.analysisPlanTaskManager.CreateOrUpdateTrigger(plan.ID); err != nil { // 此处错误不回滚状态,因为状态更新已成功,但需要明确告知用户触发器创建失败 - c.logger.Errorf("为计划 #%d 创建或更新触发器失败: %v", plan.ID, err) + c.logger.Errorf("%s: 创建或更新触发器失败: %v, ID: %d", actionType, err, plan.ID) controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "计划状态已更新,但创建执行触发器失败,请检查计划配置或稍后重试", actionType, "创建执行触发器失败", plan.ID) return } // 6. 发送成功响应 + c.logger.Infof("%s: 计划已成功启动, ID: %d", actionType, id) controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "计划已成功启动", nil, actionType, "计划已成功启动", id) } @@ -474,6 +495,7 @@ func (c *Controller) StopPlan(ctx *gin.Context) { idStr := ctx.Param("id") id, err := strconv.ParseUint(idStr, 10, 32) if err != nil { + c.logger.Errorf("%s: 计划ID格式错误: %v, ID: %s", actionType, err, idStr) controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的计划ID格式", actionType, "计划ID格式错误", idStr) return } @@ -482,27 +504,30 @@ func (c *Controller) StopPlan(ctx *gin.Context) { plan, err := c.planRepo.GetBasicPlanByID(uint(id)) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { + c.logger.Warnf("%s: 计划不存在, ID: %d", actionType, id) controller.SendErrorWithAudit(ctx, controller.CodeNotFound, "计划不存在", actionType, "计划不存在", id) return } - c.logger.Errorf("启动计划时获取计划信息失败: %v", err) + c.logger.Errorf("%s: 获取计划信息失败: %v, ID: %d", actionType, err, id) controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取计划信息时发生内部错误", actionType, "数据库查询失败", id) return } // 3. 检查计划当前状态 if plan.Status != models.PlanStatusEnabled { + c.logger.Warnf("%s: 计划当前不是启用状态, ID: %d, Status: %s", actionType, id, plan.Status) controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "计划当前不是启用状态", actionType, "计划未启用", id) return } // 4. 调用仓库层方法,该方法内部处理事务 if err := c.planRepo.StopPlanTransactionally(uint(id)); err != nil { - c.logger.Errorf("停止计划 #%d 失败: %v", id, err) + c.logger.Errorf("%s: 停止计划失败: %v, ID: %d", actionType, err, id) controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "停止计划时发生内部错误: "+err.Error(), actionType, "停止计划失败", id) return } // 5. 发送成功响应 + c.logger.Infof("%s: 计划已成功停止, ID: %d", actionType, id) controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "计划已成功停止", nil, actionType, "计划已成功停止", id) }