feat(admin): 管理端在线监控 + 好友关系管理后端
- 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
This commit is contained in:
@@ -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)
|
||||||
|
}
|
||||||
37
backend/go-service/app/admin/controller/online_controller.go
Normal file
37
backend/go-service/app/admin/controller/online_controller.go
Normal file
@@ -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})
|
||||||
|
}
|
||||||
@@ -14,4 +14,8 @@ var AdminSet = wire.NewSet(
|
|||||||
dao.NewUserManageDAO,
|
dao.NewUserManageDAO,
|
||||||
service.NewUserManageService,
|
service.NewUserManageService,
|
||||||
controller.NewUserManageController,
|
controller.NewUserManageController,
|
||||||
|
service.NewOnlineManageService,
|
||||||
|
controller.NewOnlineController,
|
||||||
|
service.NewContactManageService,
|
||||||
|
controller.NewContactManageController,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -12,7 +12,9 @@ import (
|
|||||||
// 所有管理端 API 需要 JWT + admin 角色双重中间件
|
// 所有管理端 API 需要 JWT + admin 角色双重中间件
|
||||||
func RegisterRoutes(
|
func RegisterRoutes(
|
||||||
r *gin.Engine,
|
r *gin.Engine,
|
||||||
ctrl *controller.UserManageController,
|
userCtrl *controller.UserManageController,
|
||||||
|
onlineCtrl *controller.OnlineController,
|
||||||
|
contactManageCtrl *controller.ContactManageController,
|
||||||
jwtAuth gin.HandlerFunc,
|
jwtAuth gin.HandlerFunc,
|
||||||
) {
|
) {
|
||||||
// 管理端路由组:JWT 认证 + admin/super_admin 角色检查
|
// 管理端路由组:JWT 认证 + admin/super_admin 角色检查
|
||||||
@@ -20,13 +22,21 @@ func RegisterRoutes(
|
|||||||
adminGroup.Use(jwtAuth, middleware.RequireRole(constants.RoleAdmin, constants.RoleSuperAdmin))
|
adminGroup.Use(jwtAuth, middleware.RequireRole(constants.RoleAdmin, constants.RoleSuperAdmin))
|
||||||
{
|
{
|
||||||
// 用户管理
|
// 用户管理
|
||||||
adminGroup.GET("/users", ctrl.GetUserList)
|
adminGroup.GET("/users", userCtrl.GetUserList)
|
||||||
adminGroup.GET("/users/:id", ctrl.GetUserDetail)
|
adminGroup.GET("/users/:id", userCtrl.GetUserDetail)
|
||||||
adminGroup.PUT("/users/:id/status", ctrl.UpdateUserStatus)
|
adminGroup.PUT("/users/:id/status", userCtrl.UpdateUserStatus)
|
||||||
adminGroup.PUT("/users/:id/roles", ctrl.SetRoles)
|
adminGroup.PUT("/users/:id/roles", userCtrl.SetRoles)
|
||||||
adminGroup.POST("/users", ctrl.CreateUser)
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
})
|
||||||
|
}
|
||||||
26
backend/go-service/app/admin/service/online_service.go
Normal file
26
backend/go-service/app/admin/service/online_service.go
Normal file
@@ -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)
|
||||||
|
}
|
||||||
@@ -24,7 +24,9 @@ type App struct {
|
|||||||
AuthService *service.AuthService // Auth 认证服务
|
AuthService *service.AuthService // Auth 认证服务
|
||||||
AuthController *authController.AuthController // 前台认证控制器
|
AuthController *authController.AuthController // 前台认证控制器
|
||||||
AdminAuthController *authController.AdminAuthController // 后台认证控制器
|
AdminAuthController *authController.AdminAuthController // 后台认证控制器
|
||||||
UserManageController *adminController.UserManageController // 管理端用户管理控制器
|
UserManageController *adminController.UserManageController // 管理端用户管理控制器
|
||||||
|
OnlineController *adminController.OnlineController // 管理端在线监控控制器
|
||||||
|
ContactManageController *adminController.ContactManageController // 管理端好友关系管理控制器
|
||||||
WSHandler *wsApp.Handler // WebSocket 连接处理器
|
WSHandler *wsApp.Handler // WebSocket 连接处理器
|
||||||
Hub *ws.Hub // WebSocket Hub 连接管理
|
Hub *ws.Hub // WebSocket Hub 连接管理
|
||||||
PubSub *ws.PubSub // Redis Pub/Sub 消息路由
|
PubSub *ws.PubSub // Redis Pub/Sub 消息路由
|
||||||
@@ -41,6 +43,8 @@ func NewApp(
|
|||||||
authCtrl *authController.AuthController,
|
authCtrl *authController.AuthController,
|
||||||
adminAuthCtrl *authController.AdminAuthController,
|
adminAuthCtrl *authController.AdminAuthController,
|
||||||
userManageCtrl *adminController.UserManageController,
|
userManageCtrl *adminController.UserManageController,
|
||||||
|
onlineCtrl *adminController.OnlineController,
|
||||||
|
contactManageCtrl *adminController.ContactManageController,
|
||||||
wsHandler *wsApp.Handler,
|
wsHandler *wsApp.Handler,
|
||||||
hub *ws.Hub,
|
hub *ws.Hub,
|
||||||
pubsub *ws.PubSub,
|
pubsub *ws.PubSub,
|
||||||
@@ -54,7 +58,9 @@ func NewApp(
|
|||||||
AuthService: authService,
|
AuthService: authService,
|
||||||
AuthController: authCtrl,
|
AuthController: authCtrl,
|
||||||
AdminAuthController: adminAuthCtrl,
|
AdminAuthController: adminAuthCtrl,
|
||||||
UserManageController: userManageCtrl,
|
UserManageController: userManageCtrl,
|
||||||
|
OnlineController: onlineCtrl,
|
||||||
|
ContactManageController: contactManageCtrl,
|
||||||
WSHandler: wsHandler,
|
WSHandler: wsHandler,
|
||||||
Hub: hub,
|
Hub: hub,
|
||||||
PubSub: pubsub,
|
PubSub: pubsub,
|
||||||
|
|||||||
@@ -48,11 +48,15 @@ func InitializeApp(cfg *config.Config) (*App, error) {
|
|||||||
hub := ws.ProvideHub()
|
hub := ws.ProvideHub()
|
||||||
pubSub := ws.ProvidePubSub(client, hub)
|
pubSub := ws.ProvidePubSub(client, hub)
|
||||||
onlineService := ws.ProvideOnlineService(client, hub, pubSub)
|
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)
|
handler := ws.ProvideWSHandler(hub, pubSub, jwtConfig, onlineService)
|
||||||
friendshipDAO := dao3.NewFriendshipDAO(gormDB)
|
friendshipDAO := dao3.NewFriendshipDAO(gormDB)
|
||||||
friendGroupDAO := dao3.NewFriendGroupDAO(gormDB)
|
friendGroupDAO := dao3.NewFriendGroupDAO(gormDB)
|
||||||
contactService := service3.NewContactService(friendshipDAO, friendGroupDAO, pubSub)
|
contactService := service3.NewContactService(friendshipDAO, friendGroupDAO, pubSub)
|
||||||
contactController := controller3.NewContactController(contactService)
|
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
|
return app, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ func Setup(engine *gin.Engine, app *provider.App) {
|
|||||||
|
|
||||||
// --- 各模块路由注册 ---
|
// --- 各模块路由注册 ---
|
||||||
auth.RegisterRoutes(engine, app.AuthController, app.AdminAuthController, jwtAuth)
|
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)
|
wsApp.RegisterRoutes(engine, app.WSHandler)
|
||||||
contact.RegisterRoutes(engine, app.ContactController, jwtAuth)
|
contact.RegisterRoutes(engine, app.ContactController, jwtAuth)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user