diff --git a/internal/controller/admin/admin_post_controller.go b/internal/controller/admin/admin_post_controller.go index 8e488cd..7e7633d 100644 --- a/internal/controller/admin/admin_post_controller.go +++ b/internal/controller/admin/admin_post_controller.go @@ -116,7 +116,13 @@ func (ctrl *AdminPostController) Lock(c *gin.Context) { return } - if err := ctrl.postService.Lock(uint(id)); err != nil { + var req model.PostLockRequest + if err := c.ShouldBindJSON(&req); err != nil { + common.Error(c, http.StatusBadRequest, "请填写锁定理由") + return + } + + if err := ctrl.postService.Lock(uint(id), req.Reason); err != nil { if errors.Is(err, common.ErrPostNotFound) || errors.Is(err, common.ErrPostCannotLock) { common.Error(c, http.StatusBadRequest, err.Error()) } else { diff --git a/internal/controller/admin/interfaces.go b/internal/controller/admin/interfaces.go index 14e2337..d29f228 100644 --- a/internal/controller/admin/interfaces.go +++ b/internal/controller/admin/interfaces.go @@ -42,7 +42,7 @@ type adminPostUseCase interface { ListPendingRevisions(keyword string, page, pageSize int) ([]model.Post, int64, error) Approve(postID uint) error Reject(postID uint, reason string) error - Lock(postID uint) error + Lock(postID uint, reason string) error Unlock(postID uint) error Restore(postID uint) error } diff --git a/internal/controller/studio_controller.go b/internal/controller/studio_controller.go index 1bb98ec..4ffe6da 100644 --- a/internal/controller/studio_controller.go +++ b/internal/controller/studio_controller.go @@ -154,7 +154,6 @@ func (ctrl *StudioController) WritePage(c *gin.Context) { "Post": post, "ActiveTab": "write", "ExtraCSS": "/static/css/studio.css", - "StatusNames": common.PostStatusDisplayNames, })) return } diff --git a/internal/model/dto.go b/internal/model/dto.go index 93787b3..4a486dd 100644 --- a/internal/model/dto.go +++ b/internal/model/dto.go @@ -47,6 +47,11 @@ type PostRejectRequest struct { Reason string `json:"reason" binding:"required,min=1,max=500"` } +// PostLockRequest 锁定请求 +type PostLockRequest struct { + Reason string `json:"reason" binding:"required,min=1,max=500"` +} + // PostListQuery 列表查询参数 type PostListQuery struct { Keyword string `form:"keyword"` diff --git a/internal/model/post.go b/internal/model/post.go index 77a85ce..8103e80 100644 --- a/internal/model/post.go +++ b/internal/model/post.go @@ -15,6 +15,7 @@ type Post struct { UserID uint `gorm:"index;not null" json:"user_id"` Status string `gorm:"type:varchar(20);index;default:draft;not null" json:"status"` IsLocked bool `gorm:"default:false" json:"is_locked"` + LockReason string `gorm:"type:varchar(500);default:''" json:"lock_reason,omitempty"` PendingTitle string `gorm:"type:varchar(200);default:''" json:"pending_title,omitempty"` PendingBody string `gorm:"type:text" json:"pending_body,omitempty"` RejectReason string `gorm:"type:varchar(500);default:''" json:"reject_reason,omitempty"` diff --git a/internal/service/post_service.go b/internal/service/post_service.go index 6ce2d3c..2916107 100644 --- a/internal/service/post_service.go +++ b/internal/service/post_service.go @@ -341,7 +341,7 @@ func (s *PostService) Reject(postID uint, reason string) error { } // Lock 锁定:设置 IsLocked 标志,禁止编辑,不改变帖子发布状态 -func (s *PostService) Lock(postID uint) error { +func (s *PostService) Lock(postID uint, reason string) error { post, err := s.findPost(postID) if err != nil { return err @@ -351,6 +351,7 @@ func (s *PostService) Lock(postID uint) error { return common.ErrPostCannotLock } post.IsLocked = true + post.LockReason = reason return s.repo.Update(post) } @@ -364,6 +365,7 @@ func (s *PostService) Unlock(postID uint) error { return common.ErrPostCannotUnlock } post.IsLocked = false + post.LockReason = "" return s.repo.Update(post) } diff --git a/templates/MetaLab-2026/html/studio/write.html b/templates/MetaLab-2026/html/studio/write.html index 5bc44e7..2f33f19 100644 --- a/templates/MetaLab-2026/html/studio/write.html +++ b/templates/MetaLab-2026/html/studio/write.html @@ -13,7 +13,9 @@
🔒
这篇文章已被锁定,无法编辑。 -

如需解锁请联系管理员。当前状态:{{if $.StatusNames}}{{index $.StatusNames .Post.Status}}、已锁定{{end}}

+ {{if .Post.LockReason}} +

锁定理由:{{.Post.LockReason}}

+ {{end}}
{{end}} diff --git a/templates/admin/static/js/posts.js b/templates/admin/static/js/posts.js index aae9241..1f9f53c 100644 --- a/templates/admin/static/js/posts.js +++ b/templates/admin/static/js/posts.js @@ -47,7 +47,9 @@ // 锁定 handleClick('.post-lock', function(id) { - api('/api/admin/posts/' + id + '/lock', 'POST') + var reason = prompt('请输入锁定理由(必填):'); + if (!reason || !reason.trim()) return; + api('/api/admin/posts/' + id + '/lock', 'POST', { reason: reason.trim() }) .then(function(d) { if (d.success) refreshPage(); else alert(d.message); }) .catch(function() { alert('操作失败'); }); });