From 59af6b26353f4b71ce86524d4371698bb048832d Mon Sep 17 00:00:00 2001 From: Victor_Jay Date: Sun, 31 May 2026 13:33:12 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E9=80=9A=E7=9F=A5?= =?UTF-8?q?=E7=B3=BB=E7=BB=9F=E9=93=BE=E6=8E=A5=E9=94=99=E8=AF=AF=E3=80=81?= =?UTF-8?q?=E6=A0=87=E8=AE=B0=E5=B7=B2=E8=AF=BB=E5=A4=B1=E8=B4=A5=E5=8F=8A?= =?UTF-8?q?=E5=B8=96=E5=AD=90404=E9=A1=B5=E6=B8=B2=E6=9F=93=E5=BC=82?= =?UTF-8?q?=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修复 post_rejected 通知链接到帖子详情页(原来链接到 /studio/posts) - 为 audit_approved/audit_rejected 通知添加链接到 /settings - 通知已读标记改用 fetch keepalive 代替 sendBeacon,附带 CSRF token,避免页面跳转时请求丢失 - 修复 repository 层 id 列名应为 uid(BaseModel 定义 primarykey column:uid) - 帖子404页添加 ExtraCSS 引入 posts.css,修复 SVG 图标无尺寸约束全屏渲染异常 --- internal/controller/post_controller.go | 18 ++++--- internal/repository/notification_repo.go | 2 +- internal/repository/post_repo.go | 4 +- .../MetaLab-2026/html/messages/index.html | 52 +++++++++++-------- 4 files changed, 44 insertions(+), 32 deletions(-) diff --git a/internal/controller/post_controller.go b/internal/controller/post_controller.go index 6f3a287..01190e1 100644 --- a/internal/controller/post_controller.go +++ b/internal/controller/post_controller.go @@ -78,7 +78,8 @@ func (ctrl *PostController) ShowPage(c *gin.Context) { id, err := strconv.ParseUint(c.Param("id"), 10, 64) if err != nil { c.HTML(http.StatusNotFound, "posts/404.html", common.BuildPageData(c, gin.H{ - "Title": "未找到", + "Title": "未找到", + "ExtraCSS": "/static/css/posts.css", })) return } @@ -86,7 +87,8 @@ func (ctrl *PostController) ShowPage(c *gin.Context) { post, err := ctrl.postService.GetByID(uint(id)) if err != nil { c.HTML(http.StatusNotFound, "posts/404.html", common.BuildPageData(c, gin.H{ - "Title": "未找到", + "Title": "未找到", + "ExtraCSS": "/static/css/posts.css", })) return } @@ -101,7 +103,8 @@ func (ctrl *PostController) ShowPage(c *gin.Context) { return } c.HTML(http.StatusNotFound, "posts/404.html", common.BuildPageData(c, gin.H{ - "Title": "未找到", + "Title": "未找到", + "ExtraCSS": "/static/css/posts.css", })) return } @@ -145,7 +148,8 @@ func (ctrl *PostController) EditPage(c *gin.Context) { id, err := strconv.ParseUint(c.Param("id"), 10, 64) if err != nil { c.HTML(http.StatusNotFound, "posts/404.html", common.BuildPageData(c, gin.H{ - "Title": "未找到", + "Title": "未找到", + "ExtraCSS": "/static/css/posts.css", })) return } @@ -153,7 +157,8 @@ func (ctrl *PostController) EditPage(c *gin.Context) { post, err := ctrl.postService.GetByID(uint(id)) if err != nil || post.Status == model.PostStatusPending || post.IsLocked { c.HTML(http.StatusNotFound, "posts/404.html", common.BuildPageData(c, gin.H{ - "Title": "未找到或无法编辑", + "Title": "未找到或无法编辑", + "ExtraCSS": "/static/css/posts.css", })) return } @@ -161,7 +166,8 @@ func (ctrl *PostController) EditPage(c *gin.Context) { uid, role, _ := common.GetGinUser(c) if !ctrl.postService.IsPostAccessible(uid, role, post.UserID) { c.HTML(http.StatusNotFound, "posts/404.html", common.BuildPageData(c, gin.H{ - "Title": "未找到", + "Title": "未找到", + "ExtraCSS": "/static/css/posts.css", })) return } diff --git a/internal/repository/notification_repo.go b/internal/repository/notification_repo.go index e585ab2..4dac368 100644 --- a/internal/repository/notification_repo.go +++ b/internal/repository/notification_repo.go @@ -50,7 +50,7 @@ func (r *NotificationRepo) CountUnread(userID uint) (int64, error) { // MarkRead 标记单条消息为已读 func (r *NotificationRepo) MarkRead(id, userID uint) error { return r.db.Model(&model.Notification{}). - Where("id = ? AND user_id = ?", id, userID). + Where("uid = ? AND user_id = ?", id, userID). Update("is_read", true).Error } diff --git a/internal/repository/post_repo.go b/internal/repository/post_repo.go index b60fc37..62185f2 100644 --- a/internal/repository/post_repo.go +++ b/internal/repository/post_repo.go @@ -37,7 +37,7 @@ func (r *PostRepo) FindByIDWithAuthor(id uint) (*model.Post, error) { err := r.db.Table("posts"). Select("posts.*, users.username as author_name"). Joins("LEFT JOIN users ON users.uid = posts.user_id"). - Where("posts.id = ?", id). + Where("posts.uid = ?", id). First(&post).Error if err != nil { return nil, err @@ -157,7 +157,7 @@ func (r *PostRepo) CountPending() (int64, error) { // Restore 恢复软删除 func (r *PostRepo) Restore(id uint) error { - result := r.db.Unscoped().Model(&model.Post{}).Where("id = ?", id).Update("deleted_at", nil) + result := r.db.Unscoped().Model(&model.Post{}).Where("uid = ?", id).Update("deleted_at", nil) if result.Error != nil { return result.Error } diff --git a/templates/MetaLab-2026/html/messages/index.html b/templates/MetaLab-2026/html/messages/index.html index fe81667..087d896 100644 --- a/templates/MetaLab-2026/html/messages/index.html +++ b/templates/MetaLab-2026/html/messages/index.html @@ -40,11 +40,9 @@ {{range $i, $m := .Messages}} {{$link := ""}} {{if or (eq $m.NotifyType "post_approved") (eq $m.NotifyType "post_rejected")}} - {{if eq $m.NotifyType "post_approved"}} - {{$link = printf "/posts/%d" $m.RelatedID}} - {{else}} - {{$link = "/studio/posts"}} - {{end}} + {{$link = printf "/posts/%d" $m.RelatedID}} + {{else if or (eq $m.NotifyType "audit_approved") (eq $m.NotifyType "audit_rejected")}} + {{$link = "/settings"}} {{end}} {{if $link}} @@ -107,29 +105,37 @@ (function (card) { card.addEventListener('click', function (e) { var link = card.getAttribute('data-link'); - // 如果是可跳转的通知(post 审核),不阻止默认行为,只标记已读 - // 标记已读通过 fetch 发送,不阻止链接跳转 var id = card.getAttribute('data-id'); if (!id) return; - var xhr = new XMLHttpRequest(); - xhr.open('POST', '/api/messages/' + id + '/read', true); - xhr.onreadystatechange = function () { - if (xhr.readyState === 4 && xhr.status === 200) { - card.classList.remove('unread'); - var badge = card.querySelector('.msg-badge'); - if (badge) badge.remove(); - updateUnreadCounts(); - } - }; - xhr.send(); - // 如果有链接,在标记已读后跳转(非 post 通知直接标记已读) if (link) { + // 有链接的通知:使用 fetch keepalive 确保页面跳转前标记已读不会丢失 e.preventDefault(); - var self = this; - setTimeout(function () { - window.location.href = link; - }, 200); + var csrfMeta = document.querySelector('meta[name="csrf-token"]'); + var csrfToken = csrfMeta ? csrfMeta.getAttribute('content') : ''; + fetch('/api/messages/' + id + '/read', { + method: 'POST', + keepalive: true, + headers: { 'X-CSRF-Token': csrfToken } + }); + card.classList.remove('unread'); + var badge = card.querySelector('.msg-badge'); + if (badge) badge.remove(); + updateUnreadCounts(); + window.location.href = link; + } else { + // 无链接的通知:使用 XHR 标记已读 + var xhr = new XMLHttpRequest(); + xhr.open('POST', '/api/messages/' + id + '/read', true); + xhr.onreadystatechange = function () { + if (xhr.readyState === 4 && xhr.status === 200) { + card.classList.remove('unread'); + var badge = card.querySelector('.msg-badge'); + if (badge) badge.remove(); + updateUnreadCounts(); + } + }; + xhr.send(); } }); })(cards[i]);