fix: 修复通知系统链接错误、标记已读失败及帖子404页渲染异常
- 修复 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 图标无尺寸约束全屏渲染异常
This commit is contained in:
@ -79,6 +79,7 @@ func (ctrl *PostController) ShowPage(c *gin.Context) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
c.HTML(http.StatusNotFound, "posts/404.html", common.BuildPageData(c, gin.H{
|
c.HTML(http.StatusNotFound, "posts/404.html", common.BuildPageData(c, gin.H{
|
||||||
"Title": "未找到",
|
"Title": "未找到",
|
||||||
|
"ExtraCSS": "/static/css/posts.css",
|
||||||
}))
|
}))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -87,6 +88,7 @@ func (ctrl *PostController) ShowPage(c *gin.Context) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
c.HTML(http.StatusNotFound, "posts/404.html", common.BuildPageData(c, gin.H{
|
c.HTML(http.StatusNotFound, "posts/404.html", common.BuildPageData(c, gin.H{
|
||||||
"Title": "未找到",
|
"Title": "未找到",
|
||||||
|
"ExtraCSS": "/static/css/posts.css",
|
||||||
}))
|
}))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -102,6 +104,7 @@ func (ctrl *PostController) ShowPage(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
c.HTML(http.StatusNotFound, "posts/404.html", common.BuildPageData(c, gin.H{
|
c.HTML(http.StatusNotFound, "posts/404.html", common.BuildPageData(c, gin.H{
|
||||||
"Title": "未找到",
|
"Title": "未找到",
|
||||||
|
"ExtraCSS": "/static/css/posts.css",
|
||||||
}))
|
}))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -146,6 +149,7 @@ func (ctrl *PostController) EditPage(c *gin.Context) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
c.HTML(http.StatusNotFound, "posts/404.html", common.BuildPageData(c, gin.H{
|
c.HTML(http.StatusNotFound, "posts/404.html", common.BuildPageData(c, gin.H{
|
||||||
"Title": "未找到",
|
"Title": "未找到",
|
||||||
|
"ExtraCSS": "/static/css/posts.css",
|
||||||
}))
|
}))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -154,6 +158,7 @@ func (ctrl *PostController) EditPage(c *gin.Context) {
|
|||||||
if err != nil || post.Status == model.PostStatusPending || post.IsLocked {
|
if err != nil || post.Status == model.PostStatusPending || post.IsLocked {
|
||||||
c.HTML(http.StatusNotFound, "posts/404.html", common.BuildPageData(c, gin.H{
|
c.HTML(http.StatusNotFound, "posts/404.html", common.BuildPageData(c, gin.H{
|
||||||
"Title": "未找到或无法编辑",
|
"Title": "未找到或无法编辑",
|
||||||
|
"ExtraCSS": "/static/css/posts.css",
|
||||||
}))
|
}))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -162,6 +167,7 @@ func (ctrl *PostController) EditPage(c *gin.Context) {
|
|||||||
if !ctrl.postService.IsPostAccessible(uid, role, post.UserID) {
|
if !ctrl.postService.IsPostAccessible(uid, role, post.UserID) {
|
||||||
c.HTML(http.StatusNotFound, "posts/404.html", common.BuildPageData(c, gin.H{
|
c.HTML(http.StatusNotFound, "posts/404.html", common.BuildPageData(c, gin.H{
|
||||||
"Title": "未找到",
|
"Title": "未找到",
|
||||||
|
"ExtraCSS": "/static/css/posts.css",
|
||||||
}))
|
}))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -50,7 +50,7 @@ func (r *NotificationRepo) CountUnread(userID uint) (int64, error) {
|
|||||||
// MarkRead 标记单条消息为已读
|
// MarkRead 标记单条消息为已读
|
||||||
func (r *NotificationRepo) MarkRead(id, userID uint) error {
|
func (r *NotificationRepo) MarkRead(id, userID uint) error {
|
||||||
return r.db.Model(&model.Notification{}).
|
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
|
Update("is_read", true).Error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -37,7 +37,7 @@ func (r *PostRepo) FindByIDWithAuthor(id uint) (*model.Post, error) {
|
|||||||
err := r.db.Table("posts").
|
err := r.db.Table("posts").
|
||||||
Select("posts.*, users.username as author_name").
|
Select("posts.*, users.username as author_name").
|
||||||
Joins("LEFT JOIN users ON users.uid = posts.user_id").
|
Joins("LEFT JOIN users ON users.uid = posts.user_id").
|
||||||
Where("posts.id = ?", id).
|
Where("posts.uid = ?", id).
|
||||||
First(&post).Error
|
First(&post).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -157,7 +157,7 @@ func (r *PostRepo) CountPending() (int64, error) {
|
|||||||
|
|
||||||
// Restore 恢复软删除
|
// Restore 恢复软删除
|
||||||
func (r *PostRepo) Restore(id uint) error {
|
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 {
|
if result.Error != nil {
|
||||||
return result.Error
|
return result.Error
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,11 +40,9 @@
|
|||||||
{{range $i, $m := .Messages}}
|
{{range $i, $m := .Messages}}
|
||||||
{{$link := ""}}
|
{{$link := ""}}
|
||||||
{{if or (eq $m.NotifyType "post_approved") (eq $m.NotifyType "post_rejected")}}
|
{{if or (eq $m.NotifyType "post_approved") (eq $m.NotifyType "post_rejected")}}
|
||||||
{{if eq $m.NotifyType "post_approved"}}
|
|
||||||
{{$link = printf "/posts/%d" $m.RelatedID}}
|
{{$link = printf "/posts/%d" $m.RelatedID}}
|
||||||
{{else}}
|
{{else if or (eq $m.NotifyType "audit_approved") (eq $m.NotifyType "audit_rejected")}}
|
||||||
{{$link = "/studio/posts"}}
|
{{$link = "/settings"}}
|
||||||
{{end}}
|
|
||||||
{{end}}
|
{{end}}
|
||||||
{{if $link}}
|
{{if $link}}
|
||||||
<a href="{{$link}}" class="msg-card-link">
|
<a href="{{$link}}" class="msg-card-link">
|
||||||
@ -107,10 +105,26 @@
|
|||||||
(function (card) {
|
(function (card) {
|
||||||
card.addEventListener('click', function (e) {
|
card.addEventListener('click', function (e) {
|
||||||
var link = card.getAttribute('data-link');
|
var link = card.getAttribute('data-link');
|
||||||
// 如果是可跳转的通知(post 审核),不阻止默认行为,只标记已读
|
|
||||||
// 标记已读通过 fetch 发送,不阻止链接跳转
|
|
||||||
var id = card.getAttribute('data-id');
|
var id = card.getAttribute('data-id');
|
||||||
if (!id) return;
|
if (!id) return;
|
||||||
|
|
||||||
|
if (link) {
|
||||||
|
// 有链接的通知:使用 fetch keepalive 确保页面跳转前标记已读不会丢失
|
||||||
|
e.preventDefault();
|
||||||
|
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();
|
var xhr = new XMLHttpRequest();
|
||||||
xhr.open('POST', '/api/messages/' + id + '/read', true);
|
xhr.open('POST', '/api/messages/' + id + '/read', true);
|
||||||
xhr.onreadystatechange = function () {
|
xhr.onreadystatechange = function () {
|
||||||
@ -122,14 +136,6 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
xhr.send();
|
xhr.send();
|
||||||
|
|
||||||
// 如果有链接,在标记已读后跳转(非 post 通知直接标记已读)
|
|
||||||
if (link) {
|
|
||||||
e.preventDefault();
|
|
||||||
var self = this;
|
|
||||||
setTimeout(function () {
|
|
||||||
window.location.href = link;
|
|
||||||
}, 200);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
})(cards[i]);
|
})(cards[i]);
|
||||||
|
|||||||
Reference in New Issue
Block a user