Files
nl-im-service/internal/api/room_handler.go

423 lines
9.4 KiB
Go
Raw Normal View History

2025-12-03 11:00:47 +08:00
/**
* package api
* 作用:房间管理相关API处理器
*/
package api
import (
2025-12-05 09:25:24 +08:00
"strconv"
2025-12-04 22:29:32 +08:00
"xk-websocket-v2/internal/model"
2025-12-03 11:00:47 +08:00
"xk-websocket-v2/internal/service"
"xk-websocket-v2/internal/utils"
"github.com/gin-gonic/gin"
2025-12-04 22:29:32 +08:00
"gorm.io/gorm"
2025-12-03 11:00:47 +08:00
)
/**
* CreateRoomHandler
* 功能:创建房间
* 路径:POST /api/rooms
*/
func CreateRoomHandler(c *gin.Context) {
userID, _ := c.Get("user_id")
var req struct {
2025-12-04 22:29:32 +08:00
RoomType string `json:"room_type" binding:"required,oneof=p2p group"`
Members []string `json:"members" binding:"required"`
RoomName string `json:"room_name"`
RoomAvatar string `json:"room_avatar"`
2025-12-03 11:00:47 +08:00
}
if err := c.ShouldBindJSON(&req); err != nil {
utils.BadRequest(c, "参数错误: "+err.Error())
return
}
room, err := service.RoomSvc.CreateRoom(req.RoomType, req.Members, userID.(string))
if err != nil {
utils.BadRequest(c, err.Error())
return
}
// 如果提供了房间名称和头像,更新
if req.RoomName != "" || req.RoomAvatar != "" {
updates := make(map[string]interface{})
if req.RoomName != "" {
updates["room_name"] = req.RoomName
}
if req.RoomAvatar != "" {
updates["room_avatar"] = req.RoomAvatar
}
service.RoomSvc.DB.Model(room).Updates(updates)
}
utils.SuccessWithData(c, room, "创建成功")
}
/**
* GetRoomHandler
* 功能:获取房间信息
* 路径:GET /api/rooms/:id
*/
func GetRoomHandler(c *gin.Context) {
roomID := c.Param("id")
room, err := service.RoomSvc.GetRoom(roomID)
if err != nil {
utils.NotFound(c, "房间不存在")
return
}
utils.SuccessWithData(c, room, "获取成功")
}
2025-12-04 22:29:32 +08:00
/**
* CreateChatGroupHandler
* 功能:创建群聊
* 路径:POST /api/groups
*/
func CreateChatGroupHandler(c *gin.Context) {
userID, _ := c.Get("user_id")
var req struct {
Name string `json:"name" binding:"required"`
Avatar string `json:"avatar"`
MemberIDs []string `json:"member_ids" binding:"required"`
AdminIDs []string `json:"admin_ids"`
}
if err := c.ShouldBindJSON(&req); err != nil {
utils.BadRequest(c, "参数错误: "+err.Error())
return
}
creatorID := userID.(string)
members := req.MemberIDs
// 确保创建者在成员列表中
found := false
for _, id := range members {
if id == creatorID {
found = true
break
}
}
if !found {
members = append(members, creatorID)
}
room, err := service.RoomSvc.CreateGroupRoom(creatorID, members, req.Name, req.Avatar, req.AdminIDs)
if err != nil {
utils.BadRequest(c, err.Error())
return
}
utils.SuccessWithData(c, room, "创建群聊成功")
}
/**
* GetGroupInfoHandler
* 功能:获取群聊基础信息及成员数量
* 路径:GET /api/groups/:room_id
*/
func GetGroupInfoHandler(c *gin.Context) {
roomID := c.Param("room_id")
room, err := service.RoomSvc.GetRoom(roomID)
if err != nil {
if err == gorm.ErrRecordNotFound {
utils.NotFound(c, "群聊不存在")
return
}
utils.InternalError(c, "查询失败")
return
}
members, err := service.RoomSvc.ListGroupMembers(roomID)
if err != nil {
utils.InternalError(c, "查询成员失败")
return
}
// 统计管理员ID
adminIDs := make([]string, 0)
for _, m := range members {
if m.Role == 1 {
adminIDs = append(adminIDs, m.UserID)
}
}
utils.SuccessWithData(c, gin.H{
"room": room,
"member_count": len(members),
"admin_ids": adminIDs,
"owner_id": room.OwnerID,
}, "获取成功")
}
/**
* ListGroupMembersHandler
* 功能:获取群成员列表
* 路径:GET /api/groups/:room_id/members
*/
func ListGroupMembersHandler(c *gin.Context) {
roomID := c.Param("room_id")
members, err := service.RoomSvc.ListGroupMembers(roomID)
if err != nil {
utils.InternalError(c, "查询失败")
return
}
utils.SuccessWithData(c, members, "获取成功")
}
/**
* AddGroupMembersHandler
* 功能:邀请/拉人入群
* 路径:POST /api/groups/:room_id/members
*/
func AddGroupMembersHandler(c *gin.Context) {
userID, _ := c.Get("user_id")
roomID := c.Param("room_id")
var req struct {
MemberIDs []string `json:"member_ids" binding:"required"`
}
if err := c.ShouldBindJSON(&req); err != nil {
utils.BadRequest(c, "参数错误: "+err.Error())
return
}
if err := service.RoomSvc.AddGroupMembers(roomID, userID.(string), req.MemberIDs); err != nil {
utils.BadRequest(c, err.Error())
return
}
utils.Success(c, "添加成员成功")
}
/**
* RemoveGroupMemberHandler
* 功能:移除群成员或退群
2025-12-05 09:25:24 +08:00
* 路径:POST /api/groups/:room_id/members/:user_id/remove
2025-12-04 22:29:32 +08:00
*/
func RemoveGroupMemberHandler(c *gin.Context) {
operatorID, _ := c.Get("user_id")
roomID := c.Param("room_id")
memberID := c.Param("user_id")
// 自己移除自己 = 退群
if operatorID.(string) == memberID {
if err := service.RoomSvc.QuitGroup(roomID, memberID); err != nil {
utils.BadRequest(c, err.Error())
return
}
utils.Success(c, "已退出群聊")
return
}
// 否则为管理员/群主踢人
if err := service.RoomSvc.RemoveGroupMember(roomID, operatorID.(string), memberID); err != nil {
utils.BadRequest(c, err.Error())
return
}
utils.Success(c, "已移除成员")
}
/**
* UpdateGroupInfoHandler
* 功能:修改群名称/头像
2025-12-05 09:25:24 +08:00
* 路径:POST /api/groups/:room_id/update
2025-12-04 22:29:32 +08:00
*/
func UpdateGroupInfoHandler(c *gin.Context) {
userID, _ := c.Get("user_id")
roomID := c.Param("room_id")
var req struct {
Name string `json:"name"`
Avatar string `json:"avatar"`
}
if err := c.ShouldBindJSON(&req); err != nil {
utils.BadRequest(c, "参数错误: "+err.Error())
return
}
// 仅群主或管理员可修改群信息
ok, err := service.RoomSvc.IsGroupAdminOrOwner(roomID, userID.(string))
if err != nil {
utils.InternalError(c, "权限校验失败")
return
}
if !ok {
utils.Forbidden(c, "无权限修改群信息")
return
}
updates := make(map[string]interface{})
if req.Name != "" {
updates["room_name"] = req.Name
}
if req.Avatar != "" {
updates["room_avatar"] = req.Avatar
}
if len(updates) == 0 {
utils.BadRequest(c, "没有可更新的字段")
return
}
// 更新群基础信息
if err := service.RoomSvc.DB.Model(&model.ChatRoom{}).
Where("room_id = ?", roomID).
Updates(updates).Error; err != nil {
utils.InternalError(c, "更新失败")
return
}
utils.Success(c, "更新成功")
}
/**
* ChangeMemberRoleHandler
* 功能:调整成员角色
2025-12-05 09:25:24 +08:00
* 路径:POST /api/groups/:room_id/members/:user_id/role
2025-12-04 22:29:32 +08:00
*/
func ChangeMemberRoleHandler(c *gin.Context) {
operatorID, _ := c.Get("user_id")
roomID := c.Param("room_id")
memberID := c.Param("user_id")
var req struct {
Role int8 `json:"role" binding:"required"`
}
if err := c.ShouldBindJSON(&req); err != nil {
utils.BadRequest(c, "参数错误: "+err.Error())
return
}
if err := service.RoomSvc.ChangeMemberRole(roomID, operatorID.(string), memberID, req.Role); err != nil {
utils.BadRequest(c, err.Error())
return
}
utils.Success(c, "角色已更新")
}
2025-12-05 09:25:24 +08:00
/**
* QuitGroupHandler
* 功能:群成员主动退出群聊
* 路径:POST /api/groups/:room_id/quit
*/
func QuitGroupHandler(c *gin.Context) {
userID, _ := c.Get("user_id")
roomID := c.Param("room_id")
// 校验用户是否为该群的成员
members, err := service.RoomSvc.ListGroupMembers(roomID)
if err != nil {
utils.InternalError(c, "查询成员失败")
return
}
isMember := false
for _, m := range members {
if m.UserID == userID.(string) {
isMember = true
break
}
}
if !isMember {
utils.BadRequest(c, "您不是该群的成员")
return
}
// 调用服务层退出群聊
if err := service.RoomSvc.QuitGroup(roomID, userID.(string)); err != nil {
utils.BadRequest(c, err.Error())
return
}
utils.Success(c, "已退出群聊")
}
/**
* DissolveGroupHandler
* 功能:群主解散群聊
* 路径:POST /api/groups/:room_id/dissolve
*/
func DissolveGroupHandler(c *gin.Context) {
userID, _ := c.Get("user_id")
roomID := c.Param("room_id")
// 调用服务层解散群聊
if err := service.RoomSvc.DissolveGroup(roomID, userID.(string)); err != nil {
utils.BadRequest(c, err.Error())
return
}
utils.Success(c, "群聊已解散")
}
/**
* GetGroupNotificationsHandler
* 功能:获取群通知列表
* 路径:GET /api/group-notifications
*/
func GetGroupNotificationsHandler(c *gin.Context) {
userID, _ := c.Get("user_id")
// 分页参数
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))
isReadStr := c.Query("is_read")
if page < 1 {
page = 1
}
if pageSize < 1 || pageSize > 100 {
pageSize = 20
}
// 构建查询条件
query := service.ChatSvc.DB.Model(&model.ChatMessage{}).
Where("message_type = ?", model.MessageTypeGroupNotif).
Where("room_id IN (SELECT room_id FROM room_members WHERE user_id = ?)", userID)
// 可选:按已读状态过滤
if isReadStr == "true" || isReadStr == "false" {
// 注意:chat_messages 表可能没有 is_read 字段,这里先不实现
// 如果需要,可以在 extra 字段中存储或使用其他方式
}
// 获取总数
var total int64
query.Count(&total)
// 分页查询
offset := (page - 1) * pageSize
var messages []model.ChatMessage
if err := query.Order("created_at desc").
Offset(offset).
Limit(pageSize).
Find(&messages).Error; err != nil {
utils.InternalError(c, "查询失败")
return
}
// 确保返回空数组而不是null
if messages == nil {
messages = []model.ChatMessage{}
}
utils.SuccessWithData(c, gin.H{
"data": messages,
"total": total,
"page": page,
"page_size": pageSize,
}, "获取成功")
}