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

937 lines
24 KiB
Go
Raw Normal View History

2025-12-03 11:00:47 +08:00
/**
* package api
* 作用房间管理相关API处理器
*/
package api
import (
2025-12-05 15:23:04 +08:00
"encoding/json"
"fmt"
2025-12-05 13:12:48 +08:00
"log"
2025-12-05 09:25:24 +08:00
"strconv"
2025-12-05 15:48:31 +08:00
"strings"
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
}
2025-12-05 15:23:04 +08:00
// 为所有成员创建会话记录
if service.ConversationSvc != nil {
if err := service.ConversationSvc.EnsureGroupConversations(room.RoomID); err != nil {
log.Printf("⚠️ 创建群聊会话失败 (roomID: %s): %v", room.RoomID, err)
}
}
// 发送系统消息通知所有成员
if service.ChatSvc != nil && service.UserSvc != nil {
// 获取创建者信息
creator, err := service.UserSvc.GetUserByID(creatorID)
if err == nil {
// 构建系统消息内容
content := fmt.Sprintf("%s 邀请你加入了群聊", creator.Name)
extraData := map[string]interface{}{
"type": "group_created",
"room_id": room.RoomID,
"creator": creatorID,
}
extraJSON, _ := json.Marshal(extraData)
// 为每个成员发送系统消息
for _, memberID := range members {
if memberID != creatorID {
// 创建系统消息
systemMsg := model.ChatMessage{
RoomID: room.RoomID,
SenderUserID: creatorID,
ReceiverUserID: room.RoomID, // 群聊时使用 roomID
MessageType: model.MessageTypeSystem,
Content: content,
Extra: string(extraJSON),
}
// 持久化消息
if err := service.ChatSvc.DB.Create(&systemMsg).Error; err != nil {
log.Printf("❌ 发送群聊系统消息失败 (memberID: %s): %v", memberID, err)
continue
}
// 更新会话
if service.ConversationSvc != nil {
_ = service.ConversationSvc.UpsertConversationOnMessage(memberID, room.RoomID, room.RoomID, systemMsg, false)
}
// 通过 WebSocket 推送消息
pushMsg := model.WsPayload{
RequestType: "receive_message",
Data: systemMsg,
}
msgBytes, _ := json.Marshal(pushMsg)
service.ChatSvc.DispatchMessage(memberID, msgBytes)
}
}
}
}
2025-12-04 22:29:32 +08:00
utils.SuccessWithData(c, room, "创建群聊成功")
}
2025-12-05 13:12:48 +08:00
/**
* ListUserGroupsHandler
* 功能获取用户所在的所有群聊列表带分组信息
* 路径GET /api/groups
*/
func ListUserGroupsHandler(c *gin.Context) {
userID, exists := c.Get("user_id")
if !exists {
utils.Unauthorized(c, "未授权")
return
}
groups, members, err := service.RoomSvc.ListUserGroups(userID.(string))
if err != nil {
utils.InternalError(c, "查询失败")
return
}
// 确保返回空数组而不是null
if groups == nil {
groups = []model.ChatRoom{}
}
if members == nil {
members = []model.RoomMember{}
}
// 为每个群的所有成员创建缺失的会话记录
if service.ConversationSvc != nil {
for _, group := range groups {
if err := service.ConversationSvc.EnsureGroupConversations(group.RoomID); err != nil {
// 记录错误但不中断流程
log.Printf("⚠️ 创建群聊会话失败 (roomID: %s): %v", group.RoomID, err)
}
}
}
// 创建成员映射表,方便快速查找
memberMap := make(map[string]model.RoomMember)
for _, member := range members {
memberMap[member.RoomID] = member
}
// 转换为前端期望的格式,包含 category 和 role
result := make([]map[string]interface{}, 0, len(groups))
for _, group := range groups {
// 获取用户在群中的角色
member, exists := memberMap[group.RoomID]
if !exists {
continue // 跳过无法获取成员信息的群
}
// 确定分类created/managed/joined
category := "joined"
if group.CreatorID == userID.(string) {
category = "created"
} else if member.Role == 1 || member.Role == 2 {
category = "managed"
}
// 格式化时间
var lastMessageTime *string
if group.LastMessageTime != nil {
timeStr := group.LastMessageTime.Format("2006-01-02T15:04:05Z07:00")
lastMessageTime = &timeStr
}
result = append(result, map[string]interface{}{
2025-12-08 14:18:00 +08:00
"room_id": group.RoomID,
"room_type": group.RoomType,
"room_name": group.RoomName,
"room_avatar": group.RoomAvatar,
"owner_id": group.OwnerID,
"creator_id": group.CreatorID,
"category": category,
"role": int(member.Role),
2025-12-05 13:12:48 +08:00
"last_message_time": lastMessageTime,
2025-12-08 14:18:00 +08:00
"last_message": group.LastMessage,
"created_at": group.CreatedAt.Format("2006-01-02T15:04:05Z07:00"),
"updated_at": group.UpdatedAt.Format("2006-01-02T15:04:05Z07:00"),
2025-12-05 13:12:48 +08:00
})
}
utils.SuccessWithData(c, result, "获取成功")
}
2025-12-04 22:29:32 +08:00
/**
* 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")
2025-12-05 15:23:04 +08:00
keyword := c.Query("keyword")
var members []model.RoomMember
var err error
if keyword != "" {
// 如果有搜索关键词,使用搜索方法
members, err = service.RoomSvc.SearchGroupMembers(roomID, keyword)
} else {
// 否则返回所有成员
members, err = service.RoomSvc.ListGroupMembers(roomID)
}
2025-12-04 22:29:32 +08:00
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
}
2025-12-05 15:48:31 +08:00
// 发送群通知和系统消息
if service.ChatSvc != nil && service.UserSvc != nil {
// 获取操作者信息
operator, opErr := service.UserSvc.GetUserByID(userID.(string))
if opErr == nil {
// 获取被邀请成员信息
invitedNames := make([]string, 0)
for _, memberID := range req.MemberIDs {
member, memErr := service.UserSvc.GetUserByID(memberID)
if memErr == nil {
invitedNames = append(invitedNames, member.Name)
}
}
if len(invitedNames) > 0 {
// 获取群成员列表(包括新加入的成员)
memberIDs, mErr := service.RoomSvc.GetRoomMembers(roomID)
if mErr == nil {
// 构建群通知消息内容
var notifContent string
if len(invitedNames) == 1 {
notifContent = fmt.Sprintf("%s 邀请了 %s 加入群聊", operator.Name, invitedNames[0])
} else {
notifContent = fmt.Sprintf("%s 邀请了 %s 加入群聊", operator.Name, strings.Join(invitedNames, "、"))
}
notifExtra := map[string]interface{}{
2025-12-08 14:18:00 +08:00
"type": "member_invite",
"room_id": roomID,
"operator": userID.(string),
2025-12-05 15:48:31 +08:00
"operator_name": operator.Name,
2025-12-08 14:18:00 +08:00
"targets": req.MemberIDs,
"target_names": invitedNames,
2025-12-05 15:48:31 +08:00
}
notifExtraJSON, _ := json.Marshal(notifExtra)
// 为所有成员发送群通知(包括新加入的成员)
for _, uid := range memberIDs {
// 群通知消息
notifMsg := model.ChatMessage{
RoomID: roomID,
SenderUserID: userID.(string),
ReceiverUserID: roomID,
MessageType: model.MessageTypeGroupNotif,
Content: notifContent,
Extra: string(notifExtraJSON),
}
if err := service.ChatSvc.DB.Create(&notifMsg).Error; err == nil {
// 更新会话
if service.ConversationSvc != nil {
_ = service.ConversationSvc.UpsertConversationOnMessage(uid, roomID, roomID, notifMsg, false)
}
// 推送消息
pushMsg := model.WsPayload{
RequestType: "receive_message",
Data: notifMsg,
}
msgBytes, _ := json.Marshal(pushMsg)
service.ChatSvc.DispatchMessage(uid, msgBytes)
}
}
// 为新加入的成员发送系统消息
for _, memberID := range req.MemberIDs {
systemContent := fmt.Sprintf("你被 %s 邀请加入群聊", operator.Name)
systemExtra := map[string]interface{}{
2025-12-08 14:18:00 +08:00
"type": "member_invited",
"room_id": roomID,
"operator": userID.(string),
2025-12-05 15:48:31 +08:00
"operator_name": operator.Name,
}
systemExtraJSON, _ := json.Marshal(systemExtra)
systemMsg := model.ChatMessage{
RoomID: roomID,
SenderUserID: userID.(string),
ReceiverUserID: roomID,
MessageType: model.MessageTypeSystem,
Content: systemContent,
Extra: string(systemExtraJSON),
}
if err := service.ChatSvc.DB.Create(&systemMsg).Error; err == nil {
// 更新会话
if service.ConversationSvc != nil {
_ = service.ConversationSvc.UpsertConversationOnMessage(memberID, roomID, roomID, systemMsg, false)
}
// 推送消息
pushMsg := model.WsPayload{
RequestType: "receive_message",
Data: systemMsg,
}
msgBytes, _ := json.Marshal(pushMsg)
service.ChatSvc.DispatchMessage(memberID, msgBytes)
}
}
}
}
}
}
2025-12-04 22:29:32 +08:00
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
}
2025-12-05 15:23:04 +08:00
// 发送群通知和系统消息
if service.ChatSvc != nil && service.UserSvc != nil {
// 获取操作者和被移除成员信息
operator, opErr := service.UserSvc.GetUserByID(operatorID.(string))
member, memErr := service.UserSvc.GetUserByID(memberID)
2025-12-08 14:18:00 +08:00
2025-12-05 15:23:04 +08:00
if opErr == nil && memErr == nil {
// 获取群成员列表
memberIDs, mErr := service.RoomSvc.GetRoomMembers(roomID)
if mErr == nil {
// 构建群通知消息
notifContent := fmt.Sprintf("%s 将 %s 移出了群聊", operator.Name, member.Name)
notifExtra := map[string]interface{}{
2025-12-08 14:18:00 +08:00
"type": "member_remove",
"room_id": roomID,
"operator": operatorID.(string),
"target": memberID,
2025-12-05 15:23:04 +08:00
"operator_name": operator.Name,
"target_name": member.Name,
}
notifExtraJSON, _ := json.Marshal(notifExtra)
2025-12-08 14:18:00 +08:00
2025-12-05 15:23:04 +08:00
// 构建系统消息
systemContent := fmt.Sprintf("你被 %s 移出了群聊", operator.Name)
systemExtra := map[string]interface{}{
2025-12-08 14:18:00 +08:00
"type": "member_removed",
"room_id": roomID,
2025-12-05 15:23:04 +08:00
"operator": operatorID.(string),
}
systemExtraJSON, _ := json.Marshal(systemExtra)
2025-12-08 14:18:00 +08:00
2025-12-05 15:23:04 +08:00
// 为所有成员发送群通知
for _, uid := range memberIDs {
if uid == memberID {
continue // 被移除的成员不接收群通知
}
2025-12-08 14:18:00 +08:00
2025-12-05 15:23:04 +08:00
// 群通知消息
notifMsg := model.ChatMessage{
RoomID: roomID,
SenderUserID: operatorID.(string),
ReceiverUserID: roomID,
MessageType: model.MessageTypeGroupNotif,
Content: notifContent,
Extra: string(notifExtraJSON),
}
2025-12-08 14:18:00 +08:00
2025-12-05 15:23:04 +08:00
if err := service.ChatSvc.DB.Create(&notifMsg).Error; err == nil {
// 更新会话
if service.ConversationSvc != nil {
_ = service.ConversationSvc.UpsertConversationOnMessage(uid, roomID, roomID, notifMsg, false)
}
2025-12-08 14:18:00 +08:00
2025-12-05 15:23:04 +08:00
// 推送消息
pushMsg := model.WsPayload{
RequestType: "receive_message",
Data: notifMsg,
}
msgBytes, _ := json.Marshal(pushMsg)
service.ChatSvc.DispatchMessage(uid, msgBytes)
}
}
2025-12-08 14:18:00 +08:00
2025-12-05 15:23:04 +08:00
// 为被移除的成员发送系统消息
systemMsg := model.ChatMessage{
RoomID: roomID,
SenderUserID: operatorID.(string),
ReceiverUserID: roomID,
MessageType: model.MessageTypeSystem,
Content: systemContent,
Extra: string(systemExtraJSON),
}
2025-12-08 14:18:00 +08:00
2025-12-05 15:23:04 +08:00
if err := service.ChatSvc.DB.Create(&systemMsg).Error; err == nil {
// 更新会话
if service.ConversationSvc != nil {
_ = service.ConversationSvc.UpsertConversationOnMessage(memberID, roomID, roomID, systemMsg, false)
}
2025-12-08 14:18:00 +08:00
2025-12-05 15:23:04 +08:00
// 推送消息
pushMsg := model.WsPayload{
RequestType: "receive_message",
Data: systemMsg,
}
msgBytes, _ := json.Marshal(pushMsg)
service.ChatSvc.DispatchMessage(memberID, msgBytes)
}
}
}
}
2025-12-04 22:29:32 +08:00
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 {
2025-12-08 14:55:47 +08:00
Role *int8 `json:"role"` // 使用指针类型,允许 0 值(普通成员)
2025-12-04 22:29:32 +08:00
}
if err := c.ShouldBindJSON(&req); err != nil {
utils.BadRequest(c, "参数错误: "+err.Error())
return
}
2025-12-08 14:55:47 +08:00
// 手动验证 role 是否提供
if req.Role == nil {
utils.BadRequest(c, "参数错误: role 字段必须提供")
return
}
if err := service.RoomSvc.ChangeMemberRole(roomID, operatorID.(string), memberID, *req.Role); err != nil {
2025-12-04 22:29:32 +08:00
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
}
2025-12-05 15:23:04 +08:00
// 发送群通知
if service.ChatSvc != nil && service.UserSvc != nil {
// 获取退出成员信息
member, memErr := service.UserSvc.GetUserByID(userID.(string))
2025-12-08 14:18:00 +08:00
2025-12-05 15:23:04 +08:00
if memErr == nil {
// 获取群成员列表(退出后剩余的成员)
memberIDs, mErr := service.RoomSvc.GetRoomMembers(roomID)
if mErr == nil {
// 构建群通知消息
notifContent := fmt.Sprintf("%s 退出了群聊", member.Name)
notifExtra := map[string]interface{}{
"type": "member_leave",
"room_id": roomID,
"target": userID.(string),
"target_name": member.Name,
}
notifExtraJSON, _ := json.Marshal(notifExtra)
2025-12-08 14:18:00 +08:00
2025-12-05 15:23:04 +08:00
// 为所有剩余成员发送群通知
for _, uid := range memberIDs {
notifMsg := model.ChatMessage{
RoomID: roomID,
SenderUserID: userID.(string),
ReceiverUserID: roomID,
MessageType: model.MessageTypeGroupNotif,
Content: notifContent,
Extra: string(notifExtraJSON),
}
2025-12-08 14:18:00 +08:00
2025-12-05 15:23:04 +08:00
if err := service.ChatSvc.DB.Create(&notifMsg).Error; err == nil {
// 更新会话
if service.ConversationSvc != nil {
_ = service.ConversationSvc.UpsertConversationOnMessage(uid, roomID, roomID, notifMsg, false)
}
2025-12-08 14:18:00 +08:00
2025-12-05 15:23:04 +08:00
// 推送消息
pushMsg := model.WsPayload{
RequestType: "receive_message",
Data: notifMsg,
}
msgBytes, _ := json.Marshal(pushMsg)
service.ChatSvc.DispatchMessage(uid, msgBytes)
}
}
}
}
}
2025-12-05 09:25:24 +08:00
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{
2025-12-08 14:18:00 +08:00
"data": messages,
"total": total,
"page": page,
2025-12-05 09:25:24 +08:00
"page_size": pageSize,
}, "获取成功")
}
2025-12-05 13:12:48 +08:00
/**
* GetGroupAnnouncementHandler
* 功能获取群公告
* 路径GET /api/groups/:room_id/announcement
*/
func GetGroupAnnouncementHandler(c *gin.Context) {
roomID := c.Param("room_id")
announcement, err := service.RoomSvc.GetGroupAnnouncement(roomID)
if err != nil {
if err == gorm.ErrRecordNotFound {
utils.NotFound(c, "群聊不存在")
return
}
utils.InternalError(c, "查询失败")
return
}
utils.SuccessWithData(c, gin.H{
"announcement": announcement,
}, "获取成功")
}
/**
* UpdateGroupAnnouncementHandler
* 功能更新群公告
* 路径POST /api/groups/:room_id/announcement
*/
func UpdateGroupAnnouncementHandler(c *gin.Context) {
userID, _ := c.Get("user_id")
roomID := c.Param("room_id")
var req struct {
Announcement string `json:"announcement" binding:"required"`
}
if err := c.ShouldBindJSON(&req); err != nil {
utils.BadRequest(c, "参数错误: "+err.Error())
return
}
if err := service.RoomSvc.UpdateGroupAnnouncement(roomID, userID.(string), req.Announcement); err != nil {
utils.BadRequest(c, err.Error())
return
}
utils.Success(c, "更新成功")
}
2025-12-08 14:18:00 +08:00
/**
* MuteGroupMemberHandler
* 功能禁言群成员
* 路径POST /api/groups/:room_id/members/:user_id/mute
*/
func MuteGroupMemberHandler(c *gin.Context) {
operatorID, _ := c.Get("user_id")
roomID := c.Param("room_id")
memberID := c.Param("user_id")
var req struct {
Duration int64 `json:"duration"` // 禁言时长0=永久,-1=解除禁言
}
if err := c.ShouldBindJSON(&req); err != nil {
utils.BadRequest(c, "参数错误: "+err.Error())
return
}
if err := service.RoomSvc.MuteGroupMember(roomID, operatorID.(string), memberID, req.Duration); err != nil {
utils.BadRequest(c, err.Error())
return
}
if req.Duration == -1 {
utils.Success(c, "已解除禁言")
} else if req.Duration == 0 {
utils.Success(c, "已永久禁言")
} else {
utils.Success(c, "禁言成功")
}
}
/**
* GetMemberMuteStatusHandler
* 功能获取成员禁言状态
* 路径GET /api/groups/:room_id/members/:user_id/mute
*/
func GetMemberMuteStatusHandler(c *gin.Context) {
roomID := c.Param("room_id")
memberID := c.Param("user_id")
isMuted, mutedUntil, err := service.RoomSvc.IsGroupMemberMuted(roomID, memberID)
if err != nil {
if err == gorm.ErrRecordNotFound {
utils.NotFound(c, "成员不存在")
return
}
utils.InternalError(c, "查询失败")
return
}
utils.SuccessWithData(c, gin.H{
"is_muted": isMuted,
"muted_until": mutedUntil,
}, "获取成功")
}