Files
nl-im-service/internal/api/room_handler.go
2025-12-05 09:25:24 +08:00

423 lines
9.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* package api
* 作用房间管理相关API处理器
*/
package api
import (
"strconv"
"xk-websocket-v2/internal/model"
"xk-websocket-v2/internal/service"
"xk-websocket-v2/internal/utils"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
/**
* CreateRoomHandler
* 功能:创建房间
* 路径POST /api/rooms
*/
func CreateRoomHandler(c *gin.Context) {
userID, _ := c.Get("user_id")
var req struct {
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"`
}
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, "获取成功")
}
/**
* 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
* 功能:移除群成员或退群
* 路径POST /api/groups/:room_id/members/:user_id/remove
*/
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
* 功能:修改群名称/头像
* 路径POST /api/groups/:room_id/update
*/
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
* 功能:调整成员角色
* 路径POST /api/groups/:room_id/members/:user_id/role
*/
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, "角色已更新")
}
/**
* 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,
}, "获取成功")
}