212 lines
5.4 KiB
Go
212 lines
5.4 KiB
Go
package service
|
||
|
||
import (
|
||
"metazone.cc/mce/internal/common"
|
||
"metazone.cc/mce/internal/model"
|
||
)
|
||
|
||
// Update 编辑帖子(权限在 controller 层检查)
|
||
func (s *PostService) Update(postID uint, title, body string) error {
|
||
post, err := s.findPost(postID)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
if post.Status == model.PostStatusPending || post.IsLocked {
|
||
return common.ErrPostCannotEdit
|
||
}
|
||
|
||
// 已通过帖子:编辑内容保存为待审修订,不影响当前展示
|
||
if post.Status == model.PostStatusApproved {
|
||
post.PendingTitle = title
|
||
post.PendingBody = body
|
||
post.RejectReason = "" // 清空旧退回理由
|
||
err := s.repo.Update(post)
|
||
if err == nil {
|
||
s.invalidateHomeCache()
|
||
}
|
||
return err
|
||
}
|
||
|
||
// 草稿/已退回:直接修改原文(现有逻辑)
|
||
post.Title = title
|
||
post.Body = body
|
||
post.Excerpt = generateExcerpt(body)
|
||
|
||
if post.Status == model.PostStatusRejected {
|
||
post.Status = model.PostStatusDraft
|
||
post.RejectReason = ""
|
||
}
|
||
|
||
err = s.repo.Update(post)
|
||
if err == nil {
|
||
s.invalidateHomeCache()
|
||
}
|
||
return err
|
||
}
|
||
|
||
// Delete 软删除(权限在 controller 层检查)
|
||
func (s *PostService) Delete(postID uint) error {
|
||
if err := s.repo.SoftDelete(postID); err != nil {
|
||
return err
|
||
}
|
||
s.invalidateHomeCache()
|
||
return nil
|
||
}
|
||
|
||
// SubmitForAudit 提交审核:draft → pending
|
||
func (s *PostService) SubmitForAudit(postID uint) error {
|
||
post, err := s.findPost(postID)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
if post.IsLocked {
|
||
return common.ErrPostCannotEdit
|
||
}
|
||
if post.Status != model.PostStatusDraft && post.Status != model.PostStatusRejected {
|
||
return common.ErrPostCannotSubmit
|
||
}
|
||
post.Status = model.PostStatusPending
|
||
return s.repo.Update(post)
|
||
}
|
||
|
||
// Approve 审核通过:pending → approved;或修订审核通过复制 Pending 到正式字段
|
||
func (s *PostService) Approve(postID uint) error {
|
||
post, err := s.findPost(postID)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
wasRevision := post.PendingBody != ""
|
||
|
||
// 修订审核:将待审内容覆盖到正式字段
|
||
if wasRevision {
|
||
post.Title = post.PendingTitle
|
||
post.Body = post.PendingBody
|
||
post.Excerpt = generateExcerpt(post.PendingBody)
|
||
post.PendingTitle = ""
|
||
post.PendingBody = ""
|
||
post.Status = model.PostStatusApproved
|
||
post.RejectReason = ""
|
||
if err := s.repo.Update(post); err != nil {
|
||
return err
|
||
}
|
||
s.invalidateHomeCache()
|
||
// 通知作者修订审核通过
|
||
if s.notifier != nil {
|
||
s.notifier.NotifyPostApproved(post.UserID, post.Title, post.ID)
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// 首次审核通过
|
||
if post.Status != model.PostStatusPending {
|
||
return common.ErrPostCannotApprove
|
||
}
|
||
post.Status = model.PostStatusApproved
|
||
post.RejectReason = ""
|
||
if err := s.repo.Update(post); err != nil {
|
||
return err
|
||
}
|
||
s.invalidateHomeCache()
|
||
// 通知作者审核通过
|
||
if s.notifier != nil {
|
||
s.notifier.NotifyPostApproved(post.UserID, post.Title, post.ID)
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// Reject 退回:pending/approved → rejected;修订退回则清空 Pending 保持 approved
|
||
func (s *PostService) Reject(postID uint, reason string) error {
|
||
post, err := s.findPost(postID)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
if post.Status != model.PostStatusPending && post.Status != model.PostStatusApproved {
|
||
return common.ErrPostCannotReject
|
||
}
|
||
|
||
// 修订退回:清空待审修订,保持已发布内容不变
|
||
if post.PendingBody != "" {
|
||
post.PendingTitle = ""
|
||
post.PendingBody = ""
|
||
post.RejectReason = reason
|
||
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
|
||
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 标志,禁止编辑,不改变帖子发布状态
|
||
// 锁定状态独立于审核状态,任何状态的帖子均可锁定
|
||
func (s *PostService) Lock(postID uint, reason string) error {
|
||
post, err := s.findPost(postID)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
post.IsLocked = true
|
||
post.LockReason = reason
|
||
if err := s.repo.Update(post); err != nil {
|
||
return err
|
||
}
|
||
// 通知作者稿件被锁定
|
||
if s.notifier != nil {
|
||
s.notifier.NotifyPostLocked(post.UserID, post.Title, reason, post.ID)
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// Unlock 解锁:清除 IsLocked 标志,恢复可编辑
|
||
func (s *PostService) Unlock(postID uint) error {
|
||
post, err := s.findPost(postID)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
if !post.IsLocked {
|
||
return common.ErrPostCannotUnlock
|
||
}
|
||
post.IsLocked = false
|
||
post.LockReason = ""
|
||
if err := s.repo.Update(post); err != nil {
|
||
return err
|
||
}
|
||
// 通知作者稿件被解除锁定
|
||
if s.notifier != nil {
|
||
s.notifier.NotifyPostUnlocked(post.UserID, post.Title, post.ID)
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// Restore 恢复软删除
|
||
func (s *PostService) Restore(postID uint) error {
|
||
err := s.repo.Restore(postID)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// ListPendingRevisions 查询有待审修订的帖子(approved 且 PendingBody 不为空)
|
||
func (s *PostService) ListPendingRevisions(keyword string, page, pageSize int) ([]model.Post, int64, error) {
|
||
return s.listPageable(page, pageSize, func(offset, limit int) ([]model.Post, int64, error) {
|
||
return s.repo.FindPendingRevisions(keyword, offset, limit)
|
||
})
|
||
}
|