From 4ffc41ea84adcc6dc45b318b06e08a569d08e0cf Mon Sep 17 00:00:00 2001 From: Blizzard Date: Sat, 14 Feb 2026 13:08:52 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=BC=82=E6=AD=A5=E6=A0=A1=E9=AA=8C?= =?UTF-8?q?=E7=A4=BE=E5=8C=BApost=E6=96=87=E6=9C=AC=E5=86=85=E5=AE=B9?= =?UTF-8?q?=E6=98=AF=E5=90=A6=E8=BF=9D=E8=A7=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/v1/plant/enter.go | 2 + initialize/gorm.go | 25 +++++----- initialize/router.go | 3 +- model/plant/community_post.go | 2 +- router/plant/enter.go | 2 + service/plant/enter.go | 1 + service/plant/post.go | 93 ++++++++++++++++++++++++++++++++++- 7 files changed, 112 insertions(+), 16 deletions(-) diff --git a/api/v1/plant/enter.go b/api/v1/plant/enter.go index 072e293..e56cc52 100644 --- a/api/v1/plant/enter.go +++ b/api/v1/plant/enter.go @@ -12,6 +12,7 @@ type ApiGroup struct { LevelConfigApi UserProfileApi BadgeConfigApi + CallbackApi } var ( @@ -24,4 +25,5 @@ var ( levelConfigService = service.GroupApp.PlantServiceGroup.LevelConfigService userProfileService = service.GroupApp.PlantServiceGroup.UserProfileService badgeConfigService = service.GroupApp.PlantServiceGroup.BadgeConfigService + callbackService = service.GroupApp.PlantServiceGroup.CallbackService ) diff --git a/initialize/gorm.go b/initialize/gorm.go index 0ba651c..8b88af7 100644 --- a/initialize/gorm.go +++ b/initialize/gorm.go @@ -39,18 +39,19 @@ func MigrateTable() { system.SysOperationRecord{}, system.Oss{}, - plant.MyPlant{}, //我的植物 - plant.CarePlan{}, //植物养护计划 - plant.CareTask{}, //植物养护任务 - plant.CareRecord{}, //植物养护记录 - plant.GrowthRecord{}, //植物成长记录 - plant.Topic{}, //帖子话题 - plant.Post{}, //帖子 - plant.PostLike{}, //帖子点赞 - plant.PostComment{}, //帖子评论 - plant.Class{}, //百科分类 - plant.Wiki{}, //百科植物 - plant.ClassifyRecord{}, //植物识别记录 + plant.MyPlant{}, //我的植物 + plant.CarePlan{}, //植物养护计划 + plant.CareTask{}, //植物养护任务 + plant.CareRecord{}, //植物养护记录 + plant.GrowthRecord{}, //植物成长记录 + plant.MediaCheckResult{}, //媒体安全检测结果 + plant.Topic{}, //帖子话题 + plant.Post{}, //帖子 + plant.PostLike{}, //帖子点赞 + plant.PostComment{}, //帖子评论 + plant.Class{}, //百科分类 + plant.Wiki{}, //百科植物 + plant.ClassifyRecord{}, //植物识别记录 plant.LevelConfig{}, //等级配置 plant.BadgeConfig{}, //徽章配置 diff --git a/initialize/router.go b/initialize/router.go index 13defb6..7945ffd 100644 --- a/initialize/router.go +++ b/initialize/router.go @@ -35,7 +35,8 @@ func Routers() { NeedAuthGroup.Use(middleware.AuthMiddleware()) { //无须鉴权的路由 - systemRouter.InitAuthRouter(PublicGroup) //登录不需要鉴权 + systemRouter.InitAuthRouter(PublicGroup) //登录不需要鉴权 + plantGroup.InitCallbackRouter(PublicGroup) // 回调 } { diff --git a/model/plant/community_post.go b/model/plant/community_post.go index e60b52d..130db2a 100644 --- a/model/plant/community_post.go +++ b/model/plant/community_post.go @@ -16,7 +16,7 @@ type Post struct { LikeCount int `json:"likeCount" form:"likeCount" gorm:"default:0;column:like_count;comment:点赞次数"` StarCount int `json:"starCount" form:"starCount" gorm:"default:0;column:star_count;comment:收藏次数"` Location string `json:"location" form:"location" gorm:"column:location;size:100;comment:位置"` - HasReviewed int `json:"hasReviewed" form:"hasReviewed" gorm:"column:has_reviewed;default:0;comment:是否审核通过"` + HasReviewed int `json:"hasReviewed" form:"hasReviewed" gorm:"column:has_reviewed;default:0;comment:是否审核通过"` // 0-未审核 1-审核通过 2-违规 HasLiked int `json:"hasLiked" form:"hasLiked" gorm:"-"` HasStar int `json:"hasStar" form:"hasStar" gorm:"-"` //图片 diff --git a/router/plant/enter.go b/router/plant/enter.go index c19e5f8..d0263ef 100644 --- a/router/plant/enter.go +++ b/router/plant/enter.go @@ -12,6 +12,7 @@ type RouterGroup struct { LevelConfigRouter BadgeConfigRouter UserProfileRouter + CallbackRouter } // 初始化路由 @@ -25,4 +26,5 @@ var ( levelConfigApi = v1.ApiGroupApp.PlantApiGroup.LevelConfigApi userProfileApi = v1.ApiGroupApp.PlantApiGroup.UserProfileApi badgeConfigApi = v1.ApiGroupApp.PlantApiGroup.BadgeConfigApi + callbackApi = v1.ApiGroupApp.PlantApiGroup.CallbackApi ) diff --git a/service/plant/enter.go b/service/plant/enter.go index e9781f3..ef6a384 100644 --- a/service/plant/enter.go +++ b/service/plant/enter.go @@ -10,4 +10,5 @@ type ServiceGroup struct { LevelConfigService BadgeConfigService UserProfileService + CallbackService } diff --git a/service/plant/post.go b/service/plant/post.go index a77e9bd..d8fe603 100644 --- a/service/plant/post.go +++ b/service/plant/post.go @@ -6,7 +6,11 @@ import ( plantReq "sundynix-go/model/plant/request" "sundynix-go/model/system" + "sundynix-go/utils/wechat" + "gorm.io/gorm" + + "go.uber.org/zap" ) type PostService struct{} @@ -15,9 +19,11 @@ var PostServiceApp = new(PostService) // PublishPost 发表帖子 func (s *PostService) PublishPost(req plantReq.CreatePost, userId string) error { - return global.DB.Transaction(func(tx *gorm.DB) error { + var postId string + var ossList []*system.Oss + + err := global.DB.Transaction(func(tx *gorm.DB) error { //1.验证oss是否存在 - var ossList []*system.Oss err := tx.Where("id in ?", req.OssIds).Find(&ossList).Error if err != nil { return err @@ -33,6 +39,8 @@ func (s *PostService) PublishPost(req plantReq.CreatePost, userId string) error if err != nil { return err } + postId = post.Id + //3.处理图片关系 if len(ossList) > 0 { var relations []map[string]interface{} @@ -49,6 +57,87 @@ func (s *PostService) PublishPost(req plantReq.CreatePost, userId string) error } return nil }) + + if err != nil { + return err + } + + // 4.异步内容安全检查 + // 4.异步内容安全检查 + go func(pid, uid, title, content string, imgs []*system.Oss) { + defer func() { + if r := recover(); r != nil { + global.Logger.Error("异步内容安全检查Panic", zap.Any("panic", r)) + } + }() + + // 获取用户 openid + var user system.User + if err := global.DB.Where("id = ?", uid).First(&user).Error; err != nil { + global.Logger.Error("获取用户失败,跳过安全检查", zap.String("userId", uid), zap.Error(err)) + return + } + openid := user.MiniOpenId + if openid == "" { + global.Logger.Warn("用户无MiniOpenId,跳过安全检查", zap.String("userId", uid)) + return + } + + // 文本检查 + fullContent := title + "\n" + content + isSafe := wechat.MsgSecCheck(fullContent, openid) + + // 文本违规 -> 直接拒绝 + if !isSafe { + if err := global.DB.Model(&plant.Post{}).Where("id = ?", pid).Update("has_reviewed", 2).Error; err != nil { + global.Logger.Error("更新帖子违规状态失败", zap.String("postId", pid), zap.Error(err)) + } + global.Logger.Info("帖子内容违规,已标记", zap.String("postId", pid)) + return // 文本违规,无需再检查图片 + } + if err := global.DB.Model(&plant.Post{}).Where("id = ?", pid).Update("has_reviewed", 1).Error; err != nil { + global.Logger.Error("更新帖子违规状态失败", zap.String("postId", pid), zap.Error(err)) + } + return // 文本违规,无需再检查图片 + + // 文本通过,判断是否有图片 + //if len(imgs) == 0 { + // // 无图且文本通过 -> 直接通过 + // if err := global.DB.Model(&plant.Post{}).Where("id = ?", pid).Update("has_reviewed", 1).Error; err != nil { + // global.Logger.Error("更新帖子通过状态失败", zap.String("postId", pid), zap.Error(err)) + // } + // return + //} + + // 有图,文本通过 -> 保持状态为0(待审核),等待图片回调 + + // todo 图片检查 + //for _, oss := range imgs { + // // 假设 oss.Url 是完整链接 + // traceId, err := wechat.MediaCheckAsync(oss.Url, 2, openid) + // if err != nil { + // global.Logger.Error("图片安全检查请求失败", zap.String("url", oss.Url), zap.Error(err)) + // continue + // } + // global.Logger.Info("图片安全检查请求成功", zap.String("traceId", traceId)) + // + // // 保存检测记录 + // checkResult := plant.MediaCheckResult{ + // TraceId: traceId, + // PostId: pid, + // OssId: oss.Id, + // UserId: uid, + // Status: 0, // 检测中 + // Type: 2, // 图片 + // } + // if err := global.DB.Create(&checkResult).Error; err != nil { + // global.Logger.Error("保存媒体检测记录失败", zap.Error(err)) + // } + //} + + }(postId, userId, req.Title, req.Content, ossList) + + return nil } // PostPage 帖子列表