From a77669ee99355264247844d01b08806cc89e3773 Mon Sep 17 00:00:00 2001 From: bujinyuan Date: Mon, 2 Mar 2026 17:13:06 +0800 Subject: [PATCH] =?UTF-8?q?feat(admin):=20=E7=AE=A1=E7=90=86=E7=AB=AF?= =?UTF-8?q?=E5=9C=A8=E7=BA=BF=E7=9B=91=E6=8E=A7=20+=20=E5=A5=BD=E5=8F=8B?= =?UTF-8?q?=E5=85=B3=E7=B3=BB=E7=AE=A1=E7=90=86=E5=90=8E=E7=AB=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - admin/service/online_service.go: 在线用户列表/计数 - admin/controller/online_controller.go: GET /admin/online/users|count - admin/service/contact_manage_service.go: 好友关系分页查询/管理员删除 - admin/controller/contact_manage_controller.go: GET|DELETE /admin/contacts - 更新 admin router/provider/wire 集成新控制器 Made-with: Cursor --- .../controller/contact_manage_controller.go | 50 ++++++++++++++ .../app/admin/controller/online_controller.go | 37 ++++++++++ backend/go-service/app/admin/provider.go | 4 ++ backend/go-service/app/admin/router.go | 24 +++++-- .../admin/service/contact_manage_service.go | 67 +++++++++++++++++++ .../app/admin/service/online_service.go | 26 +++++++ backend/go-service/app/provider/provider.go | 10 ++- backend/go-service/app/provider/wire_gen.go | 6 +- backend/go-service/router/router.go | 2 +- 9 files changed, 215 insertions(+), 11 deletions(-) create mode 100644 backend/go-service/app/admin/controller/contact_manage_controller.go create mode 100644 backend/go-service/app/admin/controller/online_controller.go create mode 100644 backend/go-service/app/admin/service/contact_manage_service.go create mode 100644 backend/go-service/app/admin/service/online_service.go diff --git a/backend/go-service/app/admin/controller/contact_manage_controller.go b/backend/go-service/app/admin/controller/contact_manage_controller.go new file mode 100644 index 0000000..29e1252 --- /dev/null +++ b/backend/go-service/app/admin/controller/contact_manage_controller.go @@ -0,0 +1,50 @@ +package controller + +import ( + "strconv" + + "github.com/echochat/backend/app/admin/service" + "github.com/echochat/backend/pkg/utils" + "github.com/gin-gonic/gin" +) + +type ContactManageController struct { + contactManageService *service.ContactManageService +} + +func NewContactManageController(contactManageService *service.ContactManageService) *ContactManageController { + return &ContactManageController{contactManageService: contactManageService} +} + +// GetAllContacts GET /api/v1/admin/contacts +func (ctl *ContactManageController) GetAllContacts(c *gin.Context) { + ctx := c.Request.Context() + page, _ := strconv.Atoi(c.DefaultQuery("page", "1")) + pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20")) + + contacts, total, err := ctl.contactManageService.GetAllFriendships(ctx, page, pageSize) + if err != nil { + utils.ResponseError(c, "获取好友关系列表失败") + return + } + utils.ResponseOK(c, gin.H{ + "list": contacts, + "total": total, + }) +} + +// DeleteContact DELETE /api/v1/admin/contacts/:id +func (ctl *ContactManageController) DeleteContact(c *gin.Context) { + ctx := c.Request.Context() + id, err := strconv.ParseInt(c.Param("id"), 10, 64) + if err != nil { + utils.ResponseBadRequest(c, "ID 格式错误") + return + } + + if err := ctl.contactManageService.DeleteFriendship(ctx, id); err != nil { + utils.ResponseError(c, "删除好友关系失败") + return + } + utils.ResponseOK(c, nil) +} diff --git a/backend/go-service/app/admin/controller/online_controller.go b/backend/go-service/app/admin/controller/online_controller.go new file mode 100644 index 0000000..9a024e1 --- /dev/null +++ b/backend/go-service/app/admin/controller/online_controller.go @@ -0,0 +1,37 @@ +package controller + +import ( + "github.com/echochat/backend/app/admin/service" + "github.com/echochat/backend/pkg/utils" + "github.com/gin-gonic/gin" +) + +type OnlineController struct { + onlineManageService *service.OnlineManageService +} + +func NewOnlineController(onlineManageService *service.OnlineManageService) *OnlineController { + return &OnlineController{onlineManageService: onlineManageService} +} + +// GetOnlineUsers GET /api/v1/admin/online/users +func (ctl *OnlineController) GetOnlineUsers(c *gin.Context) { + ctx := c.Request.Context() + userIDs, err := ctl.onlineManageService.GetOnlineUsers(ctx) + if err != nil { + utils.ResponseError(c, "获取在线用户列表失败") + return + } + utils.ResponseOK(c, userIDs) +} + +// GetOnlineCount GET /api/v1/admin/online/count +func (ctl *OnlineController) GetOnlineCount(c *gin.Context) { + ctx := c.Request.Context() + count, err := ctl.onlineManageService.GetOnlineCount(ctx) + if err != nil { + utils.ResponseError(c, "获取在线用户数失败") + return + } + utils.ResponseOK(c, gin.H{"count": count}) +} diff --git a/backend/go-service/app/admin/provider.go b/backend/go-service/app/admin/provider.go index fbca434..acde569 100644 --- a/backend/go-service/app/admin/provider.go +++ b/backend/go-service/app/admin/provider.go @@ -14,4 +14,8 @@ var AdminSet = wire.NewSet( dao.NewUserManageDAO, service.NewUserManageService, controller.NewUserManageController, + service.NewOnlineManageService, + controller.NewOnlineController, + service.NewContactManageService, + controller.NewContactManageController, ) diff --git a/backend/go-service/app/admin/router.go b/backend/go-service/app/admin/router.go index 5d1f2d9..da5b10d 100644 --- a/backend/go-service/app/admin/router.go +++ b/backend/go-service/app/admin/router.go @@ -12,7 +12,9 @@ import ( // 所有管理端 API 需要 JWT + admin 角色双重中间件 func RegisterRoutes( r *gin.Engine, - ctrl *controller.UserManageController, + userCtrl *controller.UserManageController, + onlineCtrl *controller.OnlineController, + contactManageCtrl *controller.ContactManageController, jwtAuth gin.HandlerFunc, ) { // 管理端路由组:JWT 认证 + admin/super_admin 角色检查 @@ -20,13 +22,21 @@ func RegisterRoutes( adminGroup.Use(jwtAuth, middleware.RequireRole(constants.RoleAdmin, constants.RoleSuperAdmin)) { // 用户管理 - adminGroup.GET("/users", ctrl.GetUserList) - adminGroup.GET("/users/:id", ctrl.GetUserDetail) - adminGroup.PUT("/users/:id/status", ctrl.UpdateUserStatus) - adminGroup.PUT("/users/:id/roles", ctrl.SetRoles) - adminGroup.POST("/users", ctrl.CreateUser) + adminGroup.GET("/users", userCtrl.GetUserList) + adminGroup.GET("/users/:id", userCtrl.GetUserDetail) + adminGroup.PUT("/users/:id/status", userCtrl.UpdateUserStatus) + adminGroup.PUT("/users/:id/roles", userCtrl.SetRoles) + adminGroup.POST("/users", userCtrl.CreateUser) // 角色管理 - adminGroup.GET("/roles", ctrl.GetAllRoles) + adminGroup.GET("/roles", userCtrl.GetAllRoles) + + // 在线监控 + adminGroup.GET("/online/users", onlineCtrl.GetOnlineUsers) + adminGroup.GET("/online/count", onlineCtrl.GetOnlineCount) + + // 好友关系管理 + adminGroup.GET("/contacts", contactManageCtrl.GetAllContacts) + adminGroup.DELETE("/contacts/:id", contactManageCtrl.DeleteContact) } } diff --git a/backend/go-service/app/admin/service/contact_manage_service.go b/backend/go-service/app/admin/service/contact_manage_service.go new file mode 100644 index 0000000..2f2e184 --- /dev/null +++ b/backend/go-service/app/admin/service/contact_manage_service.go @@ -0,0 +1,67 @@ +package service + +import ( + "context" + + "github.com/echochat/backend/app/contact/model" + "github.com/echochat/backend/pkg/logs" + "go.uber.org/zap" + "gorm.io/gorm" +) + +type ContactManageService struct { + db *gorm.DB +} + +func NewContactManageService(db *gorm.DB) *ContactManageService { + return &ContactManageService{db: db} +} + +type AdminFriendship struct { + ID int64 `json:"id"` + UserID int64 `json:"user_id"` + UserUsername string `json:"user_username"` + FriendID int64 `json:"friend_id"` + FriendUsername string `json:"friend_username"` + Status int `json:"status"` + CreatedAt string `json:"created_at"` +} + +// GetAllFriendships 获取所有好友关系(分页) +func (s *ContactManageService) GetAllFriendships(ctx context.Context, page, pageSize int) ([]AdminFriendship, int64, error) { + funcName := "service.contact_manage_service.GetAllFriendships" + logs.Debug(ctx, funcName, "管理端查询好友关系") + + var total int64 + s.db.WithContext(ctx).Model(&model.Friendship{}).Count(&total) + + var results []AdminFriendship + offset := (page - 1) * pageSize + err := s.db.WithContext(ctx). + Table("contact_friendships f"). + Select("f.id, f.user_id, u1.username as user_username, f.friend_id, u2.username as friend_username, f.status, TO_CHAR(f.created_at, 'YYYY-MM-DD HH24:MI:SS') as created_at"). + Joins("JOIN auth_users u1 ON u1.id = f.user_id"). + Joins("JOIN auth_users u2 ON u2.id = f.friend_id"). + Order("f.created_at DESC"). + Offset(offset).Limit(pageSize). + Scan(&results).Error + + return results, total, err +} + +// DeleteFriendship 管理员删除好友关系(双向删除) +func (s *ContactManageService) DeleteFriendship(ctx context.Context, friendshipID int64) error { + funcName := "service.contact_manage_service.DeleteFriendship" + logs.Info(ctx, funcName, "管理员删除好友关系", zap.Int64("friendship_id", friendshipID)) + + var f model.Friendship + if err := s.db.WithContext(ctx).First(&f, friendshipID).Error; err != nil { + return err + } + + return s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error { + tx.Where("user_id = ? AND friend_id = ?", f.UserID, f.FriendID).Delete(&model.Friendship{}) + tx.Where("user_id = ? AND friend_id = ?", f.FriendID, f.UserID).Delete(&model.Friendship{}) + return nil + }) +} diff --git a/backend/go-service/app/admin/service/online_service.go b/backend/go-service/app/admin/service/online_service.go new file mode 100644 index 0000000..3a03df5 --- /dev/null +++ b/backend/go-service/app/admin/service/online_service.go @@ -0,0 +1,26 @@ +package service + +import ( + "context" + + wsApp "github.com/echochat/backend/app/ws" + "github.com/echochat/backend/pkg/logs" +) + +type OnlineManageService struct { + onlineService *wsApp.OnlineService +} + +func NewOnlineManageService(onlineService *wsApp.OnlineService) *OnlineManageService { + return &OnlineManageService{onlineService: onlineService} +} + +func (s *OnlineManageService) GetOnlineUsers(ctx context.Context) ([]int64, error) { + funcName := "service.online_manage_service.GetOnlineUsers" + logs.Debug(ctx, funcName, "获取在线用户列表") + return s.onlineService.GetOnlineUserIDs(ctx) +} + +func (s *OnlineManageService) GetOnlineCount(ctx context.Context) (int64, error) { + return s.onlineService.GetOnlineCount(ctx) +} diff --git a/backend/go-service/app/provider/provider.go b/backend/go-service/app/provider/provider.go index 4c09344..265c6db 100644 --- a/backend/go-service/app/provider/provider.go +++ b/backend/go-service/app/provider/provider.go @@ -24,7 +24,9 @@ type App struct { AuthService *service.AuthService // Auth 认证服务 AuthController *authController.AuthController // 前台认证控制器 AdminAuthController *authController.AdminAuthController // 后台认证控制器 - UserManageController *adminController.UserManageController // 管理端用户管理控制器 + UserManageController *adminController.UserManageController // 管理端用户管理控制器 + OnlineController *adminController.OnlineController // 管理端在线监控控制器 + ContactManageController *adminController.ContactManageController // 管理端好友关系管理控制器 WSHandler *wsApp.Handler // WebSocket 连接处理器 Hub *ws.Hub // WebSocket Hub 连接管理 PubSub *ws.PubSub // Redis Pub/Sub 消息路由 @@ -41,6 +43,8 @@ func NewApp( authCtrl *authController.AuthController, adminAuthCtrl *authController.AdminAuthController, userManageCtrl *adminController.UserManageController, + onlineCtrl *adminController.OnlineController, + contactManageCtrl *adminController.ContactManageController, wsHandler *wsApp.Handler, hub *ws.Hub, pubsub *ws.PubSub, @@ -54,7 +58,9 @@ func NewApp( AuthService: authService, AuthController: authCtrl, AdminAuthController: adminAuthCtrl, - UserManageController: userManageCtrl, + UserManageController: userManageCtrl, + OnlineController: onlineCtrl, + ContactManageController: contactManageCtrl, WSHandler: wsHandler, Hub: hub, PubSub: pubsub, diff --git a/backend/go-service/app/provider/wire_gen.go b/backend/go-service/app/provider/wire_gen.go index b4921b9..5909908 100644 --- a/backend/go-service/app/provider/wire_gen.go +++ b/backend/go-service/app/provider/wire_gen.go @@ -48,11 +48,15 @@ func InitializeApp(cfg *config.Config) (*App, error) { hub := ws.ProvideHub() pubSub := ws.ProvidePubSub(client, hub) onlineService := ws.ProvideOnlineService(client, hub, pubSub) + onlineManageService := service2.NewOnlineManageService(onlineService) + onlineController := controller2.NewOnlineController(onlineManageService) + contactManageService := service2.NewContactManageService(gormDB) + contactManageController := controller2.NewContactManageController(contactManageService) handler := ws.ProvideWSHandler(hub, pubSub, jwtConfig, onlineService) friendshipDAO := dao3.NewFriendshipDAO(gormDB) friendGroupDAO := dao3.NewFriendGroupDAO(gormDB) contactService := service3.NewContactService(friendshipDAO, friendGroupDAO, pubSub) contactController := controller3.NewContactController(contactService) - app := NewApp(cfg, gormDB, client, authService, authController, adminAuthController, userManageController, handler, hub, pubSub, onlineService, contactController) + app := NewApp(cfg, gormDB, client, authService, authController, adminAuthController, userManageController, onlineController, contactManageController, handler, hub, pubSub, onlineService, contactController) return app, nil } diff --git a/backend/go-service/router/router.go b/backend/go-service/router/router.go index 6be4369..f66b0b6 100644 --- a/backend/go-service/router/router.go +++ b/backend/go-service/router/router.go @@ -33,7 +33,7 @@ func Setup(engine *gin.Engine, app *provider.App) { // --- 各模块路由注册 --- auth.RegisterRoutes(engine, app.AuthController, app.AdminAuthController, jwtAuth) - admin.RegisterRoutes(engine, app.UserManageController, jwtAuth) + admin.RegisterRoutes(engine, app.UserManageController, app.OnlineController, app.ContactManageController, jwtAuth) wsApp.RegisterRoutes(engine, app.WSHandler) contact.RegisterRoutes(engine, app.ContactController, jwtAuth)