This commit introduces several architectural improvements and optimizations across the codebase: - **Performance & Reliability**: - Implemented Redis pipelining in `ConversationCache.CacheMessage` to reduce network round-trips. - Added a circuit breaker to the JPush client to prevent cascading failures. - Introduced batch deletion and batch member addition capabilities in repositories. - Added message idempotency support using `client_msg_id` and a Redis-based cache. - Optimized WebSocket handling with connection limits (total and per-user) and improved error logging. - **Code Refactoring**: - Refactored `Router` to use a `RouterDeps` struct, simplifying the constructor and improving maintainability. - Unified model ID generation logic using new `id_helper.go` (supporting UUID and Snowflake). - Standardized JSON serialization/deserialization in models using `json_helper.go`. - Refactored DTO conversion logic, specifically for `UserResponse` (using functional options) and `Report` responses. - Removed redundant/deprecated DTOs like `PostDetailResponse` and `TradeItemDetailResponse`. - **Cache Improvements**: - Enhanced `LayeredCache` with `SetRaw` to avoid double-encoding when promoting values from Redis to local cache. - Added `DeleteBatch` support to the cache interface. - **Other Changes**: - Cleaned up `config.go` by removing redundant default values and explicit environment variable overrides. - Improved WebSocket registration flow to handle connection limits gracefully.
678 lines
30 KiB
Go
678 lines
30 KiB
Go
package router
|
||
|
||
import (
|
||
"github.com/gin-gonic/gin"
|
||
|
||
"with_you/internal/handler"
|
||
"with_you/internal/middleware"
|
||
"with_you/internal/model"
|
||
"with_you/internal/repository"
|
||
"with_you/internal/service"
|
||
)
|
||
|
||
// RouterDeps 路由依赖
|
||
type RouterDeps struct {
|
||
UserRepo repository.UserRepository
|
||
UserHandler *handler.UserHandler
|
||
PostHandler *handler.PostHandler
|
||
CommentHandler *handler.CommentHandler
|
||
MessageHandler *handler.MessageHandler
|
||
NotificationHandler *handler.NotificationHandler
|
||
UploadHandler *handler.UploadHandler
|
||
PushHandler *handler.PushHandler
|
||
SystemMessageHandler *handler.SystemMessageHandler
|
||
GroupHandler *handler.GroupHandler
|
||
StickerHandler *handler.StickerHandler
|
||
VoteHandler *handler.VoteHandler
|
||
ChannelHandler *handler.ChannelHandler
|
||
ScheduleHandler *handler.ScheduleHandler
|
||
RoleHandler *handler.RoleHandler
|
||
AdminUserHandler *handler.AdminUserHandler
|
||
AdminPostHandler *handler.AdminPostHandler
|
||
AdminCommentHandler *handler.AdminCommentHandler
|
||
AdminGroupHandler *handler.AdminGroupHandler
|
||
AdminDashboardHandler *handler.AdminDashboardHandler
|
||
AdminLogHandler *handler.AdminLogHandler
|
||
QRCodeHandler *handler.QRCodeHandler
|
||
MaterialHandler *handler.MaterialHandler
|
||
CallHandler *handler.CallHandler
|
||
ReportHandler *handler.ReportHandler
|
||
AdminReportHandler *handler.AdminReportHandler
|
||
VerificationHandler *handler.VerificationHandler
|
||
AdminVerificationHandler *handler.AdminVerificationHandler
|
||
AdminProfileAuditHandler *handler.AdminProfileAuditHandler
|
||
SetupHandler *handler.SetupHandler
|
||
TradeHandler *handler.TradeHandler
|
||
WSHandler *handler.WSHandler
|
||
JWTService *service.JWTService
|
||
LogService *service.LogService
|
||
ActivityService service.UserActivityService
|
||
CasbinService service.CasbinService
|
||
}
|
||
|
||
// Router 路由配置
|
||
type Router struct {
|
||
engine *gin.Engine
|
||
userRepo repository.UserRepository
|
||
userHandler *handler.UserHandler
|
||
postHandler *handler.PostHandler
|
||
commentHandler *handler.CommentHandler
|
||
messageHandler *handler.MessageHandler
|
||
notificationHandler *handler.NotificationHandler
|
||
uploadHandler *handler.UploadHandler
|
||
pushHandler *handler.PushHandler
|
||
systemMessageHandler *handler.SystemMessageHandler
|
||
groupHandler *handler.GroupHandler
|
||
stickerHandler *handler.StickerHandler
|
||
voteHandler *handler.VoteHandler
|
||
channelHandler *handler.ChannelHandler
|
||
scheduleHandler *handler.ScheduleHandler
|
||
roleHandler *handler.RoleHandler
|
||
adminUserHandler *handler.AdminUserHandler
|
||
adminPostHandler *handler.AdminPostHandler
|
||
adminCommentHandler *handler.AdminCommentHandler
|
||
adminGroupHandler *handler.AdminGroupHandler
|
||
adminDashboardHandler *handler.AdminDashboardHandler
|
||
adminLogHandler *handler.AdminLogHandler
|
||
qrcodeHandler *handler.QRCodeHandler
|
||
materialHandler *handler.MaterialHandler
|
||
callHandler *handler.CallHandler
|
||
reportHandler *handler.ReportHandler
|
||
adminReportHandler *handler.AdminReportHandler
|
||
verificationHandler *handler.VerificationHandler
|
||
adminVerificationHandler *handler.AdminVerificationHandler
|
||
adminProfileAuditHandler *handler.AdminProfileAuditHandler
|
||
setupHandler *handler.SetupHandler
|
||
tradeHandler *handler.TradeHandler
|
||
wsHandler *handler.WSHandler
|
||
logService *service.LogService
|
||
jwtService *service.JWTService
|
||
casbinService service.CasbinService
|
||
}
|
||
|
||
// New 创建路由
|
||
func New(deps RouterDeps) *Router {
|
||
deps.UserHandler.SetJWTService(deps.JWTService)
|
||
deps.UserHandler.SetActivityService(deps.ActivityService)
|
||
|
||
r := &Router{
|
||
engine: gin.Default(),
|
||
userRepo: deps.UserRepo,
|
||
userHandler: deps.UserHandler,
|
||
postHandler: deps.PostHandler,
|
||
commentHandler: deps.CommentHandler,
|
||
messageHandler: deps.MessageHandler,
|
||
notificationHandler: deps.NotificationHandler,
|
||
uploadHandler: deps.UploadHandler,
|
||
pushHandler: deps.PushHandler,
|
||
systemMessageHandler: deps.SystemMessageHandler,
|
||
groupHandler: deps.GroupHandler,
|
||
stickerHandler: deps.StickerHandler,
|
||
voteHandler: deps.VoteHandler,
|
||
channelHandler: deps.ChannelHandler,
|
||
scheduleHandler: deps.ScheduleHandler,
|
||
roleHandler: deps.RoleHandler,
|
||
adminUserHandler: deps.AdminUserHandler,
|
||
adminPostHandler: deps.AdminPostHandler,
|
||
adminCommentHandler: deps.AdminCommentHandler,
|
||
adminGroupHandler: deps.AdminGroupHandler,
|
||
adminDashboardHandler: deps.AdminDashboardHandler,
|
||
adminLogHandler: deps.AdminLogHandler,
|
||
qrcodeHandler: deps.QRCodeHandler,
|
||
materialHandler: deps.MaterialHandler,
|
||
callHandler: deps.CallHandler,
|
||
reportHandler: deps.ReportHandler,
|
||
adminReportHandler: deps.AdminReportHandler,
|
||
verificationHandler: deps.VerificationHandler,
|
||
adminVerificationHandler: deps.AdminVerificationHandler,
|
||
adminProfileAuditHandler: deps.AdminProfileAuditHandler,
|
||
setupHandler: deps.SetupHandler,
|
||
tradeHandler: deps.TradeHandler,
|
||
logService: deps.LogService,
|
||
jwtService: deps.JWTService,
|
||
casbinService: deps.CasbinService,
|
||
wsHandler: deps.WSHandler,
|
||
}
|
||
|
||
r.setupRoutes()
|
||
return r
|
||
}
|
||
|
||
// setupRoutes 设置路由
|
||
func (r *Router) setupRoutes() {
|
||
// 中间件
|
||
r.engine.Use(middleware.SecurityHeaders())
|
||
r.engine.Use(middleware.CORS())
|
||
|
||
// 健康检查
|
||
r.engine.GET("/health", func(c *gin.Context) {
|
||
c.JSON(200, gin.H{"status": "ok"})
|
||
})
|
||
|
||
// API v1
|
||
v1 := r.engine.Group("/api/v1")
|
||
{
|
||
// 认证路由(公开,按接口类型设置不同速率限制)
|
||
auth := v1.Group("/auth")
|
||
auth.Use(middleware.GlobalAuthRateLimit())
|
||
auth.Use(middleware.IPBanMiddleware())
|
||
{
|
||
auth.POST("/register", middleware.RegisterRateLimit(), r.userHandler.Register)
|
||
auth.POST("/register/send-code", middleware.SendCodeRateLimit(), r.userHandler.SendRegisterCode)
|
||
auth.POST("/login", middleware.LoginRateLimit(), r.userHandler.Login)
|
||
auth.POST("/password/send-code", middleware.PasswordResetRateLimit(), r.userHandler.SendPasswordResetCode)
|
||
auth.POST("/password/reset", middleware.PasswordResetRateLimit(), r.userHandler.ResetPassword)
|
||
auth.POST("/logout", r.userHandler.Logout)
|
||
auth.POST("/refresh", r.userHandler.RefreshToken)
|
||
}
|
||
|
||
// 初始化超级管理员(公开接口,只能使用一次)
|
||
if r.setupHandler != nil {
|
||
v1.POST("/admin/setup-super-admin", r.setupHandler.SetupSuperAdmin)
|
||
}
|
||
|
||
// 需要认证的路由
|
||
authMiddleware := middleware.Auth(r.jwtService)
|
||
|
||
// === 访问日志中间件 ===
|
||
if r.adminLogHandler != nil && r.logService != nil {
|
||
accessLogConfig := &middleware.AccessLogConfig{
|
||
Enable: true,
|
||
SkipPaths: []string{"/health", "/api/v1/health"},
|
||
ServerIP: "0.0.0.0",
|
||
ServerPort: 8080,
|
||
}
|
||
r.engine.Use(middleware.AccessLogMiddleware(
|
||
r.logService.OperationLog,
|
||
accessLogConfig,
|
||
))
|
||
}
|
||
|
||
// Casbin 权限中间件(暂不全局启用,可根据需要在特定路由组上使用)
|
||
// casbinMiddleware := middleware.CasbinAuth(r.casbinService)
|
||
|
||
// 用户路由
|
||
users := v1.Group("/users")
|
||
{
|
||
// 当前用户
|
||
users.GET("/me", authMiddleware, r.userHandler.GetCurrentUser)
|
||
users.PUT("/me", authMiddleware, r.userHandler.UpdateUser)
|
||
users.POST("/me/email/send-code", authMiddleware, r.userHandler.SendEmailVerifyCode)
|
||
users.POST("/me/email/verify", authMiddleware, r.userHandler.VerifyEmail)
|
||
users.POST("/me/avatar", authMiddleware, r.uploadHandler.UploadAvatar)
|
||
users.POST("/me/cover", authMiddleware, r.uploadHandler.UploadCover)
|
||
users.POST("/change-password/send-code", authMiddleware, r.userHandler.SendChangePasswordCode)
|
||
users.POST("/change-password", authMiddleware, r.userHandler.ChangePassword)
|
||
|
||
// 隐私设置
|
||
users.GET("/me/privacy", authMiddleware, r.userHandler.GetPrivacySettings)
|
||
users.PUT("/me/privacy", authMiddleware, r.userHandler.UpdatePrivacySettings)
|
||
|
||
// 账号注销
|
||
users.POST("/me/deactivate", authMiddleware, r.userHandler.RequestAccountDeletion)
|
||
users.DELETE("/me/deactivate", authMiddleware, r.userHandler.CancelAccountDeletion)
|
||
users.GET("/me/deletion-status", authMiddleware, r.userHandler.GetDeletionStatus)
|
||
|
||
// 当前用户角色
|
||
if r.roleHandler != nil {
|
||
users.GET("/me/roles", authMiddleware, r.roleHandler.GetMyRoles)
|
||
}
|
||
|
||
// 搜索用户
|
||
users.GET("/search", middleware.OptionalAuth(r.jwtService), r.userHandler.Search)
|
||
|
||
// 其他用户
|
||
users.GET("/:id", middleware.OptionalAuth(r.jwtService), r.userHandler.GetUserByID)
|
||
users.POST("/:id/follow", authMiddleware, r.userHandler.FollowUser)
|
||
users.DELETE("/:id/follow", authMiddleware, r.userHandler.UnfollowUser)
|
||
users.POST("/:id/block", authMiddleware, r.userHandler.BlockUser)
|
||
users.DELETE("/:id/block", authMiddleware, r.userHandler.UnblockUser)
|
||
users.GET("/:id/block-status", authMiddleware, r.userHandler.GetBlockStatus)
|
||
users.GET("/blocks", authMiddleware, r.userHandler.GetBlockedUsers)
|
||
users.GET("/:id/following", authMiddleware, r.userHandler.GetFollowingList)
|
||
users.GET("/:id/followers", authMiddleware, r.userHandler.GetFollowersList)
|
||
|
||
// 用户帖子 - 使用 OptionalAuth 获取当前用户点赞/收藏状态
|
||
users.GET("/:id/posts", middleware.OptionalAuth(r.jwtService), r.postHandler.GetUserPosts)
|
||
users.GET("/:id/favorites", middleware.OptionalAuth(r.jwtService), r.postHandler.GetFavorites)
|
||
}
|
||
|
||
// 身份认证路由
|
||
if r.verificationHandler != nil {
|
||
verification := v1.Group("/verification")
|
||
verification.Use(authMiddleware)
|
||
{
|
||
verification.GET("/status", r.verificationHandler.GetVerificationStatus)
|
||
verification.POST("/submit", r.verificationHandler.SubmitVerification)
|
||
verification.GET("/records", r.verificationHandler.GetVerificationRecords)
|
||
}
|
||
}
|
||
|
||
// 二维码登录(公开)
|
||
if r.qrcodeHandler != nil {
|
||
qrcode := v1.Group("/auth/qrcode")
|
||
{
|
||
qrcode.GET("", r.qrcodeHandler.GetQRCode)
|
||
qrcode.GET("/events", r.qrcodeHandler.WSEvents)
|
||
}
|
||
|
||
// 二维码操作(需认证)
|
||
qrcodeAuth := v1.Group("/auth/qrcode")
|
||
qrcodeAuth.Use(authMiddleware)
|
||
{
|
||
qrcodeAuth.POST("/scan", r.qrcodeHandler.Scan)
|
||
qrcodeAuth.POST("/confirm", r.qrcodeHandler.Confirm)
|
||
qrcodeAuth.POST("/cancel", r.qrcodeHandler.Cancel)
|
||
}
|
||
}
|
||
|
||
// 认证路由(公开)
|
||
authPublic := v1.Group("/auth")
|
||
{
|
||
authPublic.GET("/check-username", r.userHandler.CheckUsername)
|
||
}
|
||
|
||
// 帖子路由
|
||
posts := v1.Group("/posts")
|
||
{
|
||
// 使用 OptionalAuth 中间件来获取用户登录状态
|
||
posts.GET("", middleware.OptionalAuth(r.jwtService), r.postHandler.List)
|
||
posts.GET("/search", middleware.OptionalAuth(r.jwtService), r.postHandler.Search)
|
||
posts.GET("/suggest", middleware.OptionalAuth(r.jwtService), r.postHandler.Suggest)
|
||
posts.GET("/:id", middleware.OptionalAuth(r.jwtService), r.postHandler.GetByID)
|
||
posts.POST("", authMiddleware, middleware.RequireVerified(r.userRepo), r.postHandler.Create)
|
||
posts.PUT("/:id", authMiddleware, middleware.RequireVerified(r.userRepo), r.postHandler.Update)
|
||
posts.DELETE("/:id", authMiddleware, middleware.RequireVerified(r.userRepo), r.postHandler.Delete)
|
||
|
||
// 浏览量记录(可选认证,允许游客浏览)
|
||
posts.POST("/:id/view", middleware.OptionalAuth(r.jwtService), r.postHandler.RecordView)
|
||
// 分享计数(可选认证;仅已发布帖子生效)
|
||
posts.POST("/:id/share", middleware.OptionalAuth(r.jwtService), r.postHandler.RecordShare)
|
||
|
||
// 内链相关路由
|
||
posts.GET("/:id/related", middleware.OptionalAuth(r.jwtService), r.postHandler.GetRelatedPosts)
|
||
posts.GET("/:id/refs", middleware.OptionalAuth(r.jwtService), r.postHandler.GetReferencedPosts)
|
||
posts.POST("/:id/ref-click", middleware.OptionalAuth(r.jwtService), r.postHandler.RecordRefClick)
|
||
|
||
// 点赞
|
||
posts.POST("/:id/like", authMiddleware, middleware.RequireVerified(r.userRepo), r.postHandler.Like)
|
||
posts.DELETE("/:id/like", authMiddleware, middleware.RequireVerified(r.userRepo), r.postHandler.Unlike)
|
||
|
||
// 收藏
|
||
posts.POST("/:id/favorite", authMiddleware, middleware.RequireVerified(r.userRepo), r.postHandler.Favorite)
|
||
posts.DELETE("/:id/favorite", authMiddleware, middleware.RequireVerified(r.userRepo), r.postHandler.Unfavorite)
|
||
|
||
// 投票相关路由
|
||
posts.POST("/vote", authMiddleware, middleware.RequireVerified(r.userRepo), r.voteHandler.CreateVotePost) // 创建投票帖子
|
||
posts.GET("/:id/vote", middleware.OptionalAuth(r.jwtService), r.voteHandler.GetVoteResult) // 获取投票结果
|
||
posts.POST("/:id/vote", authMiddleware, middleware.RequireVerified(r.userRepo), r.voteHandler.Vote) // 投票
|
||
posts.DELETE("/:id/vote", authMiddleware, middleware.RequireVerified(r.userRepo), r.voteHandler.Unvote) // 取消投票
|
||
}
|
||
|
||
// 频道路由(公开)
|
||
if r.channelHandler != nil {
|
||
channels := v1.Group("/channels")
|
||
{
|
||
channels.GET("", r.channelHandler.ListPublic)
|
||
}
|
||
}
|
||
|
||
// 二手交易路由
|
||
if r.tradeHandler != nil {
|
||
trade := v1.Group("/trade")
|
||
{
|
||
trade.GET("", middleware.OptionalAuth(r.jwtService), r.tradeHandler.List)
|
||
trade.GET("/:id", middleware.OptionalAuth(r.jwtService), r.tradeHandler.GetByID)
|
||
trade.POST("", authMiddleware, middleware.RequireVerified(r.userRepo), r.tradeHandler.Create)
|
||
trade.PUT("/:id", authMiddleware, middleware.RequireVerified(r.userRepo), r.tradeHandler.Update)
|
||
trade.DELETE("/:id", authMiddleware, middleware.RequireVerified(r.userRepo), r.tradeHandler.Delete)
|
||
trade.PUT("/:id/status", authMiddleware, middleware.RequireVerified(r.userRepo), r.tradeHandler.UpdateStatus)
|
||
trade.POST("/:id/view", middleware.OptionalAuth(r.jwtService), r.tradeHandler.RecordView)
|
||
trade.POST("/:id/favorite", authMiddleware, middleware.RequireVerified(r.userRepo), r.tradeHandler.Favorite)
|
||
trade.DELETE("/:id/favorite", authMiddleware, middleware.RequireVerified(r.userRepo), r.tradeHandler.Unfavorite)
|
||
}
|
||
}
|
||
|
||
// 课表路由
|
||
if r.scheduleHandler != nil {
|
||
schedule := v1.Group("/schedule")
|
||
schedule.Use(authMiddleware)
|
||
{
|
||
schedule.GET("/courses", r.scheduleHandler.ListCourses)
|
||
schedule.POST("/courses", r.scheduleHandler.CreateCourse)
|
||
schedule.POST("/sync", r.scheduleHandler.SyncSchedule) // 同步课表
|
||
schedule.PUT("/courses/:id", r.scheduleHandler.UpdateCourse)
|
||
schedule.DELETE("/courses/:id", r.scheduleHandler.DeleteCourse)
|
||
}
|
||
}
|
||
|
||
// 学习资料路由(公开)
|
||
if r.materialHandler != nil {
|
||
materials := v1.Group("/materials")
|
||
{
|
||
// 学科相关
|
||
materials.GET("/subjects", r.materialHandler.ListSubjects)
|
||
materials.GET("/subjects/:id", r.materialHandler.GetSubject)
|
||
// 资料相关
|
||
materials.GET("", r.materialHandler.ListMaterials)
|
||
materials.GET("/search", r.materialHandler.SearchMaterials)
|
||
materials.GET("/:id", r.materialHandler.GetMaterial)
|
||
materials.GET("/:id/download", r.materialHandler.DownloadMaterial)
|
||
}
|
||
}
|
||
|
||
// 投票选项路由
|
||
voteOptions := v1.Group("/vote-options")
|
||
voteOptions.Use(authMiddleware)
|
||
{
|
||
voteOptions.PUT("/:id", r.voteHandler.UpdateVoteOption) // 更新选项
|
||
}
|
||
|
||
// 评论路由
|
||
comments := v1.Group("/comments")
|
||
{
|
||
comments.GET("/post/:id", middleware.OptionalAuth(r.jwtService), r.commentHandler.GetByPostID)
|
||
comments.GET("/post/:id/cursor", middleware.OptionalAuth(r.jwtService), r.commentHandler.GetByPostIDByCursor) // 帖子评论游标分页
|
||
comments.GET("/:id", middleware.OptionalAuth(r.jwtService), r.commentHandler.GetByID)
|
||
comments.POST("", authMiddleware, middleware.RequireVerified(r.userRepo), r.commentHandler.Create)
|
||
comments.PUT("/:id", authMiddleware, middleware.RequireVerified(r.userRepo), r.commentHandler.Update)
|
||
comments.DELETE("/:id", authMiddleware, middleware.RequireVerified(r.userRepo), r.commentHandler.Delete)
|
||
comments.GET("/:id/replies", middleware.OptionalAuth(r.jwtService), r.commentHandler.GetReplies)
|
||
comments.GET("/:id/replies/flat", middleware.OptionalAuth(r.jwtService), r.commentHandler.GetRepliesByRootID) // 扁平化分页获取回复
|
||
comments.GET("/:id/replies/cursor", middleware.OptionalAuth(r.jwtService), r.commentHandler.GetRepliesByRootIDByCursor) // 回复游标分页
|
||
// 评论点赞
|
||
comments.POST("/:id/like", authMiddleware, middleware.RequireVerified(r.userRepo), r.commentHandler.Like)
|
||
comments.DELETE("/:id/like", authMiddleware, middleware.RequireVerified(r.userRepo), r.commentHandler.Unlike)
|
||
}
|
||
|
||
// 会话路由
|
||
conversations := v1.Group("/conversations")
|
||
conversations.Use(authMiddleware)
|
||
{
|
||
// ================================================================
|
||
// 新的 RESTful 风格路由(推荐使用)
|
||
// ================================================================
|
||
conversations.GET("", r.messageHandler.HandleGetConversationList) // 列表
|
||
conversations.GET("/cursor", r.messageHandler.GetConversationsByCursor) // 会话列表游标分页
|
||
conversations.POST("", middleware.RequireVerified(r.userRepo), r.messageHandler.HandleCreateConversation) // 创建
|
||
conversations.GET("/:id", r.messageHandler.HandleGetConversation) // 详情
|
||
conversations.GET("/:id/messages", r.messageHandler.HandleGetMessages) // 消息列表
|
||
conversations.GET("/:id/messages/cursor", r.messageHandler.GetMessagesByCursor) // 消息列表游标分页
|
||
conversations.POST("/:id/messages", middleware.RequireVerified(r.userRepo), r.messageHandler.HandleSendMessage) // 发送消息
|
||
conversations.POST("/:id/read", r.messageHandler.HandleMarkRead) // 标记已读
|
||
conversations.PUT("/:id/pinned", r.messageHandler.HandleSetConversationPinned) // 置顶设置
|
||
conversations.PUT("/:id/notification_muted", r.messageHandler.HandleSetConversationNotificationMuted) // 免打扰设置
|
||
conversations.GET("/unread/count", r.messageHandler.GetUnreadCount) // 未读数
|
||
conversations.POST("/:id/typing", r.messageHandler.HandleTyping) // 输入状态
|
||
conversations.DELETE("/:id/self", r.messageHandler.HandleDeleteConversationForSelf) // 删除会话(仅自己)
|
||
|
||
}
|
||
|
||
realtime := v1.Group("/realtime")
|
||
{
|
||
// WebSocket端点 - 在中间件之前处理认证(通过query参数)
|
||
realtime.GET("/ws", r.wsHandler.HandleWebSocket)
|
||
}
|
||
|
||
// 通话路由
|
||
if r.callHandler != nil {
|
||
calls := v1.Group("/calls")
|
||
calls.Use(authMiddleware)
|
||
{
|
||
calls.GET("/history", r.callHandler.GetCallHistory)
|
||
calls.GET("/ice-servers", r.callHandler.GetICEServers)
|
||
}
|
||
}
|
||
|
||
// 消息操作路由
|
||
messages := v1.Group("/messages")
|
||
messages.Use(authMiddleware)
|
||
{
|
||
// 撤回/删除消息(统一接口)
|
||
messages.POST("/delete_msg", middleware.RequireVerified(r.userRepo), r.messageHandler.HandleDeleteMsg)
|
||
}
|
||
|
||
// 举报路由
|
||
if r.reportHandler != nil {
|
||
reports := v1.Group("/reports")
|
||
reports.Use(authMiddleware)
|
||
{
|
||
reports.POST("", r.reportHandler.Create)
|
||
}
|
||
}
|
||
|
||
// 通知路由
|
||
notifications := v1.Group("/notifications")
|
||
{
|
||
notifications.GET("", authMiddleware, r.notificationHandler.GetNotifications)
|
||
notifications.GET("/cursor", authMiddleware, r.notificationHandler.GetNotificationsByCursor) // 通知游标分页
|
||
notifications.POST("/:id/read", authMiddleware, r.notificationHandler.MarkAsRead)
|
||
notifications.POST("/read-all", authMiddleware, r.notificationHandler.MarkAllAsRead)
|
||
notifications.GET("/unread-count", authMiddleware, r.notificationHandler.GetUnreadCount)
|
||
notifications.DELETE("/:id", authMiddleware, r.notificationHandler.DeleteNotification)
|
||
notifications.DELETE("", authMiddleware, r.notificationHandler.ClearAllNotifications)
|
||
}
|
||
|
||
// 上传路由
|
||
uploads := v1.Group("/uploads")
|
||
{
|
||
uploads.POST("/images", authMiddleware, r.uploadHandler.UploadImage)
|
||
}
|
||
|
||
// 推送相关路由
|
||
if r.pushHandler != nil {
|
||
pushGroup := v1.Group("/push")
|
||
pushGroup.Use(authMiddleware)
|
||
{
|
||
pushGroup.POST("/devices", r.pushHandler.RegisterDevice)
|
||
pushGroup.GET("/devices", r.pushHandler.GetMyDevices)
|
||
pushGroup.DELETE("/devices/:device_id", r.pushHandler.UnregisterDevice)
|
||
pushGroup.PUT("/devices/:device_id/token", r.pushHandler.UpdateDeviceToken)
|
||
pushGroup.GET("/records", r.pushHandler.GetPushRecords)
|
||
}
|
||
}
|
||
|
||
// 系统消息路由
|
||
if r.systemMessageHandler != nil {
|
||
msgGroup := v1.Group("/messages")
|
||
msgGroup.Use(authMiddleware)
|
||
{
|
||
msgGroup.GET("/system", r.systemMessageHandler.GetSystemMessages)
|
||
msgGroup.GET("/system/unread-count", r.systemMessageHandler.GetUnreadCount)
|
||
msgGroup.PUT("/system/:id/read", r.systemMessageHandler.MarkAsRead)
|
||
msgGroup.PUT("/system/read-all", r.systemMessageHandler.MarkAllAsRead)
|
||
}
|
||
}
|
||
|
||
// 群组路由
|
||
if r.groupHandler != nil {
|
||
groups := v1.Group("/groups")
|
||
groups.Use(authMiddleware)
|
||
{
|
||
// ================================================================
|
||
// 新的 RESTful 风格路由(推荐使用)
|
||
// ================================================================
|
||
// 群组基本操作
|
||
groups.GET("", r.groupHandler.HandleGetUserGroups) // 列表
|
||
groups.GET("/cursor", r.groupHandler.GetGroupsByCursor) // 群组游标分页
|
||
groups.POST("", r.groupHandler.HandleCreateGroup) // 创建
|
||
groups.GET("/:id", r.groupHandler.HandleGetGroupInfo) // 详情
|
||
groups.GET("/:id/me", r.groupHandler.HandleGetMyMemberInfo) // 当前用户成员信息
|
||
groups.DELETE("/:id", r.groupHandler.HandleDissolveGroup) // 解散群组
|
||
groups.POST("/:id/transfer", r.groupHandler.HandleTransferOwner) // 转让群主
|
||
|
||
// 成员管理
|
||
groups.POST("/:id/invitations", r.groupHandler.HandleInviteMembers) // 邀请成员
|
||
groups.POST("/:id/join-requests", r.groupHandler.HandleJoinGroup) // 申请加群
|
||
groups.POST("/:id/join-requests/respond", r.groupHandler.HandleRespondInvite) // 响应加群邀请/申请
|
||
groups.POST("/:id/leave", r.groupHandler.HandleSetGroupLeave) // 退群
|
||
groups.GET("/:id/members", r.groupHandler.HandleGetGroupMemberList) // 成员列表
|
||
groups.GET("/:id/members/cursor", r.groupHandler.GetMembersByCursor) // 成员游标分页
|
||
groups.POST("/:id/members/kick", r.groupHandler.HandleSetGroupKick) // 踢出成员
|
||
groups.PUT("/:id/members/:user_id/admin", r.groupHandler.HandleSetGroupAdmin) // 设置管理员
|
||
groups.PUT("/:id/members/me/nickname", r.groupHandler.HandleSetNickname) // 设置群昵称
|
||
groups.POST("/:id/members/ban", r.groupHandler.HandleSetGroupBan) // 禁言成员
|
||
|
||
// 群设置
|
||
groups.PUT("/:id/ban", r.groupHandler.HandleSetGroupWholeBan) // 全员禁言
|
||
groups.PUT("/:id/join-type", r.groupHandler.HandleSetJoinType) // 加群方式
|
||
groups.PUT("/:id/name", r.groupHandler.HandleSetGroupName) // 群名称
|
||
groups.PUT("/:id/avatar", r.groupHandler.HandleSetGroupAvatar) // 群头像
|
||
|
||
// 群公告
|
||
groups.POST("/:id/announcements", r.groupHandler.HandleCreateAnnouncement) // 创建公告
|
||
groups.GET("/:id/announcements", r.groupHandler.HandleGetAnnouncements) // 公告列表
|
||
groups.GET("/:id/announcements/cursor", r.groupHandler.GetAnnouncementsByCursor) // 公告游标分页
|
||
groups.DELETE("/:id/announcements/:announcement_id", r.groupHandler.HandleDeleteAnnouncement) // 删除公告
|
||
|
||
// 加群请求处理
|
||
groups.POST("/:id/join-requests/handle", r.groupHandler.HandleSetGroupAddRequest) // 处理加群请求
|
||
|
||
}
|
||
}
|
||
|
||
// 自定义表情路由
|
||
if r.stickerHandler != nil {
|
||
stickers := v1.Group("/stickers")
|
||
stickers.Use(authMiddleware)
|
||
{
|
||
stickers.GET("", r.stickerHandler.GetStickers)
|
||
stickers.POST("", r.stickerHandler.AddSticker)
|
||
stickers.DELETE("", r.stickerHandler.DeleteSticker)
|
||
stickers.POST("/reorder", r.stickerHandler.ReorderStickers)
|
||
stickers.GET("/check", r.stickerHandler.CheckStickerExists)
|
||
}
|
||
}
|
||
|
||
// 管理路由(需要管理员权限)
|
||
if r.roleHandler != nil {
|
||
admin := v1.Group("/admin")
|
||
admin.Use(authMiddleware)
|
||
admin.Use(middleware.RequireRole(r.casbinService, model.RoleAdmin, model.RoleSuperAdmin))
|
||
{
|
||
// 角色管理
|
||
admin.GET("/roles", r.roleHandler.GetAllRoles)
|
||
admin.GET("/roles/:name", r.roleHandler.GetRoleDetail)
|
||
admin.GET("/roles/:name/permissions", r.roleHandler.GetRolePermissions)
|
||
admin.PUT("/roles/:name/permissions", r.roleHandler.UpdateRolePermissions)
|
||
admin.GET("/permissions", r.roleHandler.GetAllPermissions)
|
||
admin.GET("/users/:id/roles", r.roleHandler.GetUserRoles)
|
||
admin.POST("/users/:id/roles", r.roleHandler.AssignRole)
|
||
admin.DELETE("/users/:id/roles/:role", r.roleHandler.RemoveRole)
|
||
|
||
// 用户管理
|
||
if r.adminUserHandler != nil {
|
||
admin.GET("/users", r.adminUserHandler.GetUserList)
|
||
admin.GET("/users/:id", r.adminUserHandler.GetUserDetail)
|
||
admin.PUT("/users/:id/status", r.adminUserHandler.UpdateUserStatus)
|
||
}
|
||
|
||
// 帖子管理
|
||
if r.adminPostHandler != nil {
|
||
admin.GET("/posts", r.adminPostHandler.GetPostList)
|
||
admin.GET("/posts/:id", r.adminPostHandler.GetPostDetail)
|
||
admin.DELETE("/posts/:id", r.adminPostHandler.DeletePost)
|
||
admin.PUT("/posts/:id/moderate", r.adminPostHandler.ModeratePost)
|
||
admin.POST("/posts/batch-delete", r.adminPostHandler.BatchDeletePosts)
|
||
admin.POST("/posts/batch-moderate", r.adminPostHandler.BatchModeratePosts)
|
||
admin.PUT("/posts/:id/pin", r.adminPostHandler.SetPostPin)
|
||
admin.PUT("/posts/:id/feature", r.adminPostHandler.SetPostFeature)
|
||
}
|
||
|
||
// 频道管理
|
||
if r.channelHandler != nil {
|
||
admin.GET("/channels", r.channelHandler.AdminList)
|
||
admin.POST("/channels", r.channelHandler.AdminCreate)
|
||
admin.PUT("/channels/:id", r.channelHandler.AdminUpdate)
|
||
admin.DELETE("/channels/:id", r.channelHandler.AdminDelete)
|
||
}
|
||
|
||
// 评论管理
|
||
if r.adminCommentHandler != nil {
|
||
admin.GET("/comments", r.adminCommentHandler.GetCommentList)
|
||
admin.GET("/comments/:id", r.adminCommentHandler.GetCommentDetail)
|
||
admin.DELETE("/comments/:id", r.adminCommentHandler.DeleteComment)
|
||
admin.PUT("/comments/:id/moderate", r.adminCommentHandler.ModerateComment)
|
||
admin.POST("/comments/batch-delete", r.adminCommentHandler.BatchDeleteComments)
|
||
admin.POST("/comments/batch-moderate", r.adminCommentHandler.BatchModerateComments)
|
||
admin.GET("/comments/post/:postId", r.adminCommentHandler.GetPostComments)
|
||
}
|
||
|
||
// 群组管理
|
||
if r.adminGroupHandler != nil {
|
||
admin.GET("/groups", r.adminGroupHandler.GetGroupList)
|
||
admin.GET("/groups/:id", r.adminGroupHandler.GetGroupDetail)
|
||
admin.GET("/groups/:id/members", r.adminGroupHandler.GetGroupMembers)
|
||
admin.DELETE("/groups/:id", r.adminGroupHandler.DeleteGroup)
|
||
admin.PUT("/groups/:id/status", r.adminGroupHandler.UpdateGroupStatus)
|
||
admin.DELETE("/groups/:id/members/:userId", r.adminGroupHandler.RemoveMember)
|
||
admin.PUT("/groups/:id/transfer", r.adminGroupHandler.TransferOwner)
|
||
}
|
||
|
||
// 仪表盘
|
||
if r.adminDashboardHandler != nil {
|
||
admin.GET("/dashboard/stats", r.adminDashboardHandler.GetStats)
|
||
admin.GET("/dashboard/user-activity", r.adminDashboardHandler.GetUserActivityTrend)
|
||
admin.GET("/dashboard/content-stats", r.adminDashboardHandler.GetContentStats)
|
||
admin.GET("/dashboard/pending-content", r.adminDashboardHandler.GetPendingContent)
|
||
admin.GET("/dashboard/online-users", r.adminDashboardHandler.GetOnlineUsers)
|
||
}
|
||
|
||
// 日志管理
|
||
if r.adminLogHandler != nil {
|
||
logs := admin.Group("/logs")
|
||
{
|
||
logs.GET("/operations", r.adminLogHandler.GetOperationLogs)
|
||
logs.GET("/logins", r.adminLogHandler.GetLoginLogs)
|
||
logs.GET("/data-changes", r.adminLogHandler.GetDataChangeLogs)
|
||
logs.GET("/statistics", r.adminLogHandler.GetLogStatistics)
|
||
logs.GET("/export", r.adminLogHandler.ExportLogs)
|
||
}
|
||
}
|
||
|
||
// 学习资料管理
|
||
if r.materialHandler != nil {
|
||
// 学科管理
|
||
admin.GET("/materials/subjects", r.materialHandler.AdminListSubjects)
|
||
admin.POST("/materials/subjects", r.materialHandler.AdminCreateSubject)
|
||
admin.PUT("/materials/subjects/:id", r.materialHandler.AdminUpdateSubject)
|
||
admin.DELETE("/materials/subjects/:id", r.materialHandler.AdminDeleteSubject)
|
||
// 资料管理
|
||
admin.GET("/materials", r.materialHandler.AdminListMaterials)
|
||
admin.GET("/materials/:id", r.materialHandler.AdminGetMaterial)
|
||
admin.POST("/materials", r.materialHandler.AdminCreateMaterial)
|
||
admin.PUT("/materials/:id", r.materialHandler.AdminUpdateMaterial)
|
||
admin.DELETE("/materials/:id", r.materialHandler.AdminDeleteMaterial)
|
||
}
|
||
|
||
// 举报管理
|
||
if r.adminReportHandler != nil {
|
||
admin.GET("/reports", r.adminReportHandler.List)
|
||
admin.GET("/reports/:id", r.adminReportHandler.Detail)
|
||
admin.PUT("/reports/:id/handle", r.adminReportHandler.Handle)
|
||
admin.POST("/reports/batch-handle", r.adminReportHandler.BatchHandle)
|
||
}
|
||
|
||
// 身份认证管理
|
||
if r.adminVerificationHandler != nil {
|
||
admin.GET("/verifications", r.adminVerificationHandler.ListVerifications)
|
||
admin.GET("/verifications/:id", r.adminVerificationHandler.GetVerificationDetail)
|
||
admin.PUT("/verifications/:id/review", r.adminVerificationHandler.ReviewVerification)
|
||
}
|
||
|
||
// 用户资料审核管理
|
||
if r.adminProfileAuditHandler != nil {
|
||
admin.GET("/profile-audits", r.adminProfileAuditHandler.GetPendingList)
|
||
admin.PUT("/profile-audits/:id/moderate", r.adminProfileAuditHandler.ModerateAudit)
|
||
admin.POST("/profile-audits/batch-moderate", r.adminProfileAuditHandler.BatchModerate)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// Engine 获取引擎
|
||
func (r *Router) Engine() *gin.Engine {
|
||
return r.engine
|
||
}
|