diff --git a/internal/model/notification.go b/internal/model/notification.go index d6efce2..f96ada3 100644 --- a/internal/model/notification.go +++ b/internal/model/notification.go @@ -2,8 +2,10 @@ package model // 消息/通知类型常量 const ( - NotifyAuditApproved = "audit_approved" - NotifyAuditRejected = "audit_rejected" + NotifyAuditApproved = "audit_approved" + NotifyAuditRejected = "audit_rejected" + NotifyPostApproved = "post_approved" + NotifyPostRejected = "post_rejected" ) // Notification 消息/通知模型 @@ -20,8 +22,10 @@ type Notification struct { // NotifyTypeNames 通知类型 → 中文名 var NotifyTypeNames = map[string]string{ - NotifyAuditApproved: "系统通知", - NotifyAuditRejected: "系统通知", + NotifyAuditApproved: "资料审核", + NotifyAuditRejected: "资料审核", + NotifyPostApproved: "稿件审核", + NotifyPostRejected: "稿件审核", } // NotificationListResult 消息列表查询结果 diff --git a/internal/router/deps_extra.go b/internal/router/deps_extra.go index 8c673b0..f773890 100644 --- a/internal/router/deps_extra.go +++ b/internal/router/deps_extra.go @@ -32,7 +32,7 @@ func buildDeps(db *gorm.DB, cfg *config.Config, siteSettings *config.SiteSetting ) postRepo := repository.NewPostRepo(db) - postService := service.NewPostService(postRepo, siteSettings) + postService := service.NewPostService(postRepo, siteSettings, notificationService) shortcodeSvc := service.NewShortcodeService() postCtrl := controller.NewPostController(postService, shortcodeSvc) adminPostCtrl := adminCtrl.NewAdminPostController(postService) diff --git a/internal/service/notification_service.go b/internal/service/notification_service.go index 4d62dad..1356fd4 100644 --- a/internal/service/notification_service.go +++ b/internal/service/notification_service.go @@ -110,3 +110,20 @@ func (s *NotificationService) NotifyAuditRejected(userID uint, auditType, reason content, &relatedID) } + +// NotifyPostApproved 稿件审核通过通知 +func (s *NotificationService) NotifyPostApproved(userID uint, postTitle string, postID uint) { + title := "稿件审核通过" + content := "你的稿件《" + postTitle + "》已通过审核,现已公开发布" + _ = s.Create(userID, model.NotifyPostApproved, title, content, &postID) +} + +// NotifyPostRejected 稿件审核拒绝通知 +func (s *NotificationService) NotifyPostRejected(userID uint, postTitle, reason string, postID uint) { + title := "稿件审核未通过" + content := "你的稿件《" + postTitle + "》未通过审核" + if reason != "" { + content += ",理由:" + reason + } + _ = s.Create(userID, model.NotifyPostRejected, title, content, &postID) +} diff --git a/internal/service/post_service.go b/internal/service/post_service.go index 2a55835..6ce2d3c 100644 --- a/internal/service/post_service.go +++ b/internal/service/post_service.go @@ -75,15 +75,17 @@ func generateExcerpt(md string) string { // PostService 帖子业务逻辑 type PostService struct { - repo postStore - ss *config.SiteSettings + repo postStore + ss *config.SiteSettings + notifier postNotifier } // NewPostService 构造函数 -func NewPostService(repo postStore, ss *config.SiteSettings) *PostService { +func NewPostService(repo postStore, ss *config.SiteSettings, notifier postNotifier) *PostService { return &PostService{ - repo: repo, - ss: ss, + repo: repo, + ss: ss, + notifier: notifier, } } @@ -263,8 +265,10 @@ func (s *PostService) Approve(postID uint) error { return err } + wasRevision := post.PendingBody != "" + // 修订审核:将待审内容覆盖到正式字段 - if post.PendingBody != "" { + if wasRevision { post.Title = post.PendingTitle post.Body = post.PendingBody post.Excerpt = generateExcerpt(post.PendingBody) @@ -272,7 +276,14 @@ func (s *PostService) Approve(postID uint) error { post.PendingBody = "" post.Status = model.PostStatusApproved post.RejectReason = "" - return s.repo.Update(post) + if err := s.repo.Update(post); err != nil { + return err + } + // 通知作者修订审核通过 + if s.notifier != nil { + s.notifier.NotifyPostApproved(post.UserID, post.Title, post.ID) + } + return nil } // 首次审核通过 @@ -281,7 +292,14 @@ func (s *PostService) Approve(postID uint) error { } post.Status = model.PostStatusApproved post.RejectReason = "" - return s.repo.Update(post) + if err := s.repo.Update(post); err != nil { + return err + } + // 通知作者审核通过 + if s.notifier != nil { + s.notifier.NotifyPostApproved(post.UserID, post.Title, post.ID) + } + return nil } // Reject 退回:pending/approved → rejected;修订退回则清空 Pending 保持 approved @@ -299,13 +317,27 @@ func (s *PostService) Reject(postID uint, reason string) error { post.PendingTitle = "" post.PendingBody = "" post.RejectReason = reason - return s.repo.Update(post) + if err := s.repo.Update(post); err != nil { + return err + } + // 通知作者修订被退回 + if s.notifier != nil { + s.notifier.NotifyPostRejected(post.UserID, post.Title, reason, post.ID) + } + return nil } // 普通退回(首次审核) post.Status = model.PostStatusRejected post.RejectReason = reason - return s.repo.Update(post) + if err := s.repo.Update(post); err != nil { + return err + } + // 通知作者审核被退回 + if s.notifier != nil { + s.notifier.NotifyPostRejected(post.UserID, post.Title, reason, post.ID) + } + return nil } // Lock 锁定:设置 IsLocked 标志,禁止编辑,不改变帖子发布状态 diff --git a/internal/service/repository.go b/internal/service/repository.go index 96edfd3..6854966 100644 --- a/internal/service/repository.go +++ b/internal/service/repository.go @@ -53,4 +53,10 @@ type spaceUserStore interface { // spacePostStore SpaceService 所需的最小帖子仓储接口(ISP:1 个方法) type spacePostStore interface { FindByUserID(userID uint, offset, limit int) ([]model.Post, int64, error) +} + +// postNotifier PostService 所需的通知服务接口(ISP:2 个方法) +type postNotifier interface { + NotifyPostApproved(userID uint, postTitle string, postID uint) + NotifyPostRejected(userID uint, postTitle, reason string, postID uint) } \ No newline at end of file diff --git a/templates/MetaLab-2026/html/messages/index.html b/templates/MetaLab-2026/html/messages/index.html index 4dd171a..4ddf8db 100644 --- a/templates/MetaLab-2026/html/messages/index.html +++ b/templates/MetaLab-2026/html/messages/index.html @@ -21,6 +21,15 @@