package plant import ( "sundynix-go/global" "sundynix-go/model/plant" plantres "sundynix-go/model/plant/response" "go.uber.org/zap" "gorm.io/gorm" ) type CallbackService struct{} var CallbackServiceApp = new(CallbackService) // HandleMediaCheckCallback 处理媒体检测回调 func (s *CallbackService) HandleMediaCheckCallback(cb plantres.WeChatCheckResultCallback) error { global.Logger.Info("收到微信媒体检测回调", zap.String("traceId", cb.TraceId), zap.String("suggest", cb.Result.Suggest)) var checkResult plant.MediaCheckResult err := global.DB.Where("trace_id = ?", cb.TraceId).First(&checkResult).Error if err != nil { global.Logger.Error("回调traceId未找到", zap.String("traceId", cb.TraceId), zap.Error(err)) return err } // 1. 更新检测结果状态 status := 0 if cb.Result.Suggest == "pass" { status = 1 } else { status = 2 } err = global.DB.Model(&checkResult).Updates(map[string]interface{}{ "status": status, "err_msg": cb.Result.Suggest, }).Error if err != nil { global.Logger.Error("更新检测结果失败", zap.Error(err)) return err } // 2. 根据结果处理帖子状态 return s.updatePostStatus(checkResult.PostId) } // updatePostStatus 更新帖子状态 // 逻辑: // 1. 如果有任意一个检测结果为违规(2) -> 帖子违规(2) // 2. 如果所有检测结果都为通过(1) -> 帖子通过(1) // 3. 否则保持待审核(0) func (s *CallbackService) updatePostStatus(postId string) error { return global.DB.Transaction(func(tx *gorm.DB) error { var post plant.Post if err := tx.Where("id = ?", postId).First(&post).Error; err != nil { return err } // 如果帖子已经是违规状态,无需再处理(可能之前已经由文本检测判定违规) if post.HasReviewed == 2 { return nil } var results []plant.MediaCheckResult if err := tx.Where("post_id = ?", postId).Find(&results).Error; err != nil { return err } hasRisky := false allPass := true for _, res := range results { if res.Status == 2 { hasRisky = true break } if res.Status != 1 { allPass = false } } var newStatus = post.HasReviewed // 默认保持原状态 if hasRisky { newStatus = 2 // TODO: 这里可以执行额外的封禁逻辑,例如不仅标记违规,还软删除Oss关联等 global.Logger.Warn("帖子包含违规图片,标记为违规", zap.String("postId", postId)) } else if allPass { // 只有当所有图片都通过,且原状态不是违规时,才标记为通过 // 注意:这里假设文本检测已经通过(文本检测是同步的,若不通过早已设为2) // 如果文本检测尚未完成(理论上不可能,因为是先文本后图片),这里可能会有竞态,但文本检测在发帖goroutine中是串行的。 // 唯一需要注意的是,如果文本检测还在进行中,这里不应覆盖。 // 但我们在PublishPost中是先改HasReviewed再发图片检查。 // 如果文本通过,HasReviewed会被设为1? 不,根据新逻辑,PublishPost中只有无图才设为1。 // 有图时,PublishPost中HasReviewed保持0。 newStatus = 1 global.Logger.Info("帖子所有图片检测通过,标记为通过", zap.String("postId", postId)) } if newStatus != post.HasReviewed { if err := tx.Model(&post).Update("has_reviewed", newStatus).Error; err != nil { return err } } return nil }) }