416 lines
13 KiB
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
|
|
}
|