feat: 实时消息与管理端运营能力

新增群聊/私信与公共 WebSocket 总线,站长用户内容档案,并将通知与待审角标改为推送驱动;同步精简管理仪表盘并修复主题换肤 DOM 冲突。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-15 22:58:16 +08:00
parent 29db9ae9b5
commit 42c395a864
55 changed files with 7607 additions and 346 deletions

View File

@@ -8,6 +8,7 @@ import (
"github.com/freefire/jiang13-bbs/handler"
"github.com/freefire/jiang13-bbs/middleware"
"github.com/freefire/jiang13-bbs/model"
"github.com/freefire/jiang13-bbs/realtime"
"github.com/freefire/jiang13-bbs/service"
"github.com/gin-contrib/cors"
"github.com/gin-gonic/gin"
@@ -51,6 +52,7 @@ func Setup(cfg *config.Config) (*gin.Engine, error) {
settingSvc := service.NewSettingService(model.DB)
adminUserSvc := service.NewAdminUserService(model.DB)
moderationSvc := service.NewModerationService(model.DB, notifSvc)
chatSvc := service.NewChatService(model.DB, notifSvc)
if err := uploadSvc.EnsureDir(); err != nil {
return nil, err
}
@@ -58,6 +60,7 @@ func Setup(cfg *config.Config) (*gin.Engine, error) {
h := &handler.Handlers{
Cfg: cfg,
Hub: realtime.NewHub(),
Auth: authSvc,
Board: boardSvc,
Post: postSvc,
@@ -71,6 +74,16 @@ func Setup(cfg *config.Config) (*gin.Engine, error) {
Setting: settingSvc,
AdminUser: adminUserSvc,
Moderation: moderationSvc,
Chat: chatSvc,
}
// 通知落库后统一推 WS 红点(点赞/评论/审核/@ 等共用)
notifSvc.OnNotifyNew = func(userID uint) {
if h.Hub == nil {
return
}
h.Hub.BroadcastUser(userID, realtime.Envelope{
Type: realtime.EventNotificationNew,
})
}
authMW := middleware.NewAuthMiddleware(authSvc)
@@ -83,6 +96,9 @@ func Setup(cfg *config.Config) (*gin.Engine, error) {
r.GET("/robots.txt", h.RobotsTxt)
r.GET("/sitemap.xml", h.SitemapXML)
// 实时通信总线(WebSocket,cookie 鉴权 + Origin 校验,处理器内部完成鉴权升级)
r.GET("/api/ws", h.RealtimeWS)
// 公开 API(可选登录)
pubAPI := r.Group("/api", authMW.OptionalAuth())
{
@@ -131,6 +147,26 @@ func Setup(cfg *config.Config) (*gin.Engine, error) {
api.PUT("/avatar/use", h.UseAvatar)
api.GET("/my/media", h.MyMedia)
api.DELETE("/my/attachments/:id", h.DeleteAttachment)
// 群聊(二期):建群/成员/消息/未读
api.GET("/chat/rooms", h.ListChatRooms)
api.POST("/chat/rooms", h.CreateChatRoom)
api.POST("/chat/direct", h.OpenDirectChat)
api.GET("/chat/users", h.SearchChatUsers)
api.GET("/chat/rooms/:id", h.GetChatRoom)
api.PUT("/chat/rooms/:id", h.UpdateChatRoom)
api.PUT("/chat/rooms/:id/pin", h.PinChatRoom)
api.DELETE("/chat/rooms/:id", h.DissolveChatRoom)
api.POST("/chat/rooms/:id/join", h.JoinChatRoom)
api.POST("/chat/rooms/:id/leave", h.LeaveChatRoom)
api.GET("/chat/rooms/:id/members", h.ListChatMembers)
api.POST("/chat/rooms/:id/members", h.InviteChatMembers)
api.DELETE("/chat/rooms/:id/members/:uid", h.KickChatMember)
api.GET("/chat/rooms/:id/messages", h.ListChatMessages)
api.POST("/chat/rooms/:id/messages", middleware.RateLimitMiddleware(limiter, service.RateChat), h.SendChatMessage)
api.DELETE("/chat/rooms/:id/messages/:mid", h.RecallChatMessage)
api.PUT("/chat/rooms/:id/read", h.MarkChatRead)
api.GET("/chat/unread-summary", h.ChatUnreadSummary)
}
// 管理后台 API:RequireStaff 基础鉴权(板块管理员及以上,Actor 实时从 DB 现取),
@@ -166,6 +202,11 @@ func Setup(cfg *config.Config) (*gin.Engine, error) {
usersAPI.PUT("/users/:id/role", h.AdminUpdateUserRole)
usersAPI.PUT("/users/:id/ban", h.AdminSetUserBan)
usersAPI.GET("/users/:id/login-logs", h.AdminUserLoginLogs)
// 站长内容档案(handler 内再校验 owner)
usersAPI.GET("/users/:id", h.AdminGetUserAudit)
usersAPI.GET("/users/:id/posts", h.AdminUserAuditPosts)
usersAPI.GET("/users/:id/comments", h.AdminUserAuditComments)
usersAPI.GET("/users/:id/messages", h.AdminUserAuditMessages)
}
r.NoRoute(func(c *gin.Context) {