增加审计输出(初步)

This commit is contained in:
2025-09-28 01:23:50 +08:00
parent 7d527d9a67
commit 17344cdb89
2 changed files with 70 additions and 70 deletions

View File

@@ -123,14 +123,14 @@ func (c *Controller) CreateDevice(ctx *gin.Context) {
var req CreateDeviceRequest var req CreateDeviceRequest
if err := ctx.ShouldBindJSON(&req); err != nil { if err := ctx.ShouldBindJSON(&req); err != nil {
c.logger.Errorf("创建设备: 参数绑定失败: %v", err) c.logger.Errorf("创建设备: 参数绑定失败: %v", err)
controller.SendErrorResponse(ctx, controller.CodeBadRequest, err.Error()) controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, err.Error(), "创建设备", "请求体绑定失败", req)
return return
} }
propertiesJSON, err := json.Marshal(req.Properties) propertiesJSON, err := json.Marshal(req.Properties)
if err != nil { if err != nil {
c.logger.Errorf("创建设备: 序列化属性失败: %v", err) c.logger.Errorf("创建设备: 序列化属性失败: %v", err)
controller.SendErrorResponse(ctx, controller.CodeBadRequest, "属性字段格式错误") controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "属性字段格式错误", "创建设备", "属性序列化失败", req.Properties)
return return
} }
@@ -146,24 +146,24 @@ func (c *Controller) CreateDevice(ctx *gin.Context) {
// 在创建设备前进行自检 // 在创建设备前进行自检
if !device.SelfCheck() { if !device.SelfCheck() {
c.logger.Errorf("创建设备: 设备属性自检失败: %v", device) c.logger.Errorf("创建设备: 设备属性自检失败: %v", device)
controller.SendErrorResponse(ctx, controller.CodeBadRequest, "设备属性不符合要求") controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "设备属性不符合要求", "创建设备", "设备属性自检失败", device)
return return
} }
if err := c.repo.Create(device); err != nil { if err := c.repo.Create(device); err != nil {
c.logger.Errorf("创建设备: 数据库操作失败: %v", err) c.logger.Errorf("创建设备: 数据库操作失败: %v", err)
controller.SendErrorResponse(ctx, controller.CodeInternalError, "创建设备失败") controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "创建设备失败", "创建设备", "数据库创建失败", device)
return return
} }
resp, err := newDeviceResponse(device) resp, err := newDeviceResponse(device)
if err != nil { if err != nil {
c.logger.Errorf("创建设备: 序列化响应失败: %v", err) c.logger.Errorf("创建设备: 序列化响应失败: %v", err)
controller.SendErrorResponse(ctx, controller.CodeInternalError, "设备创建成功,但响应生成失败") controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "设备创建成功,但响应生成失败", "创建设备", "响应序列化失败", device)
return return
} }
controller.SendResponse(ctx, controller.CodeCreated, "设备创建成功", resp) controller.SendSuccessWithAudit(ctx, controller.CodeCreated, "设备创建成功", resp, "创建设备", "设备创建成功", resp)
} }
// GetDevice godoc // GetDevice godoc
@@ -180,26 +180,26 @@ func (c *Controller) GetDevice(ctx *gin.Context) {
device, err := c.repo.FindByIDString(deviceID) device, err := c.repo.FindByIDString(deviceID)
if err != nil { if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) { if errors.Is(err, gorm.ErrRecordNotFound) {
controller.SendErrorResponse(ctx, controller.CodeNotFound, "设备未找到") controller.SendErrorWithAudit(ctx, controller.CodeNotFound, "设备未找到", "获取设备", "设备不存在", deviceID)
return return
} }
if strings.Contains(err.Error(), "无效的设备ID格式") { if strings.Contains(err.Error(), "无效的设备ID格式") {
controller.SendErrorResponse(ctx, controller.CodeBadRequest, err.Error()) controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, err.Error(), "获取设备", "设备ID格式错误", deviceID)
return return
} }
c.logger.Errorf("获取设备: 数据库操作失败: %v", err) c.logger.Errorf("获取设备: 数据库操作失败: %v", err)
controller.SendErrorResponse(ctx, controller.CodeInternalError, "获取设备信息失败") controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取设备信息失败", "获取设备", "数据库查询失败", deviceID)
return return
} }
resp, err := newDeviceResponse(device) resp, err := newDeviceResponse(device)
if err != nil { if err != nil {
c.logger.Errorf("获取设备: 序列化响应失败: %v", err) c.logger.Errorf("获取设备: 序列化响应失败: %v", err)
controller.SendErrorResponse(ctx, controller.CodeInternalError, "获取设备信息失败: 内部数据格式错误") controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取设备信息失败: 内部数据格式错误", "获取设备", "响应序列化失败", device)
return return
} }
controller.SendResponse(ctx, controller.CodeSuccess, "获取设备信息成功", resp) controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "获取设备信息成功", resp, "获取设备", "获取设备信息成功", resp)
} }
// ListDevices godoc // ListDevices godoc
@@ -213,18 +213,18 @@ func (c *Controller) ListDevices(ctx *gin.Context) {
devices, err := c.repo.ListAll() devices, err := c.repo.ListAll()
if err != nil { if err != nil {
c.logger.Errorf("获取设备列表: 数据库操作失败: %v", err) c.logger.Errorf("获取设备列表: 数据库操作失败: %v", err)
controller.SendErrorResponse(ctx, controller.CodeInternalError, "获取设备列表失败") controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取设备列表失败", "获取设备列表", "数据库查询失败", nil)
return return
} }
resp, err := newListDeviceResponse(devices) resp, err := newListDeviceResponse(devices)
if err != nil { if err != nil {
c.logger.Errorf("获取设备列表: 序列化响应失败: %v", err) c.logger.Errorf("获取设备列表: 序列化响应失败: %v", err)
controller.SendErrorResponse(ctx, controller.CodeInternalError, "获取设备列表失败: 内部数据格式错误") controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取设备列表失败: 内部数据格式错误", "获取设备列表", "响应序列化失败", devices)
return return
} }
controller.SendResponse(ctx, controller.CodeSuccess, "获取设备列表成功", resp) controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "获取设备列表成功", resp, "获取设备列表", "获取设备列表成功", resp)
} }
// UpdateDevice godoc // UpdateDevice godoc
@@ -244,15 +244,15 @@ func (c *Controller) UpdateDevice(ctx *gin.Context) {
existingDevice, err := c.repo.FindByIDString(deviceID) existingDevice, err := c.repo.FindByIDString(deviceID)
if err != nil { if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) { if errors.Is(err, gorm.ErrRecordNotFound) {
controller.SendErrorResponse(ctx, controller.CodeNotFound, "设备未找到") controller.SendErrorWithAudit(ctx, controller.CodeNotFound, "设备未找到", "更新设备", "设备不存在", deviceID)
return return
} }
if strings.Contains(err.Error(), "无效的设备ID格式") { if strings.Contains(err.Error(), "无效的设备ID格式") {
controller.SendErrorResponse(ctx, controller.CodeBadRequest, err.Error()) controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, err.Error(), "更新设备", "设备ID格式错误", deviceID)
return return
} }
c.logger.Errorf("更新设备: 查找设备失败: %v", err) c.logger.Errorf("更新设备: 查找设备失败: %v", err)
controller.SendErrorResponse(ctx, controller.CodeInternalError, "更新设备失败") controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "更新设备失败", "更新设备", "数据库查询失败", deviceID)
return return
} }
@@ -260,14 +260,14 @@ func (c *Controller) UpdateDevice(ctx *gin.Context) {
var req UpdateDeviceRequest var req UpdateDeviceRequest
if err := ctx.ShouldBindJSON(&req); err != nil { if err := ctx.ShouldBindJSON(&req); err != nil {
c.logger.Errorf("更新设备: 参数绑定失败: %v", err) c.logger.Errorf("更新设备: 参数绑定失败: %v", err)
controller.SendErrorResponse(ctx, controller.CodeBadRequest, err.Error()) controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, err.Error(), "更新设备", "请求体绑定失败", req)
return return
} }
propertiesJSON, err := json.Marshal(req.Properties) propertiesJSON, err := json.Marshal(req.Properties)
if err != nil { if err != nil {
c.logger.Errorf("更新设备: 序列化属性失败: %v", err) c.logger.Errorf("更新设备: 序列化属性失败: %v", err)
controller.SendErrorResponse(ctx, controller.CodeBadRequest, "属性字段格式错误") controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "属性字段格式错误", "更新设备", "属性序列化失败", req.Properties)
return return
} }
@@ -282,25 +282,25 @@ func (c *Controller) UpdateDevice(ctx *gin.Context) {
// 在更新设备前进行自检 // 在更新设备前进行自检
if !existingDevice.SelfCheck() { if !existingDevice.SelfCheck() {
c.logger.Errorf("更新设备: 设备属性自检失败: %v", existingDevice) c.logger.Errorf("更新设备: 设备属性自检失败: %v", existingDevice)
controller.SendErrorResponse(ctx, controller.CodeBadRequest, "设备属性不符合要求") controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "设备属性不符合要求", "更新设备", "设备属性自检失败", existingDevice)
return return
} }
// 4. 将修改后的 existingDevice 对象保存回数据库 // 4. 将修改后的 existingDevice 对象保存回数据库
if err := c.repo.Update(existingDevice); err != nil { if err := c.repo.Update(existingDevice); err != nil {
c.logger.Errorf("更新设备: 数据库操作失败: %v", err) c.logger.Errorf("更新设备: 数据库操作失败: %v", err)
controller.SendErrorResponse(ctx, controller.CodeInternalError, "更新设备失败") controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "更新设备失败", "更新设备", "数据库更新失败", existingDevice)
return return
} }
resp, err := newDeviceResponse(existingDevice) resp, err := newDeviceResponse(existingDevice)
if err != nil { if err != nil {
c.logger.Errorf("更新设备: 序列化响应失败: %v", err) c.logger.Errorf("更新设备: 序列化响应失败: %v", err)
controller.SendErrorResponse(ctx, controller.CodeInternalError, "设备更新成功,但响应生成失败") controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "设备更新成功,但响应生成失败", "更新设备", "响应序列化失败", existingDevice)
return return
} }
controller.SendResponse(ctx, controller.CodeSuccess, "设备更新成功", resp) controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "设备更新成功", resp, "更新设备", "设备更新成功", resp)
} }
// DeleteDevice godoc // DeleteDevice godoc
@@ -317,15 +317,15 @@ func (c *Controller) DeleteDevice(ctx *gin.Context) {
// 我们需要先将字符串ID转换为uint因为Delete方法需要uint类型 // 我们需要先将字符串ID转换为uint因为Delete方法需要uint类型
idUint, err := strconv.ParseUint(deviceID, 10, 64) idUint, err := strconv.ParseUint(deviceID, 10, 64)
if err != nil { if err != nil {
controller.SendErrorResponse(ctx, controller.CodeBadRequest, "无效的设备ID格式") controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的设备ID格式", "删除设备", "设备ID格式错误", deviceID)
return return
} }
if err := c.repo.Delete(uint(idUint)); err != nil { if err := c.repo.Delete(uint(idUint)); err != nil {
c.logger.Errorf("删除设备: 数据库操作失败: %v", err) c.logger.Errorf("删除设备: 数据库操作失败: %v", err)
controller.SendErrorResponse(ctx, controller.CodeInternalError, "删除设备失败") controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "删除设备失败", "删除设备", "数据库删除失败", deviceID)
return return
} }
controller.SendResponse(ctx, controller.CodeSuccess, "设备删除成功", nil) controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "设备删除成功", nil, "删除设备", "设备删除成功", deviceID)
} }

View File

@@ -119,14 +119,14 @@ func NewController(logger *logs.Logger, planRepo repository.PlanRepository, anal
func (c *Controller) CreatePlan(ctx *gin.Context) { func (c *Controller) CreatePlan(ctx *gin.Context) {
var req CreatePlanRequest var req CreatePlanRequest
if err := ctx.ShouldBindJSON(&req); err != nil { if err := ctx.ShouldBindJSON(&req); err != nil {
controller.SendErrorResponse(ctx, controller.CodeBadRequest, "无效的请求体: "+err.Error()) controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的请求体: "+err.Error(), "创建计划", "请求体绑定失败", req)
return return
} }
// 使用已有的转换函数,它已经包含了验证和重排逻辑 // 使用已有的转换函数,它已经包含了验证和重排逻辑
planToCreate, err := PlanFromCreateRequest(&req) planToCreate, err := PlanFromCreateRequest(&req)
if err != nil { if err != nil {
controller.SendErrorResponse(ctx, controller.CodeBadRequest, "计划数据校验失败: "+err.Error()) controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "计划数据校验失败: "+err.Error(), "创建计划", "计划数据校验失败", req)
return return
} }
@@ -140,7 +140,7 @@ func (c *Controller) CreatePlan(ctx *gin.Context) {
// 调用仓库方法创建计划 // 调用仓库方法创建计划
if err := c.planRepo.CreatePlan(planToCreate); err != nil { if err := c.planRepo.CreatePlan(planToCreate); err != nil {
controller.SendErrorResponse(ctx, controller.CodeBadRequest, "创建计划失败: "+err.Error()) controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "创建计划失败: "+err.Error(), "创建计划", "数据库创建计划失败", planToCreate)
return return
} }
@@ -154,12 +154,12 @@ func (c *Controller) CreatePlan(ctx *gin.Context) {
resp, err := PlanToResponse(planToCreate) resp, err := PlanToResponse(planToCreate)
if err != nil { if err != nil {
c.logger.Errorf("创建计划: 序列化响应失败: %v", err) c.logger.Errorf("创建计划: 序列化响应失败: %v", err)
controller.SendErrorResponse(ctx, controller.CodeInternalError, "计划创建成功,但响应生成失败") controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "计划创建成功,但响应生成失败", "创建计划", "响应序列化失败", planToCreate)
return return
} }
// 使用统一的成功响应函数 // 使用统一的成功响应函数
controller.SendResponse(ctx, controller.CodeCreated, "计划创建成功", resp) controller.SendSuccessWithAudit(ctx, controller.CodeCreated, "计划创建成功", resp, "创建计划", "计划创建成功", resp)
} }
// GetPlan godoc // GetPlan godoc
@@ -175,7 +175,7 @@ func (c *Controller) GetPlan(ctx *gin.Context) {
idStr := ctx.Param("id") idStr := ctx.Param("id")
id, err := strconv.ParseUint(idStr, 10, 32) id, err := strconv.ParseUint(idStr, 10, 32)
if err != nil { if err != nil {
controller.SendErrorResponse(ctx, controller.CodeBadRequest, "无效的计划ID格式") controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的计划ID格式", "获取计划详情", "计划ID格式错误", idStr)
return return
} }
@@ -184,12 +184,12 @@ func (c *Controller) GetPlan(ctx *gin.Context) {
if err != nil { if err != nil {
// 判断是否为“未找到”错误 // 判断是否为“未找到”错误
if errors.Is(err, gorm.ErrRecordNotFound) { if errors.Is(err, gorm.ErrRecordNotFound) {
controller.SendErrorResponse(ctx, controller.CodeNotFound, "计划不存在") controller.SendErrorWithAudit(ctx, controller.CodeNotFound, "计划不存在", "获取计划详情", "计划不存在", id)
return return
} }
// 其他数据库错误视为内部错误 // 其他数据库错误视为内部错误
c.logger.Errorf("获取计划详情失败: %v", err) c.logger.Errorf("获取计划详情失败: %v", err)
controller.SendErrorResponse(ctx, controller.CodeInternalError, "获取计划详情时发生内部错误") controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取计划详情时发生内部错误", "获取计划详情", "数据库查询失败", id)
return return
} }
@@ -197,12 +197,12 @@ func (c *Controller) GetPlan(ctx *gin.Context) {
resp, err := PlanToResponse(plan) resp, err := PlanToResponse(plan)
if err != nil { if err != nil {
c.logger.Errorf("获取计划详情: 序列化响应失败: %v", err) c.logger.Errorf("获取计划详情: 序列化响应失败: %v", err)
controller.SendErrorResponse(ctx, controller.CodeInternalError, "获取计划详情失败: 内部数据格式错误") controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取计划详情失败: 内部数据格式错误", "获取计划详情", "响应序列化失败", plan)
return return
} }
// 4. 发送成功响应 // 4. 发送成功响应
controller.SendResponse(ctx, controller.CodeSuccess, "获取计划详情成功", resp) controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "获取计划详情成功", resp, "获取计划详情", "获取计划详情成功", resp)
} }
// ListPlans godoc // ListPlans godoc
@@ -217,7 +217,7 @@ func (c *Controller) ListPlans(ctx *gin.Context) {
plans, err := c.planRepo.ListBasicPlans() plans, err := c.planRepo.ListBasicPlans()
if err != nil { if err != nil {
c.logger.Errorf("获取计划列表失败: %v", err) c.logger.Errorf("获取计划列表失败: %v", err)
controller.SendErrorResponse(ctx, controller.CodeInternalError, "获取计划列表时发生内部错误") controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取计划列表时发生内部错误", "获取计划列表", "数据库查询失败", nil)
return return
} }
@@ -227,7 +227,7 @@ func (c *Controller) ListPlans(ctx *gin.Context) {
resp, err := PlanToResponse(&p) resp, err := PlanToResponse(&p)
if err != nil { if err != nil {
c.logger.Errorf("获取计划列表: 序列化响应失败: %v", err) c.logger.Errorf("获取计划列表: 序列化响应失败: %v", err)
controller.SendErrorResponse(ctx, controller.CodeInternalError, "获取计划列表失败: 内部数据格式错误") controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取计划列表失败: 内部数据格式错误", "获取计划列表", "响应序列化失败", p)
return return
} }
planResponses = append(planResponses, *resp) planResponses = append(planResponses, *resp)
@@ -238,7 +238,7 @@ func (c *Controller) ListPlans(ctx *gin.Context) {
Plans: planResponses, Plans: planResponses,
Total: len(planResponses), Total: len(planResponses),
} }
controller.SendResponse(ctx, controller.CodeSuccess, "获取计划列表成功", resp) controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "获取计划列表成功", resp, "获取计划列表", "获取计划列表成功", resp)
} }
// UpdatePlan godoc // UpdatePlan godoc
@@ -256,21 +256,21 @@ func (c *Controller) UpdatePlan(ctx *gin.Context) {
idStr := ctx.Param("id") idStr := ctx.Param("id")
id, err := strconv.ParseUint(idStr, 10, 32) id, err := strconv.ParseUint(idStr, 10, 32)
if err != nil { if err != nil {
controller.SendErrorResponse(ctx, controller.CodeBadRequest, "无效的计划ID格式") controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的计划ID格式", "更新计划", "计划ID格式错误", idStr)
return return
} }
// 2. 绑定请求体 // 2. 绑定请求体
var req UpdatePlanRequest var req UpdatePlanRequest
if err := ctx.ShouldBindJSON(&req); err != nil { if err := ctx.ShouldBindJSON(&req); err != nil {
controller.SendErrorResponse(ctx, controller.CodeBadRequest, "无效的请求体: "+err.Error()) controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的请求体: "+err.Error(), "更新计划", "请求体绑定失败", req)
return return
} }
// 3. 将请求转换为模型(转换函数带校验) // 3. 将请求转换为模型(转换函数带校验)
planToUpdate, err := PlanFromUpdateRequest(&req) planToUpdate, err := PlanFromUpdateRequest(&req)
if err != nil { if err != nil {
controller.SendErrorResponse(ctx, controller.CodeBadRequest, "计划数据校验失败: "+err.Error()) controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "计划数据校验失败: "+err.Error(), "更新计划", "计划数据校验失败", req)
return return
} }
planToUpdate.ID = uint(id) // 确保ID被设置 planToUpdate.ID = uint(id) // 确保ID被设置
@@ -287,11 +287,11 @@ func (c *Controller) UpdatePlan(ctx *gin.Context) {
_, err = c.planRepo.GetBasicPlanByID(uint(id)) _, err = c.planRepo.GetBasicPlanByID(uint(id))
if err != nil { if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) { if errors.Is(err, gorm.ErrRecordNotFound) {
controller.SendErrorResponse(ctx, controller.CodeNotFound, "计划不存在") controller.SendErrorWithAudit(ctx, controller.CodeNotFound, "计划不存在", "更新计划", "计划不存在", id)
return return
} }
c.logger.Errorf("获取计划详情失败: %v", err) c.logger.Errorf("获取计划详情失败: %v", err)
controller.SendErrorResponse(ctx, controller.CodeInternalError, "获取计划详情时发生内部错误") controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取计划详情时发生内部错误", "更新计划", "数据库查询失败", id)
return return
} }
@@ -301,7 +301,7 @@ func (c *Controller) UpdatePlan(ctx *gin.Context) {
c.logger.Infof("计划 #%d 被更新,执行计数器已重置为 0。", planToUpdate.ID) c.logger.Infof("计划 #%d 被更新,执行计数器已重置为 0。", planToUpdate.ID)
if err := c.planRepo.UpdatePlan(planToUpdate); err != nil { if err := c.planRepo.UpdatePlan(planToUpdate); err != nil {
controller.SendErrorResponse(ctx, controller.CodeBadRequest, "更新计划失败: "+err.Error()) controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "更新计划失败: "+err.Error(), "更新计划", "数据库更新计划失败", planToUpdate)
return return
} }
@@ -315,7 +315,7 @@ func (c *Controller) UpdatePlan(ctx *gin.Context) {
updatedPlan, err := c.planRepo.GetPlanByID(uint(id)) updatedPlan, err := c.planRepo.GetPlanByID(uint(id))
if err != nil { if err != nil {
c.logger.Errorf("获取更新后的计划详情失败: %v", err) c.logger.Errorf("获取更新后的计划详情失败: %v", err)
controller.SendErrorResponse(ctx, controller.CodeInternalError, "获取更新后计划详情时发生内部错误") controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取更新后计划详情时发生内部错误", "更新计划", "获取更新后计划详情失败", id)
return return
} }
@@ -323,12 +323,12 @@ func (c *Controller) UpdatePlan(ctx *gin.Context) {
resp, err := PlanToResponse(updatedPlan) resp, err := PlanToResponse(updatedPlan)
if err != nil { if err != nil {
c.logger.Errorf("更新计划: 序列化响应失败: %v", err) c.logger.Errorf("更新计划: 序列化响应失败: %v", err)
controller.SendErrorResponse(ctx, controller.CodeInternalError, "计划更新成功,但响应生成失败") controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "计划更新成功,但响应生成失败", "更新计划", "响应序列化失败", updatedPlan)
return return
} }
// 8. 发送成功响应 // 8. 发送成功响应
controller.SendResponse(ctx, controller.CodeSuccess, "计划更新成功", resp) controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "计划更新成功", resp, "更新计划", "计划更新成功", resp)
} }
// DeletePlan godoc // DeletePlan godoc
@@ -344,7 +344,7 @@ func (c *Controller) DeletePlan(ctx *gin.Context) {
idStr := ctx.Param("id") idStr := ctx.Param("id")
id, err := strconv.ParseUint(idStr, 10, 32) id, err := strconv.ParseUint(idStr, 10, 32)
if err != nil { if err != nil {
controller.SendErrorResponse(ctx, controller.CodeBadRequest, "无效的计划ID格式") controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的计划ID格式", "删除计划", "计划ID格式错误", idStr)
return return
} }
@@ -352,11 +352,11 @@ func (c *Controller) DeletePlan(ctx *gin.Context) {
plan, err := c.planRepo.GetBasicPlanByID(uint(id)) plan, err := c.planRepo.GetBasicPlanByID(uint(id))
if err != nil { if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) { if errors.Is(err, gorm.ErrRecordNotFound) {
controller.SendErrorResponse(ctx, controller.CodeNotFound, "计划不存在") controller.SendErrorWithAudit(ctx, controller.CodeNotFound, "计划不存在", "删除计划", "计划不存在", id)
return return
} }
c.logger.Errorf("启动计划时获取计划信息失败: %v", err) c.logger.Errorf("启动计划时获取计划信息失败: %v", err)
controller.SendErrorResponse(ctx, controller.CodeInternalError, "获取计划信息时发生内部错误") controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取计划信息时发生内部错误", "删除计划", "数据库查询失败", id)
return return
} }
@@ -364,20 +364,20 @@ func (c *Controller) DeletePlan(ctx *gin.Context) {
if plan.Status == models.PlanStatusEnabled { if plan.Status == models.PlanStatusEnabled {
if err := c.planRepo.StopPlanTransactionally(uint(id)); err != nil { if err := c.planRepo.StopPlanTransactionally(uint(id)); err != nil {
c.logger.Errorf("停止计划 #%d 失败: %v", id, err) c.logger.Errorf("停止计划 #%d 失败: %v", id, err)
controller.SendErrorResponse(ctx, controller.CodeInternalError, "停止计划时发生内部错误: "+err.Error()) controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "停止计划时发生内部错误: "+err.Error(), "删除计划", "停止计划失败", id)
return return
} }
} }
// 4. 调用仓库层删除计划 // 4. 调用仓库层删除计划
if err := c.planRepo.DeletePlan(uint(id)); err != nil { if err := c.planRepo.DeletePlan(uint(id)); err != nil {
c.logger.Errorf("删除计划失败: %v", err) c.logger.Errorf("删除计划: 数据库操作失败: %v", err)
controller.SendErrorResponse(ctx, controller.CodeInternalError, "删除计划时发生内部错误") controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "删除计划时发生内部错误", "删除计划", "数据库删除失败", id)
return return
} }
// 5. 发送成功响应 // 5. 发送成功响应
controller.SendResponse(ctx, controller.CodeSuccess, "计划删除成功", nil) controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "计划删除成功", nil, "删除计划", "计划删除成功", id)
} }
// StartPlan godoc // StartPlan godoc
@@ -393,7 +393,7 @@ func (c *Controller) StartPlan(ctx *gin.Context) {
idStr := ctx.Param("id") idStr := ctx.Param("id")
id, err := strconv.ParseUint(idStr, 10, 32) id, err := strconv.ParseUint(idStr, 10, 32)
if err != nil { if err != nil {
controller.SendErrorResponse(ctx, controller.CodeBadRequest, "无效的计划ID格式") controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的计划ID格式", "启动计划", "计划ID格式错误", idStr)
return return
} }
@@ -401,17 +401,17 @@ func (c *Controller) StartPlan(ctx *gin.Context) {
plan, err := c.planRepo.GetBasicPlanByID(uint(id)) plan, err := c.planRepo.GetBasicPlanByID(uint(id))
if err != nil { if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) { if errors.Is(err, gorm.ErrRecordNotFound) {
controller.SendErrorResponse(ctx, controller.CodeNotFound, "计划不存在") controller.SendErrorWithAudit(ctx, controller.CodeNotFound, "计划不存在", "启动计划", "计划不存在", id)
return return
} }
c.logger.Errorf("启动计划时获取计划信息失败: %v", err) c.logger.Errorf("启动计划时获取计划信息失败: %v", err)
controller.SendErrorResponse(ctx, controller.CodeInternalError, "获取计划信息时发生内部错误") controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取计划信息时发生内部错误", "启动计划", "数据库查询失败", id)
return return
} }
// 3. 检查计划当前状态 // 3. 检查计划当前状态
if plan.Status == models.PlanStatusEnabled { if plan.Status == models.PlanStatusEnabled {
controller.SendErrorResponse(ctx, controller.CodeBadRequest, "计划已处于启动状态,无需重复操作") controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "计划已处于启动状态,无需重复操作", "启动计划", "计划已启动", id)
return return
} }
@@ -422,7 +422,7 @@ func (c *Controller) StartPlan(ctx *gin.Context) {
if plan.ExecuteCount > 0 { if plan.ExecuteCount > 0 {
if err := c.planRepo.UpdateExecuteCount(plan.ID, 0); err != nil { if err := c.planRepo.UpdateExecuteCount(plan.ID, 0); err != nil {
c.logger.Errorf("重置计划 #%d 执行计数失败: %v", plan.ID, err) c.logger.Errorf("重置计划 #%d 执行计数失败: %v", plan.ID, err)
controller.SendErrorResponse(ctx, controller.CodeInternalError, "重置计划执行计数失败") controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "重置计划执行计数失败", "启动计划", "重置执行计数失败", plan.ID)
return return
} }
c.logger.Infof("计划 #%d 的执行计数器已重置为 0。", plan.ID) c.logger.Infof("计划 #%d 的执行计数器已重置为 0。", plan.ID)
@@ -431,14 +431,14 @@ func (c *Controller) StartPlan(ctx *gin.Context) {
// 更新计划状态为“已启动” // 更新计划状态为“已启动”
if err := c.planRepo.UpdatePlanStatus(plan.ID, models.PlanStatusEnabled); err != nil { if err := c.planRepo.UpdatePlanStatus(plan.ID, models.PlanStatusEnabled); err != nil {
c.logger.Errorf("更新计划 #%d 状态失败: %v", plan.ID, err) c.logger.Errorf("更新计划 #%d 状态失败: %v", plan.ID, err)
controller.SendErrorResponse(ctx, controller.CodeInternalError, "更新计划状态失败") controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "更新计划状态失败", "启动计划", "更新计划状态失败", plan.ID)
return return
} }
c.logger.Infof("已成功更新计划 #%d 的状态为 '已启动'。", plan.ID) c.logger.Infof("已成功更新计划 #%d 的状态为 '已启动'。", plan.ID)
} else { } else {
// 如果计划已经处于 Enabled 状态,则无需更新 // 如果计划已经处于 Enabled 状态,则无需更新
c.logger.Infof("计划 #%d 已处于启动状态,无需重复操作。", plan.ID) c.logger.Infof("计划 #%d 已处于启动状态,无需重复操作。", plan.ID)
controller.SendErrorResponse(ctx, controller.CodeBadRequest, "计划已处于启动状态,无需重复操作") controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "计划已处于启动状态,无需重复操作", "启动计划", "计划已处于启动状态", plan.ID)
return return
} }
@@ -446,12 +446,12 @@ func (c *Controller) StartPlan(ctx *gin.Context) {
if err := c.analysisPlanTaskManager.CreateOrUpdateTrigger(plan.ID); err != nil { if err := c.analysisPlanTaskManager.CreateOrUpdateTrigger(plan.ID); err != nil {
// 此处错误不回滚状态,因为状态更新已成功,但需要明确告知用户触发器创建失败 // 此处错误不回滚状态,因为状态更新已成功,但需要明确告知用户触发器创建失败
c.logger.Errorf("为计划 #%d 创建或更新触发器失败: %v", plan.ID, err) c.logger.Errorf("为计划 #%d 创建或更新触发器失败: %v", plan.ID, err)
controller.SendErrorResponse(ctx, controller.CodeInternalError, "计划状态已更新,但创建执行触发器失败,请检查计划配置或稍后重试") controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "计划状态已更新,但创建执行触发器失败,请检查计划配置或稍后重试", "启动计划", "创建执行触发器失败", plan.ID)
return return
} }
// 6. 发送成功响应 // 6. 发送成功响应
controller.SendResponse(ctx, controller.CodeSuccess, "计划已成功启动", nil) controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "计划已成功启动", nil, "启动计划", "计划已成功启动", id)
} }
// StopPlan godoc // StopPlan godoc
@@ -467,7 +467,7 @@ func (c *Controller) StopPlan(ctx *gin.Context) {
idStr := ctx.Param("id") idStr := ctx.Param("id")
id, err := strconv.ParseUint(idStr, 10, 32) id, err := strconv.ParseUint(idStr, 10, 32)
if err != nil { if err != nil {
controller.SendErrorResponse(ctx, controller.CodeBadRequest, "无效的计划ID格式") controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的计划ID格式", "停止计划", "计划ID格式错误", idStr)
return return
} }
@@ -475,27 +475,27 @@ func (c *Controller) StopPlan(ctx *gin.Context) {
plan, err := c.planRepo.GetBasicPlanByID(uint(id)) plan, err := c.planRepo.GetBasicPlanByID(uint(id))
if err != nil { if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) { if errors.Is(err, gorm.ErrRecordNotFound) {
controller.SendErrorResponse(ctx, controller.CodeNotFound, "计划不存在") controller.SendErrorWithAudit(ctx, controller.CodeNotFound, "计划不存在", "停止计划", "计划不存在", id)
return return
} }
c.logger.Errorf("启动计划时获取计划信息失败: %v", err) c.logger.Errorf("启动计划时获取计划信息失败: %v", err)
controller.SendErrorResponse(ctx, controller.CodeInternalError, "获取计划信息时发生内部错误") controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取计划信息时发生内部错误", "停止计划", "数据库查询失败", id)
return return
} }
// 3. 检查计划当前状态 // 3. 检查计划当前状态
if plan.Status != models.PlanStatusEnabled { if plan.Status != models.PlanStatusEnabled {
controller.SendErrorResponse(ctx, controller.CodeBadRequest, "计划当前不是启用状态") controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "计划当前不是启用状态", "停止计划", "计划未启用", id)
return return
} }
// 4. 调用仓库层方法,该方法内部处理事务 // 4. 调用仓库层方法,该方法内部处理事务
if err := c.planRepo.StopPlanTransactionally(uint(id)); err != nil { if err := c.planRepo.StopPlanTransactionally(uint(id)); err != nil {
c.logger.Errorf("停止计划 #%d 失败: %v", id, err) c.logger.Errorf("停止计划 #%d 失败: %v", id, err)
controller.SendErrorResponse(ctx, controller.CodeInternalError, "停止计划时发生内部错误: "+err.Error()) controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "停止计划时发生内部错误: "+err.Error(), "停止计划", "停止计划失败", id)
return return
} }
// 5. 发送成功响应 // 5. 发送成功响应
controller.SendResponse(ctx, controller.CodeSuccess, "计划已成功停止", nil) controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "计划已成功停止", nil, "停止计划", "计划已成功停止", id)
} }