Files
IUQT/acquaintances/biz/dal/mysql/chat_group.go

416 lines
13 KiB
Go

package mysql
import (
"acquaintances/biz/model"
"acquaintances/biz/model/user"
"errors"
"github.com/cloudwego/hertz/pkg/common/hlog"
"gorm.io/gorm"
)
// 创建群
func CreateChatGroupInfo(userId string, data *model.ChatGroupInfo) error {
// 参数校验
if userId == "" {
return errors.New("用户ID不能为空")
}
if data == nil {
return errors.New("群组信息不能为空")
}
if data.ChatGroupID == "" {
return errors.New("群组ID不能为空")
}
if data.ChatGroupName == "" {
return errors.New("群组名称不能为空")
}
// 执行事务操作
errTransaction := DB.Transaction(func(tx *gorm.DB) error {
// 创建群基本信息
if err := tx.Model(&model.ChatGroupInfo{}).Create(data).Error; err != nil {
hlog.Error("创建群基本信息失败", err, "group_id", data.ChatGroupID, "user_id", userId)
return errors.New("创建群信息失败")
}
hlog.Info("群基本信息创建成功", "group_id", data.ChatGroupID)
// 添加创始人到群,设置为群主
creater := model.GroupUserRelation{
ChatGroupID: data.ChatGroupID,
UserID: userId,
Role: model.GroupLeader,
}
if err := tx.Model(&model.GroupUserRelation{}).Create(&creater).Error; err != nil {
hlog.Error("添加群主到群失败", err, "group_id", data.ChatGroupID, "user_id", userId)
return errors.New("添加群主失败")
}
hlog.Info("群主添加到群成功", "group_id", data.ChatGroupID, "user_id", userId)
return nil
})
if errTransaction != nil {
hlog.Error("创建群事务执行失败", errTransaction, "group_id", data.ChatGroupID, "user_id", userId)
return errTransaction
}
hlog.Info("群创建成功", "group_id", data.ChatGroupID, "creator", userId)
return nil
}
// 解散群
func DeleteChatGroupInfo(chatGroupId, userId string) error {
// 参数校验
if chatGroupId == "" || userId == "" {
return errors.New("群组ID和用户ID不能为空")
}
// 检查用户是否为群主(只有群主可以解散群)
var role int
err := DB.Model(&model.GroupUserRelation{}).
Where("chat_group_id = ? AND user_id = ?", chatGroupId, userId).
Pluck("role", &role).Error
if err != nil {
hlog.Error("查询用户群角色失败", err, "user_id", userId, "group_id", chatGroupId)
return errors.New("查询用户权限失败")
}
if role != int(model.GroupLeader) {
hlog.Warn("非群主尝试解散群", "user_id", userId, "group_id", chatGroupId, "role", role)
return errors.New("只有群主可以解散群")
}
// 执行事务操作
errTransaction := DB.Transaction(func(tx *gorm.DB) error {
// 解除群与用户关系
relationResult := tx.Where("chat_group_id = ?", chatGroupId).Delete(&model.GroupUserRelation{})
if relationResult.Error != nil {
hlog.Error("解除群与用户关系失败", relationResult.Error, "group_id", chatGroupId)
return errors.New("解除群成员关系失败")
}
hlog.Info("解除群与用户关系成功", "group_id", chatGroupId, "affected_users", relationResult.RowsAffected)
// 删除群基本信息
groupResult := tx.Where("chat_group_id = ?", chatGroupId).Delete(&model.ChatGroupInfo{})
if groupResult.Error != nil {
hlog.Error("删除群基本信息失败", groupResult.Error, "group_id", chatGroupId)
return errors.New("删除群信息失败")
}
if groupResult.RowsAffected == 0 {
hlog.Warn("未找到要删除的群信息", "group_id", chatGroupId)
return errors.New("未找到对应的群")
}
hlog.Info("群信息删除成功", "group_id", chatGroupId)
return nil
})
if errTransaction != nil {
hlog.Error("解散群事务执行失败", errTransaction, "group_id", chatGroupId, "user_id", userId)
return errTransaction
}
hlog.Info("群解散成功", "group_id", chatGroupId, "operator", userId)
return nil
}
// 修改群信息
func UpdatesChatGroupInfo(cg *user.UpdateChatGroupReq) error {
// 参数基本校验
if cg == nil {
return errors.New("请求参数不能为空")
}
if cg.UserID == "" || cg.ChatGroupID == "" {
return errors.New("用户ID和群组ID不能为空")
}
// 检查用户是否有修改权限(群主或管理员)
var hasPermission bool
err := DB.Model(&model.GroupUserRelation{}).
Where("user_id = ? AND chat_group_id = ? AND role IN (?, ?)",
cg.UserID, cg.ChatGroupID, model.GroupLeader, model.Administrators).
Select("COUNT(*) > 0").
Scan(&hasPermission).Error
if err != nil {
hlog.Error("查询用户群权限失败", err, "user_id", cg.UserID, "group_id", cg.ChatGroupID)
return errors.New("查询权限失败")
}
if !hasPermission {
return errors.New("没有权限修改群信息")
}
// 构建更新字段映射
updateFields := make(map[string]interface{})
if cg.NewChatGroupName != "" {
updateFields["chat_group_name"] = cg.NewChatGroupName
}
if cg.ChatGroupNameImageURL != "" {
updateFields["chat_group_image_url"] = cg.ChatGroupNameImageURL
}
if cg.ChatGroupNotice != "" {
updateFields["chat_group_notice"] = cg.ChatGroupNotice
}
// 没有需要更新的字段
if len(updateFields) == 0 {
return errors.New("没有需要更新的群信息")
}
hlog.Info("准备更新群信息", "group_id", cg.ChatGroupID, "fields", updateFields)
// 执行更新操作
result := DB.Model(&model.ChatGroupInfo{}).
Where("chat_group_id = ?", cg.ChatGroupID).
Updates(updateFields)
if result.Error != nil {
hlog.Error("更新群信息失败", result.Error, "group_id", cg.ChatGroupID)
return errors.New("更新群信息失败")
}
if result.RowsAffected == 0 {
hlog.Warn("未找到对应群组或没有修改任何信息", "group_id", cg.ChatGroupID)
return errors.New("未找到对应群组")
}
hlog.Info("群信息更新成功", "group_id", cg.ChatGroupID, "rows_affected", result.RowsAffected)
return nil
}
// 加入群
func JoinChatGroup(joinData *user.JoinChatGroupReq) error {
// 参数校验
if joinData == nil {
return errors.New("请求参数不能为空")
}
if joinData.UserID == "" || joinData.ChatGroupID == "" {
return errors.New("用户ID和群组ID不能为空")
}
// 检查群组是否存在
var groupExists bool
err := DB.Model(&model.ChatGroupInfo{}).
Where("chat_group_id = ?", joinData.ChatGroupID).
Select("COUNT(*) > 0").
Scan(&groupExists).Error
if err != nil {
hlog.Error("查询群组存在性失败", err, "group_id", joinData.ChatGroupID)
return errors.New("查询群组信息失败")
}
if !groupExists {
return errors.New("群组不存在")
}
// 检查用户是否已在群中
var userInGroup bool
err = DB.Model(&model.GroupUserRelation{}).
Where("chat_group_id = ? AND user_id = ?", joinData.ChatGroupID, joinData.UserID).
Select("COUNT(*) > 0").
Scan(&userInGroup).Error
if err != nil {
hlog.Error("查询用户是否在群中失败", err, "group_id", joinData.ChatGroupID, "user_id", joinData.UserID)
return errors.New("查询用户群成员关系失败")
}
if userInGroup {
return errors.New("用户已在群中")
}
// 准备加入群的数据
joinUser := &model.GroupUserRelation{
UserID: joinData.UserID,
ChatGroupID: joinData.ChatGroupID,
Role: model.General,
}
hlog.Info("准备添加群成员", "group_id", joinData.ChatGroupID, "user_id", joinData.UserID)
// 执行添加操作
err = DB.Model(&model.GroupUserRelation{}).Create(joinUser).Error
if err != nil {
hlog.Error("添加群成员失败", err, "group_id", joinData.ChatGroupID, "user_id", joinData.UserID)
return errors.New("加入群失败")
}
hlog.Info("用户成功加入群", "group_id", joinData.ChatGroupID, "user_id", joinData.UserID)
return nil
}
// 退出群
func ExitChatGroup(leaveData *user.ExitChatGroupReq) error {
// 参数校验
if leaveData == nil {
return errors.New("请求参数不能为空")
}
if leaveData.UserID == "" || leaveData.ChatGroupID == "" {
return errors.New("用户ID和群组ID不能为空")
}
// 检查用户是否在群中
var userRelation model.GroupUserRelation
err := DB.Model(&model.GroupUserRelation{}).
Where("chat_group_id = ? AND user_id = ?", leaveData.ChatGroupID, leaveData.UserID).
First(&userRelation).Error
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return errors.New("用户不在该群中")
}
hlog.Error("查询用户群关系失败", err, "group_id", leaveData.ChatGroupID, "user_id", leaveData.UserID)
return errors.New("查询用户群成员关系失败")
}
// 检查是否为群主
if userRelation.Role == model.GroupLeader {
// 统计群成员数量
var memberCount int64
if err := DB.Model(&model.GroupUserRelation{}).
Where("chat_group_id = ?", leaveData.ChatGroupID).
Count(&memberCount).Error; err != nil {
hlog.Error("查询群成员数量失败", err, "group_id", leaveData.ChatGroupID)
return errors.New("查询群成员数量失败")
}
// 群主不能退出群,只能解散群(如果是最后一个成员则允许退出并解散)
if memberCount > 1 {
return errors.New("群主不能退出群,请先解散群或转让群主身份")
}
}
// 执行退出操作
result := DB.Model(&model.GroupUserRelation{}).
Where("chat_group_id = ? AND user_id = ?", leaveData.ChatGroupID, leaveData.UserID).
Delete(&model.GroupUserRelation{})
if result.Error != nil {
hlog.Error("退出群失败", result.Error, "group_id", leaveData.ChatGroupID, "user_id", leaveData.UserID)
return errors.New("退出群失败")
}
// 如果是群主且是最后一个成员,同时删除群
if userRelation.Role == model.GroupLeader {
var remainingCount int64
if err := DB.Model(&model.GroupUserRelation{}).
Where("chat_group_id = ?", leaveData.ChatGroupID).
Count(&remainingCount).Error; err != nil {
hlog.Error("查询剩余群成员失败", err, "group_id", leaveData.ChatGroupID)
return errors.New("查询剩余群成员失败")
}
if remainingCount == 0 {
// 最后一个成员(群主)退出,删除群
if err := DB.Where("chat_group_id = ?", leaveData.ChatGroupID).
Delete(&model.ChatGroupInfo{}).Error; err != nil {
hlog.Error("删除空群失败", err, "group_id", leaveData.ChatGroupID)
// 这里不返回错误,因为用户已经成功退出
hlog.Warn("用户已退出,但删除空群失败", "group_id", leaveData.ChatGroupID)
} else {
hlog.Info("群已解散(最后一个成员退出)", "group_id", leaveData.ChatGroupID)
}
}
}
hlog.Info("用户成功退出群", "group_id", leaveData.ChatGroupID, "user_id", leaveData.UserID)
return nil
}
// 获取群成员列表
func GetUserListByChatGroup(req *user.ListUserChatGroupReq) ([]*user.UserInfoReq, error) {
// 参数校验
if req == nil {
return nil, errors.New("请求参数不能为空")
}
if req.ChatGroupID == "" {
return nil, errors.New("群组ID不能为空")
}
// 检查群组是否存在
var groupCount int64
if err := DB.Model(&model.ChatGroupInfo{}).
Where("chat_group_id = ?", req.ChatGroupID).
Count(&groupCount).Error; err != nil {
hlog.Error("查询群组存在性失败", err, "chat_group_id", req.ChatGroupID)
return nil, errors.New("查询群组信息失败")
}
if groupCount == 0 {
return nil, errors.New("指定的群组不存在")
}
// 查询群内所有成员关系
var relations []model.GroupUserRelation
if err := DB.Model(&model.GroupUserRelation{}).
Where("chat_group_id = ?", req.ChatGroupID).
Find(&relations).Error; err != nil {
hlog.Error("查询群成员关系失败", err, "chat_group_id", req.ChatGroupID)
return nil, errors.New("获取群成员关系失败")
}
// 处理没有成员的情况
if len(relations) == 0 {
return []*user.UserInfoReq{}, nil // 返回空列表而非错误
}
// 提取成员ID列表
var userIDs []string
for _, relation := range relations {
userIDs = append(userIDs, relation.UserID)
}
// 批量获取用户信息
users, err := GetUsersById(userIDs...)
if err != nil {
hlog.Error("批量获取用户信息失败", err, "user_ids_count", len(userIDs))
return nil, errors.New("获取用户信息失败")
}
hlog.Info("成功获取群成员列表", "chat_group_id", req.ChatGroupID, "member_count", len(users))
return users, nil
}
// 获取用户群列表
func GetChatGroupListByUser(req *user.ListChatGroupByUserReq) ([]*user.ChatGroupInfo, error) {
// 参数校验
if req == nil {
return nil, errors.New("请求参数不能为空")
}
if req.UserID == "" {
return nil, errors.New("用户ID不能为空")
}
// 查询用户加入的所有群的关系记录
var relations []model.GroupUserRelation
if err := DB.Model(&model.GroupUserRelation{}).
Where("user_id = ?", req.UserID).
Find(&relations).Error; err != nil {
hlog.Error("查询用户群关系失败", err, "user_id", req.UserID)
return nil, errors.New("获取用户群关系失败")
}
// 处理用户未加入任何群的情况
if len(relations) == 0 {
return []*user.ChatGroupInfo{}, nil // 返回空列表而非错误
}
// 提取所有群组ID
var groupIDs []string
for _, relation := range relations {
groupIDs = append(groupIDs, relation.ChatGroupID)
}
// 查询这些群组的详细信息
var groupInfos []*user.ChatGroupInfo
if err := DB.Model(&model.ChatGroupInfo{}).
Where("chat_group_id IN (?)", groupIDs).
Find(&groupInfos).Error; err != nil {
hlog.Error("查询群组信息失败", err, "group_ids_count", len(groupIDs))
return nil, errors.New("获取群组信息失败")
}
hlog.Info("成功获取用户群列表", "user_id", req.UserID, "group_count", len(groupInfos))
return groupInfos, nil
}