fix: 空评论列表 500,并完善撤回审计与角色说明
空切片 JSON 统一为数组;撤回保留正文供站长阅读,成员侧居中提示与重新编辑;头像支持拖放;角色弹窗补全职责说明并汇入封禁。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -102,7 +102,7 @@ func (h *Handlers) AdminUserLoginLogs(c *gin.Context) {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "获取登录历史失败"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"logs": logs, "total": total, "page": page})
|
||||
c.JSON(http.StatusOK, gin.H{"logs": nonNilSlice(logs), "total": total, "page": page})
|
||||
}
|
||||
|
||||
// AdminGetUserAudit 站长:用户内容档案摘要
|
||||
@@ -131,7 +131,7 @@ func (h *Handlers) AdminUserAuditPosts(c *gin.Context) {
|
||||
respondAdminUserError(c, err)
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"items": items, "total": total, "page": page})
|
||||
c.JSON(http.StatusOK, gin.H{"items": nonNilSlice(items), "total": total, "page": page})
|
||||
}
|
||||
|
||||
// AdminUserAuditComments 站长:用户评论(含驳回/软删)
|
||||
@@ -146,7 +146,7 @@ func (h *Handlers) AdminUserAuditComments(c *gin.Context) {
|
||||
respondAdminUserError(c, err)
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"items": items, "total": total, "page": page})
|
||||
c.JSON(http.StatusOK, gin.H{"items": nonNilSlice(items), "total": total, "page": page})
|
||||
}
|
||||
|
||||
// AdminUserAuditMessages 站长:用户聊天消息(含撤回/软删)
|
||||
@@ -161,7 +161,7 @@ func (h *Handlers) AdminUserAuditMessages(c *gin.Context) {
|
||||
respondAdminUserError(c, err)
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"items": items, "total": total, "page": page})
|
||||
c.JSON(http.StatusOK, gin.H{"items": nonNilSlice(items), "total": total, "page": page})
|
||||
}
|
||||
|
||||
// parseAdminUserID 解析路径中的用户 ID,失败时直接写出 400
|
||||
|
||||
@@ -19,7 +19,7 @@ func (h *Handlers) AnnouncementsList(c *gin.Context) {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "获取公告失败"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"announcements": list})
|
||||
c.JSON(http.StatusOK, gin.H{"announcements": nonNilSlice(list)})
|
||||
}
|
||||
|
||||
// AnnouncementDetail 已发布公告详情
|
||||
@@ -50,7 +50,7 @@ func (h *Handlers) AdminListAnnouncements(c *gin.Context) {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "获取公告失败"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"announcements": list})
|
||||
c.JSON(http.StatusOK, gin.H{"announcements": nonNilSlice(list)})
|
||||
}
|
||||
|
||||
// AdminCreateAnnouncement 新建公告
|
||||
|
||||
@@ -13,5 +13,5 @@ func (h *Handlers) Boards(c *gin.Context) {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"boards": boards})
|
||||
c.JSON(http.StatusOK, gin.H{"boards": nonNilSlice(boards)})
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ func (h *Handlers) ListChatRooms(c *gin.Context) {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "获取会话列表失败"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"rooms": rooms, "total": total, "page": page, "size": size})
|
||||
c.JSON(http.StatusOK, gin.H{"rooms": nonNilSlice(rooms), "total": total, "page": page, "size": size})
|
||||
}
|
||||
|
||||
// GetChatRoom 群详情(公开非成员可预览;私密非成员 404)
|
||||
@@ -273,7 +273,7 @@ func (h *Handlers) ListChatMembers(c *gin.Context) {
|
||||
c.JSON(chatErrToStatus(err), gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"members": list})
|
||||
c.JSON(http.StatusOK, gin.H{"members": nonNilSlice(list)})
|
||||
}
|
||||
|
||||
// KickChatMember 群主踢人
|
||||
@@ -315,7 +315,7 @@ func (h *Handlers) ListChatMessages(c *gin.Context) {
|
||||
c.JSON(chatErrToStatus(err), gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"messages": msgs, "has_more": hasMore})
|
||||
c.JSON(http.StatusOK, gin.H{"messages": nonNilSlice(msgs), "has_more": hasMore})
|
||||
}
|
||||
|
||||
// SendChatMessage 发消息
|
||||
@@ -387,16 +387,30 @@ func (h *Handlers) RecallChatMessage(c *gin.Context) {
|
||||
c.JSON(chatErrToStatus(err), gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
data := gin.H{
|
||||
"id": msg.ID,
|
||||
"room_id": roomID,
|
||||
"sender_id": msg.SenderID,
|
||||
"recalled_by": msg.RecalledBy,
|
||||
"recalled_at": msg.RecalledAt,
|
||||
}
|
||||
if msg.Recaller != nil && msg.Recaller.ID > 0 {
|
||||
data["recaller"] = gin.H{
|
||||
"id": msg.Recaller.ID,
|
||||
"username": msg.Recaller.Username,
|
||||
"nickname": msg.Recaller.Nickname,
|
||||
"avatar": msg.Recaller.Avatar,
|
||||
"role": msg.Recaller.Role,
|
||||
}
|
||||
}
|
||||
h.Hub.BroadcastRoom(realtime.RoomChat(roomID), realtime.Envelope{
|
||||
Type: realtime.EventChatRecalled,
|
||||
Data: gin.H{
|
||||
"id": msg.ID,
|
||||
"room_id": roomID,
|
||||
"sender_id": msg.SenderID,
|
||||
"recalled_by": msg.RecalledBy,
|
||||
"recalled_at": msg.RecalledAt,
|
||||
},
|
||||
Data: data,
|
||||
})
|
||||
// 监管者保留正文供界面展示;撤回者本人保留正文供「重新编辑」;其余不回传
|
||||
if !oversee && msg.SenderID != claims.ID {
|
||||
msg.Content = ""
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"message": msg})
|
||||
}
|
||||
|
||||
@@ -444,7 +458,7 @@ func (h *Handlers) SearchChatUsers(c *gin.Context) {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "搜索失败"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"users": users})
|
||||
c.JSON(http.StatusOK, gin.H{"users": nonNilSlice(users)})
|
||||
}
|
||||
|
||||
// ChatUnreadSummary 未读汇总
|
||||
|
||||
@@ -44,7 +44,7 @@ func (h *Handlers) PostComments(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"comments": comments,
|
||||
"comments": nonNilSlice(comments),
|
||||
"total": floors, // 楼层数(主评论数)→ 前端分页与楼层号计算
|
||||
"total_comments": totalComments, // 全部评论数(含回复)→ 展示徽标
|
||||
"page": page,
|
||||
|
||||
9
backend/handler/jsonutil.go
Normal file
9
backend/handler/jsonutil.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package handler
|
||||
|
||||
// nonNilSlice 保证 JSON 序列化为 [] 而非 null(Go nil slice 会编成 null)。
|
||||
func nonNilSlice[T any](s []T) []T {
|
||||
if s == nil {
|
||||
return []T{}
|
||||
}
|
||||
return s
|
||||
}
|
||||
@@ -21,7 +21,7 @@ func (h *Handlers) AdminPendingPosts(c *gin.Context) {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "获取待审帖子失败"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"posts": posts, "total": total, "page": page})
|
||||
c.JSON(http.StatusOK, gin.H{"posts": nonNilSlice(posts), "total": total, "page": page})
|
||||
}
|
||||
|
||||
// AdminPendingComments 待审核评论分页
|
||||
@@ -32,7 +32,7 @@ func (h *Handlers) AdminPendingComments(c *gin.Context) {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "获取待审评论失败"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"comments": comments, "total": total, "page": page})
|
||||
c.JSON(http.StatusOK, gin.H{"comments": nonNilSlice(comments), "total": total, "page": page})
|
||||
}
|
||||
|
||||
// AdminPendingCounts 当前操作者可见的待审数量(导航角标)
|
||||
|
||||
@@ -20,7 +20,7 @@ func (h *Handlers) Notifications(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"notifications": list,
|
||||
"notifications": nonNilSlice(list),
|
||||
"total": total,
|
||||
"page": page,
|
||||
"size": size,
|
||||
|
||||
@@ -77,7 +77,7 @@ func (h *Handlers) MyMedia(c *gin.Context) {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"attachments": list})
|
||||
c.JSON(http.StatusOK, gin.H{"attachments": nonNilSlice(list)})
|
||||
}
|
||||
|
||||
// DeleteAttachment 彻底删除本人附件(DB + 物理文件)
|
||||
|
||||
@@ -104,6 +104,9 @@ func (h *Handlers) UserProfile(c *gin.Context) {
|
||||
if user.Role == model.RoleBoardAdmin {
|
||||
boardIDs, _ = h.Auth.GetUserBoardIDs(user.ID)
|
||||
}
|
||||
if boardIDs == nil {
|
||||
boardIDs = []uint{}
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"user": gin.H{
|
||||
@@ -122,7 +125,7 @@ func (h *Handlers) UserProfile(c *gin.Context) {
|
||||
"points": pointsTotal,
|
||||
"streak": streak,
|
||||
},
|
||||
"posts": posts,
|
||||
"posts": nonNilSlice(posts),
|
||||
"posts_total": postsTotal,
|
||||
"page": page,
|
||||
"size": size,
|
||||
@@ -152,7 +155,7 @@ func (h *Handlers) UserComments(c *gin.Context) {
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"comments": comments,
|
||||
"comments": nonNilSlice(comments),
|
||||
"total": total,
|
||||
"page": page,
|
||||
"size": size,
|
||||
|
||||
Reference in New Issue
Block a user