Files
nl-im-service/internal/api/room_handler.go
2026-07-08 08:18:58 +08:00

1027 lines
27 KiB
Go
Raw Permalink 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 (
"encoding/json"
"fmt"
"log"
"strconv"
"strings"
"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
}
// 为所有成员创建会话记录
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)
}
}
}
}
utils.SuccessWithData(c, room, "创建群聊成功")
}
/**
* 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{}{
"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),
"last_message_time": lastMessageTime,
"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"),
})
}
utils.SuccessWithData(c, result, "获取成功")
}
/**
* 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")
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)
}
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
}
// 发送群通知和系统消息
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{}{
"type": "member_invite",
"room_id": roomID,
"operator": userID.(string),
"operator_name": operator.Name,
"targets": req.MemberIDs,
"target_names": invitedNames,
}
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{}{
"type": "member_invited",
"room_id": roomID,
"operator": userID.(string),
"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)
}
}
}
}
}
}
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
}
// 发送群通知和系统消息
if service.ChatSvc != nil && service.UserSvc != nil {
// 获取操作者和被移除成员信息
operator, opErr := service.UserSvc.GetUserByID(operatorID.(string))
member, memErr := service.UserSvc.GetUserByID(memberID)
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{}{
"type": "member_remove",
"room_id": roomID,
"operator": operatorID.(string),
"target": memberID,
"operator_name": operator.Name,
"target_name": member.Name,
}
notifExtraJSON, _ := json.Marshal(notifExtra)
// 构建系统消息
systemContent := fmt.Sprintf("你被 %s 移出了群聊", operator.Name)
systemExtra := map[string]interface{}{
"type": "member_removed",
"room_id": roomID,
"operator": operatorID.(string),
}
systemExtraJSON, _ := json.Marshal(systemExtra)
// 为所有成员发送群通知
for _, uid := range memberIDs {
if uid == memberID {
continue // 被移除的成员不接收群通知
}
// 群通知消息
notifMsg := model.ChatMessage{
RoomID: roomID,
SenderUserID: operatorID.(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)
}
}
// 为被移除的成员发送系统消息
systemMsg := model.ChatMessage{
RoomID: roomID,
SenderUserID: operatorID.(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)
}
}
}
}
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"` // 使用指针类型,允许 0 值(普通成员)
}
if err := c.ShouldBindJSON(&req); err != nil {
utils.BadRequest(c, "参数错误: "+err.Error())
return
}
// 手动验证 role 是否提供
if req.Role == nil {
utils.BadRequest(c, "参数错误: role 字段必须提供")
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
}
// 发送群通知
if service.ChatSvc != nil && service.UserSvc != nil {
// 获取退出成员信息
member, memErr := service.UserSvc.GetUserByID(userID.(string))
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)
// 为所有剩余成员发送群通知
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)
}
}
}
}
}
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,
}, "获取成功")
}
/**
* 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, "更新成功")
}
/**
* 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,
}, "获取成功")
}
/**
* GetGroupSettingsHandler
* 功能:获取群设置(名称、头像、公告、邀请权限等)
* 路径GET /api/groups/:room_id/settings
*/
func GetGroupSettingsHandler(c *gin.Context) {
roomID := c.Param("room_id")
room, err := service.RoomSvc.GetRoom(roomID)
if err != nil {
utils.NotFound(c, "群聊不存在")
return
}
utils.SuccessWithData(c, gin.H{
"name": room.RoomName,
"avatar": room.RoomAvatar,
"description": room.Announcement,
"invite_permission": 0,
"created_at": room.CreatedAt,
"updated_at": room.UpdatedAt,
}, "获取成功")
}
/**
* UpdateGroupSettingsHandler
* 功能:更新群设置
* 路径POST /api/groups/:room_id/settings
*/
func UpdateGroupSettingsHandler(c *gin.Context) {
userID, _ := c.Get("user_id")
roomID := c.Param("room_id")
ok, err := service.RoomSvc.IsGroupAdminOrOwner(roomID, userID.(string))
if err != nil || !ok {
utils.Forbidden(c, "无权限修改群设置")
return
}
var req struct {
Name string `json:"name"`
Avatar string `json:"avatar"`
Description string `json:"description"`
InvitePermission *int `json:"invite_permission"`
}
if err := c.ShouldBindJSON(&req); err != nil {
utils.BadRequest(c, "参数错误")
return
}
updates := map[string]interface{}{}
if req.Name != "" {
updates["room_name"] = req.Name
}
if req.Avatar != "" {
updates["room_avatar"] = req.Avatar
}
if req.Description != "" {
updates["announcement"] = req.Description
}
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
}
GetGroupSettingsHandler(c)
}
/**
* GetCallHistoryHandler
* 功能:获取当前用户的通话记录(基于 call_id 消息)
* 路径GET /api/calls/history
*/
func GetCallHistoryHandler(c *gin.Context) {
userID, _ := c.Get("user_id")
var messages []model.ChatMessage
err := service.ChatSvc.DB.
Where("(sender_user_id = ? OR receiver_user_id = ?) AND call_id <> '' AND call_id IS NOT NULL", userID, userID).
Order("created_at DESC").
Limit(50).
Find(&messages).Error
if err != nil {
utils.InternalError(c, "查询失败")
return
}
utils.SuccessWithData(c, messages, "获取成功")
}