feat: 对接稿件审核通知系统 + 消息页面系统消息区域

- 新增通知类型 post_approved / post_rejected
- PostService.Approve/Reject 完成后通知作者(通知失败不影响主流程)
- NotificationService 新增 NotifyPostApproved/NotifyPostRejected 方法
- 消息页面顶部增加系统消息标识和分隔线,之下为全部消息列表
- 稿件审核通过通知卡片点击跳转到 /posts/{id} 页面
- 稿件审核拒绝通知卡片点击跳转到 /studio/posts 创作中心
- 新增 postNotifier 接口遵循 ISP 原则
This commit is contained in:
2026-05-30 21:24:30 +08:00
parent fb94ce60ae
commit 67444434b9
7 changed files with 148 additions and 17 deletions

View File

@ -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 标志,禁止编辑,不改变帖子发布状态