feat: 🎸 在线交流接口
This commit is contained in:
parent
c7a66f623f
commit
59cd0049e2
@ -24,10 +24,13 @@ import org.jeecg.modules.aiol.entity.AiolChatMember;
|
||||
import org.jeecg.modules.aiol.entity.AiolChatMessage;
|
||||
import org.jeecg.modules.aiol.entity.AiolClass;
|
||||
import org.jeecg.modules.aiol.entity.AiolClassStudent;
|
||||
import org.jeecg.modules.aiol.dto.ChatWithUnreadCountDTO;
|
||||
import org.jeecg.modules.aiol.mapper.AiolChatMemberMapper;
|
||||
import org.jeecg.modules.aiol.mapper.AiolChatMessageMapper;
|
||||
import org.jeecg.modules.aiol.mapper.AiolClassMapper;
|
||||
import org.jeecg.modules.aiol.mapper.AiolClassStudentMapper;
|
||||
import org.jeecg.modules.system.mapper.SysUserRoleMapper;
|
||||
import org.jeecg.modules.aiol.constant.RoleConst;
|
||||
import org.jeecg.modules.aiol.service.IAiolChatService;
|
||||
import org.jeecg.modules.system.entity.SysUser;
|
||||
import org.jeecg.modules.system.mapper.SysUserMapper;
|
||||
@ -85,6 +88,9 @@ public class AiolChatController extends JeecgController<AiolChat, IAiolChatServi
|
||||
@Autowired
|
||||
private AiolClassStudentMapper aiolClassStudentMapper;
|
||||
|
||||
@Autowired
|
||||
private SysUserRoleMapper sysUserRoleMapper;
|
||||
|
||||
/**
|
||||
* 分页列表查询
|
||||
*
|
||||
@ -218,9 +224,9 @@ public class AiolChatController extends JeecgController<AiolChat, IAiolChatServi
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
@Operation(summary = "查询当前用户会话列表", description = "根据当前登录用户ID查询其参与的会话列表")
|
||||
@Operation(summary = "查询当前用户会话列表", description = "根据当前登录用户ID查询其参与的会话列表,包含未读消息数")
|
||||
@GetMapping(value = "/my_chats")
|
||||
public Result<List<AiolChat>> queryMyChatList(HttpServletRequest request) {
|
||||
public Result<List<ChatWithUnreadCountDTO>> queryMyChatList(HttpServletRequest request) {
|
||||
try {
|
||||
// 1. 从token获取当前用户信息
|
||||
String token = request.getHeader(CommonConstant.X_ACCESS_TOKEN);
|
||||
@ -235,7 +241,7 @@ public class AiolChatController extends JeecgController<AiolChat, IAiolChatServi
|
||||
return Result.error("用户信息不存在");
|
||||
}
|
||||
|
||||
// 2. 根据用户ID查询会话成员表,获取chat_id列表
|
||||
// 2. 根据用户ID查询会话成员表,获取chat_id列表和last_read_msg_id
|
||||
QueryWrapper<AiolChatMember> memberWrapper = new QueryWrapper<>();
|
||||
memberWrapper.eq("user_id", sysUser.getId());
|
||||
List<AiolChatMember> chatMembers = aiolChatMemberMapper.selectList(memberWrapper);
|
||||
@ -256,37 +262,16 @@ public class AiolChatController extends JeecgController<AiolChat, IAiolChatServi
|
||||
|
||||
List<AiolChat> chatList = aiolChatService.list(chatWrapper);
|
||||
|
||||
// 5. 处理私聊类型的会话,获取对方用户信息
|
||||
// 5. 转换为包含未读消息数的DTO列表
|
||||
List<ChatWithUnreadCountDTO> resultList = new java.util.ArrayList<>();
|
||||
|
||||
for (AiolChat chat : chatList) {
|
||||
if (chat.getType() != null && chat.getType() == 0) {
|
||||
// 私聊类型,需要获取对方用户信息
|
||||
try {
|
||||
// 查询该会话的成员,排除当前用户
|
||||
QueryWrapper<AiolChatMember> otherMemberWrapper = new QueryWrapper<>();
|
||||
otherMemberWrapper.eq("chat_id", chat.getId())
|
||||
.ne("user_id", sysUser.getId());
|
||||
List<AiolChatMember> otherMembers = aiolChatMemberMapper.selectList(otherMemberWrapper);
|
||||
|
||||
if (!otherMembers.isEmpty()) {
|
||||
// 获取对方用户ID
|
||||
String otherUserId = otherMembers.get(0).getUserId();
|
||||
|
||||
// 查询对方用户信息
|
||||
SysUser otherUser = sysUserMapper.selectById(otherUserId);
|
||||
if (otherUser != null) {
|
||||
// 替换会话的name和avatar为对方用户信息
|
||||
chat.setName(otherUser.getRealname());
|
||||
chat.setAvatar(otherUser.getAvatar());
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("获取私聊对方用户信息失败: chatId={}, error={}", chat.getId(), e.getMessage());
|
||||
}
|
||||
}
|
||||
ChatWithUnreadCountDTO chatDTO = convertToChatWithUnreadCount(chat, chatMembers, sysUser.getId());
|
||||
resultList.add(chatDTO);
|
||||
}
|
||||
|
||||
log.info("用户 {} 查询到 {} 个会话", username, chatList.size());
|
||||
return Result.OK(chatList);
|
||||
log.info("用户 {} 查询到 {} 个会话", username, resultList.size());
|
||||
return Result.OK(resultList);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("查询用户会话列表失败: {}", e.getMessage(), e);
|
||||
@ -300,7 +285,7 @@ public class AiolChatController extends JeecgController<AiolChat, IAiolChatServi
|
||||
* @param chatId 会话ID
|
||||
* @return
|
||||
*/
|
||||
@Operation(summary = "查询群聊会话成员列表", description = "根据会话ID查询该会话的所有成员信息,包括用户ID、真实姓名和头像")
|
||||
@Operation(summary = "查询群聊会话成员列表", description = "根据会话ID查询该会话的所有成员信息,包括用户ID、真实姓名、头像和教师身份")
|
||||
@GetMapping(value = "/{chatId}/members")
|
||||
public Result<List<Map<String, Object>>> queryChatMembers(@PathVariable(value = "chatId") String chatId) {
|
||||
try {
|
||||
@ -321,7 +306,26 @@ public class AiolChatController extends JeecgController<AiolChat, IAiolChatServi
|
||||
// 3. 查询用户信息
|
||||
List<SysUser> userList = sysUserMapper.selectByIds(userIds);
|
||||
|
||||
// 4. 构建返回结果
|
||||
// 4. 查询所有用户的教师角色身份
|
||||
Map<String, Boolean> teacherStatusMap = new java.util.HashMap<>();
|
||||
if (!userIds.isEmpty()) {
|
||||
try {
|
||||
QueryWrapper<org.jeecg.modules.system.entity.SysUserRole> roleWrapper = new QueryWrapper<>();
|
||||
roleWrapper.eq("role_id", RoleConst.TEACHER_ROLE_ID)
|
||||
.in("user_id", userIds);
|
||||
|
||||
List<org.jeecg.modules.system.entity.SysUserRole> teacherRoleList = sysUserRoleMapper.selectList(roleWrapper);
|
||||
|
||||
// 构建教师身份映射
|
||||
for (org.jeecg.modules.system.entity.SysUserRole userRole : teacherRoleList) {
|
||||
teacherStatusMap.put(userRole.getUserId(), true);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("查询教师角色身份失败: error={}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// 5. 构建返回结果
|
||||
List<Map<String, Object>> result = new java.util.ArrayList<>();
|
||||
for (SysUser user : userList) {
|
||||
Map<String, Object> memberInfo = new java.util.HashMap<>();
|
||||
@ -329,6 +333,10 @@ public class AiolChatController extends JeecgController<AiolChat, IAiolChatServi
|
||||
memberInfo.put("realname", user.getRealname());
|
||||
memberInfo.put("avatar", user.getAvatar());
|
||||
|
||||
// 添加教师身份标记
|
||||
boolean isTeacher = teacherStatusMap.getOrDefault(user.getId(), false);
|
||||
memberInfo.put("isTeacher", isTeacher);
|
||||
|
||||
// 可选:添加更多用户信息
|
||||
memberInfo.put("username", user.getUsername());
|
||||
memberInfo.put("phone", user.getPhone());
|
||||
@ -502,4 +510,458 @@ public class AiolChatController extends JeecgController<AiolChat, IAiolChatServi
|
||||
return Result.error("查询会话详情失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 开启全员禁言
|
||||
*
|
||||
* @param chatId 会话ID
|
||||
* @return
|
||||
*/
|
||||
@AutoLog(value = "会话-开启全员禁言")
|
||||
@Operation(summary = "开启全员禁言", description = "开启群聊的全员禁言功能,设置iz_all_muted字段为1")
|
||||
@PostMapping(value = "/{chatId}/mute_all")
|
||||
public Result<String> muteAll(@PathVariable(value = "chatId") String chatId) {
|
||||
try {
|
||||
return updateChatSetting(chatId, "iz_all_muted", 1, "开启全员禁言");
|
||||
} catch (Exception e) {
|
||||
log.error("开启全员禁言失败: chatId={}, error={}", chatId, e.getMessage(), e);
|
||||
return Result.error("开启全员禁言失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭全员禁言
|
||||
*
|
||||
* @param chatId 会话ID
|
||||
* @return
|
||||
*/
|
||||
@AutoLog(value = "会话-关闭全员禁言")
|
||||
@Operation(summary = "关闭全员禁言", description = "关闭群聊的全员禁言功能,设置iz_all_muted字段为0")
|
||||
@PostMapping(value = "/{chatId}/unmute_all")
|
||||
public Result<String> unmuteAll(@PathVariable(value = "chatId") String chatId) {
|
||||
try {
|
||||
return updateChatSetting(chatId, "iz_all_muted", 0, "关闭全员禁言");
|
||||
} catch (Exception e) {
|
||||
log.error("关闭全员禁言失败: chatId={}, error={}", chatId, e.getMessage(), e);
|
||||
return Result.error("关闭全员禁言失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 开启显示教师标签
|
||||
*
|
||||
* @param chatId 会话ID
|
||||
* @return
|
||||
*/
|
||||
@AutoLog(value = "会话-开启显示教师标签")
|
||||
@Operation(summary = "开启显示教师标签", description = "开启群聊中显示教师标签功能,设置show_label字段为1")
|
||||
@PostMapping(value = "/{chatId}/show_label")
|
||||
public Result<String> showLabel(@PathVariable(value = "chatId") String chatId) {
|
||||
try {
|
||||
return updateChatSetting(chatId, "show_label", 1, "开启显示教师标签");
|
||||
} catch (Exception e) {
|
||||
log.error("开启显示教师标签失败: chatId={}, error={}", chatId, e.getMessage(), e);
|
||||
return Result.error("开启显示教师标签失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭显示教师标签
|
||||
*
|
||||
* @param chatId 会话ID
|
||||
* @return
|
||||
*/
|
||||
@AutoLog(value = "会话-关闭显示教师标签")
|
||||
@Operation(summary = "关闭显示教师标签", description = "关闭群聊中显示教师标签功能,设置show_label字段为0")
|
||||
@PostMapping(value = "/{chatId}/hide_label")
|
||||
public Result<String> hideLabel(@PathVariable(value = "chatId") String chatId) {
|
||||
try {
|
||||
return updateChatSetting(chatId, "show_label", 0, "关闭显示教师标签");
|
||||
} catch (Exception e) {
|
||||
log.error("关闭显示教师标签失败: chatId={}, error={}", chatId, e.getMessage(), e);
|
||||
return Result.error("关闭显示教师标签失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 通用更新会话设置的方法
|
||||
*
|
||||
* @param chatId 会话ID
|
||||
* @param fieldName 字段名
|
||||
* @param value 字段值
|
||||
* @param operationName 操作名称
|
||||
* @return
|
||||
*/
|
||||
private Result<String> updateChatSetting(String chatId, String fieldName, Integer value, String operationName) {
|
||||
// 1. 查询会话是否存在
|
||||
AiolChat chat = aiolChatService.getById(chatId);
|
||||
if (chat == null) {
|
||||
return Result.error("会话不存在");
|
||||
}
|
||||
|
||||
// 2. 根据字段名设置相应的值
|
||||
if ("iz_all_muted".equals(fieldName)) {
|
||||
chat.setIzAllMuted(value);
|
||||
} else if ("show_label".equals(fieldName)) {
|
||||
chat.setShowLabel(value);
|
||||
} else {
|
||||
return Result.error("无效的字段名");
|
||||
}
|
||||
|
||||
// 3. 更新数据库
|
||||
boolean updated = aiolChatService.updateById(chat);
|
||||
if (!updated) {
|
||||
return Result.error(operationName + "失败");
|
||||
}
|
||||
|
||||
log.info("{}成功: chatId={}, {}={}", operationName, chatId, fieldName, value);
|
||||
return Result.OK(operationName + "成功!");
|
||||
}
|
||||
|
||||
/**
|
||||
* 禁言群聊成员
|
||||
*
|
||||
* @param chatId 会话ID
|
||||
* @param userId 用户ID
|
||||
* @return
|
||||
*/
|
||||
@AutoLog(value = "会话-禁言群聊成员")
|
||||
@Operation(summary = "禁言群聊成员", description = "禁言指定群聊成员,设置iz_muted字段为1")
|
||||
@PostMapping(value = "/{chatId}/mute_member/{userId}")
|
||||
public Result<String> muteMember(@PathVariable(value = "chatId") String chatId,
|
||||
@PathVariable(value = "userId") String userId) {
|
||||
try {
|
||||
return updateMemberSetting(chatId, userId, "iz_muted", 1, "禁言群聊成员");
|
||||
} catch (Exception e) {
|
||||
log.error("禁言群聊成员失败: chatId={}, userId={}, error={}", chatId, userId, e.getMessage(), e);
|
||||
return Result.error("禁言群聊成员失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解除禁言群聊成员
|
||||
*
|
||||
* @param chatId 会话ID
|
||||
* @param userId 用户ID
|
||||
* @return
|
||||
*/
|
||||
@AutoLog(value = "会话-解除禁言群聊成员")
|
||||
@Operation(summary = "解除禁言群聊成员", description = "解除指定群聊成员的禁言状态,设置iz_muted字段为0")
|
||||
@PostMapping(value = "/{chatId}/unmute_member/{userId}")
|
||||
public Result<String> unmuteMember(@PathVariable(value = "chatId") String chatId,
|
||||
@PathVariable(value = "userId") String userId) {
|
||||
try {
|
||||
return updateMemberSetting(chatId, userId, "iz_muted", 0, "解除禁言群聊成员");
|
||||
} catch (Exception e) {
|
||||
log.error("解除禁言群聊成员失败: chatId={}, userId={}, error={}", chatId, userId, e.getMessage(), e);
|
||||
return Result.error("解除禁言群聊成员失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 开启免打扰
|
||||
*
|
||||
* @param chatId 会话ID
|
||||
* @param userId 用户ID
|
||||
* @return
|
||||
*/
|
||||
@AutoLog(value = "会话-开启免打扰")
|
||||
@Operation(summary = "开启免打扰", description = "为指定用户开启群聊免打扰功能,设置iz_not_disturb字段为1")
|
||||
@PostMapping(value = "/{chatId}/enable_not_disturb/{userId}")
|
||||
public Result<String> enableNotDisturb(@PathVariable(value = "chatId") String chatId,
|
||||
@PathVariable(value = "userId") String userId) {
|
||||
try {
|
||||
return updateMemberSetting(chatId, userId, "iz_not_disturb", 1, "开启免打扰");
|
||||
} catch (Exception e) {
|
||||
log.error("开启免打扰失败: chatId={}, userId={}, error={}", chatId, userId, e.getMessage(), e);
|
||||
return Result.error("开启免打扰失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭免打扰
|
||||
*
|
||||
* @param chatId 会话ID
|
||||
* @param userId 用户ID
|
||||
* @return
|
||||
*/
|
||||
@AutoLog(value = "会话-关闭免打扰")
|
||||
@Operation(summary = "关闭免打扰", description = "为指定用户关闭群聊免打扰功能,设置iz_not_disturb字段为0")
|
||||
@PostMapping(value = "/{chatId}/disable_not_disturb/{userId}")
|
||||
public Result<String> disableNotDisturb(@PathVariable(value = "chatId") String chatId,
|
||||
@PathVariable(value = "userId") String userId) {
|
||||
try {
|
||||
return updateMemberSetting(chatId, userId, "iz_not_disturb", 0, "关闭免打扰");
|
||||
} catch (Exception e) {
|
||||
log.error("关闭免打扰失败: chatId={}, userId={}, error={}", chatId, userId, e.getMessage(), e);
|
||||
return Result.error("关闭免打扰失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 通用更新群聊成员设置的方法
|
||||
*
|
||||
* @param chatId 会话ID
|
||||
* @param userId 用户ID
|
||||
* @param fieldName 字段名
|
||||
* @param value 字段值
|
||||
* @param operationName 操作名称
|
||||
* @return
|
||||
*/
|
||||
private Result<String> updateMemberSetting(String chatId, String userId, String fieldName, Integer value, String operationName) {
|
||||
// 1. 查询群聊成员是否存在
|
||||
QueryWrapper<AiolChatMember> memberWrapper = new QueryWrapper<>();
|
||||
memberWrapper.eq("chat_id", chatId).eq("user_id", userId);
|
||||
AiolChatMember chatMember = aiolChatMemberMapper.selectOne(memberWrapper);
|
||||
|
||||
if (chatMember == null) {
|
||||
return Result.error("该用户不是群聊成员或会话不存在");
|
||||
}
|
||||
|
||||
// 2. 根据字段名设置相应的值
|
||||
if ("iz_muted".equals(fieldName)) {
|
||||
chatMember.setIzMuted(value);
|
||||
} else if ("iz_not_disturb".equals(fieldName)) {
|
||||
chatMember.setIzNotDisturb(value);
|
||||
} else {
|
||||
return Result.error("无效的字段名");
|
||||
}
|
||||
|
||||
// 3. 更新数据库
|
||||
boolean updated = aiolChatMemberMapper.updateById(chatMember) > 0;
|
||||
if (!updated) {
|
||||
return Result.error(operationName + "失败");
|
||||
}
|
||||
|
||||
log.info("{}成功: chatId={}, userId={}, {}={}", operationName, chatId, userId, fieldName, value);
|
||||
return Result.OK(operationName + "成功!");
|
||||
}
|
||||
|
||||
/**
|
||||
* 将AiolChat转换为包含未读消息数的DTO
|
||||
* @param chat 会话实体
|
||||
* @param chatMembers 会话成员列表
|
||||
* @param userId 当前用户ID
|
||||
* @return 包含未读消息数的DTO
|
||||
*/
|
||||
private ChatWithUnreadCountDTO convertToChatWithUnreadCount(AiolChat chat, List<AiolChatMember> chatMembers, String userId) {
|
||||
ChatWithUnreadCountDTO chatDTO = new ChatWithUnreadCountDTO();
|
||||
|
||||
// 复制基本属性
|
||||
chatDTO.setId(chat.getId());
|
||||
chatDTO.setType(chat.getType());
|
||||
chatDTO.setName(chat.getName());
|
||||
chatDTO.setAvatar(chat.getAvatar());
|
||||
chatDTO.setRefId(chat.getRefId());
|
||||
chatDTO.setIzAllMuted(chat.getIzAllMuted());
|
||||
chatDTO.setShowLabel(chat.getShowLabel());
|
||||
chatDTO.setCreateBy(chat.getCreateBy());
|
||||
chatDTO.setCreateTime(chat.getCreateTime());
|
||||
chatDTO.setUpdateBy(chat.getUpdateBy());
|
||||
chatDTO.setUpdateTime(chat.getUpdateTime());
|
||||
|
||||
try {
|
||||
// 1. 计算未读消息数
|
||||
AiolChatMember currentUserMember = chatMembers.stream()
|
||||
.filter(member -> member.getChatId().equals(chat.getId()) && member.getUserId().equals(userId))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
|
||||
int unreadCount = 0;
|
||||
if (currentUserMember != null) {
|
||||
String lastReadMsgId = currentUserMember.getLastReadMsgId();
|
||||
|
||||
// 查询该会话中last_read_msg_id之后的消息数量
|
||||
QueryWrapper<AiolChatMessage> messageWrapper = new QueryWrapper<>();
|
||||
messageWrapper.eq("chat_id", chat.getId());
|
||||
|
||||
if (lastReadMsgId != null && !lastReadMsgId.trim().isEmpty()) {
|
||||
// 如果有最后读取的消息ID,查询该消息之后的消息
|
||||
QueryWrapper<AiolChatMessage> lastReadMsgWrapper = new QueryWrapper<>();
|
||||
lastReadMsgWrapper.eq("chat_id", chat.getId()).eq("id", lastReadMsgId);
|
||||
AiolChatMessage lastReadMsg = aiolChatMessageMapper.selectOne(lastReadMsgWrapper);
|
||||
|
||||
if (lastReadMsg != null) {
|
||||
// 查询创建时间晚于最后读取消息的消息数量
|
||||
messageWrapper.gt("create_time", lastReadMsg.getCreateTime());
|
||||
}
|
||||
}
|
||||
|
||||
Long count = aiolChatMessageMapper.selectCount(messageWrapper);
|
||||
unreadCount = count != null ? count.intValue() : 0;
|
||||
}
|
||||
|
||||
chatDTO.setUnreadCount(unreadCount);
|
||||
|
||||
// 2. 处理私聊类型的会话,获取对方用户信息
|
||||
if (chat.getType() != null && chat.getType() == 0) {
|
||||
// 私聊类型,需要获取对方用户信息
|
||||
try {
|
||||
// 查询该会话的成员,排除当前用户
|
||||
QueryWrapper<AiolChatMember> otherMemberWrapper = new QueryWrapper<>();
|
||||
otherMemberWrapper.eq("chat_id", chat.getId())
|
||||
.ne("user_id", userId);
|
||||
List<AiolChatMember> otherMembers = aiolChatMemberMapper.selectList(otherMemberWrapper);
|
||||
|
||||
if (!otherMembers.isEmpty()) {
|
||||
// 获取对方用户ID
|
||||
String otherUserId = otherMembers.get(0).getUserId();
|
||||
|
||||
// 查询对方用户信息
|
||||
SysUser otherUser = sysUserMapper.selectById(otherUserId);
|
||||
if (otherUser != null) {
|
||||
// 替换会话的name和avatar为对方用户信息
|
||||
chatDTO.setName(otherUser.getRealname());
|
||||
chatDTO.setAvatar(otherUser.getAvatar());
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("获取私聊对方用户信息失败: chatId={}, error={}", chat.getId(), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("转换会话信息失败: chatId={}, error={}", chat.getId(), e.getMessage(), e);
|
||||
// 即使转换失败,也返回基本的会话信息
|
||||
chatDTO.setUnreadCount(0);
|
||||
}
|
||||
|
||||
return chatDTO;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新用户最后读取的消息ID
|
||||
*
|
||||
* @param chatId 会话ID
|
||||
* @param messageId 消息ID
|
||||
* @param request HTTP请求对象
|
||||
* @return
|
||||
*/
|
||||
@AutoLog(value = "会话-更新最后读取消息ID")
|
||||
@Operation(summary = "更新最后读取消息ID", description = "更新当前用户在指定会话中的最后读取消息ID")
|
||||
@PostMapping(value = "/{chatId}/update_last_read/{messageId}")
|
||||
public Result<String> updateLastReadMsgId(@PathVariable(value = "chatId") String chatId,
|
||||
@PathVariable(value = "messageId") String messageId,
|
||||
HttpServletRequest request) {
|
||||
try {
|
||||
// 1. 从token获取当前用户信息
|
||||
String token = request.getHeader(CommonConstant.X_ACCESS_TOKEN);
|
||||
if (token == null || token.trim().isEmpty()) {
|
||||
return Result.error("用户未登录");
|
||||
}
|
||||
|
||||
String username = JwtUtil.getUsername(token);
|
||||
LoginUser sysUser = sysBaseApi.getUserByName(username);
|
||||
|
||||
if (sysUser == null) {
|
||||
return Result.error("用户信息不存在");
|
||||
}
|
||||
|
||||
// 2. 查询群聊成员是否存在
|
||||
QueryWrapper<AiolChatMember> memberWrapper = new QueryWrapper<>();
|
||||
memberWrapper.eq("chat_id", chatId).eq("user_id", sysUser.getId());
|
||||
AiolChatMember chatMember = aiolChatMemberMapper.selectOne(memberWrapper);
|
||||
|
||||
if (chatMember == null) {
|
||||
return Result.error("该用户不是群聊成员或会话不存在");
|
||||
}
|
||||
|
||||
// 3. 验证消息是否存在
|
||||
AiolChatMessage message = aiolChatMessageMapper.selectById(messageId);
|
||||
if (message == null || !message.getChatId().equals(chatId)) {
|
||||
return Result.error("消息不存在或不属于该会话");
|
||||
}
|
||||
|
||||
// 4. 更新最后读取的消息ID
|
||||
chatMember.setLastReadMsgId(messageId);
|
||||
boolean updated = aiolChatMemberMapper.updateById(chatMember) > 0;
|
||||
|
||||
if (!updated) {
|
||||
return Result.error("更新失败");
|
||||
}
|
||||
|
||||
log.info("用户 {} 更新会话 {} 的最后读取消息ID为 {}", username, chatId, messageId);
|
||||
return Result.OK("更新成功!");
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("更新最后读取消息ID失败: chatId={}, messageId={}, error={}", chatId, messageId, e.getMessage(), e);
|
||||
return Result.error("更新失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 退出群聊
|
||||
*
|
||||
* @param chatId 会话ID
|
||||
* @param request HTTP请求对象
|
||||
* @return
|
||||
*/
|
||||
@AutoLog(value = "会话-退出群聊")
|
||||
@Operation(summary = "退出群聊", description = "当前用户退出指定的群聊会话,从aiol_chat_member表中删除用户记录")
|
||||
@DeleteMapping(value = "/{chatId}/exit")
|
||||
public Result<String> exitChat(@PathVariable(value = "chatId") String chatId,
|
||||
HttpServletRequest request) {
|
||||
try {
|
||||
// 1. 从token获取当前用户信息
|
||||
String token = request.getHeader(CommonConstant.X_ACCESS_TOKEN);
|
||||
if (token == null || token.trim().isEmpty()) {
|
||||
return Result.error("用户未登录");
|
||||
}
|
||||
|
||||
String username = JwtUtil.getUsername(token);
|
||||
LoginUser sysUser = sysBaseApi.getUserByName(username);
|
||||
|
||||
if (sysUser == null) {
|
||||
return Result.error("用户信息不存在");
|
||||
}
|
||||
|
||||
// 2. 验证会话是否存在
|
||||
AiolChat chat = aiolChatService.getById(chatId);
|
||||
if (chat == null) {
|
||||
return Result.error("会话不存在");
|
||||
}
|
||||
|
||||
// 3. 查询用户是否为该会话的成员
|
||||
QueryWrapper<AiolChatMember> memberWrapper = new QueryWrapper<>();
|
||||
memberWrapper.eq("chat_id", chatId).eq("user_id", sysUser.getId());
|
||||
AiolChatMember chatMember = aiolChatMemberMapper.selectOne(memberWrapper);
|
||||
|
||||
if (chatMember == null) {
|
||||
return Result.error("您不是该会话的成员");
|
||||
}
|
||||
|
||||
// 4. 检查是否为会话创建者(可选:不允许创建者退出)
|
||||
if (chat.getCreateBy() != null && chat.getCreateBy().equals(sysUser.getId())) {
|
||||
// 可选:如果创建者退出,需要转移创建者权限或不允许退出
|
||||
log.warn("会话创建者尝试退出群聊: chatId={}, userId={}", chatId, sysUser.getId());
|
||||
// 这里可以选择是否允许创建者退出,或者需要先转移权限
|
||||
// return Result.error("群聊创建者不能直接退出,请先转移群主权限");
|
||||
}
|
||||
|
||||
// 5. 从会话成员表中删除该用户
|
||||
boolean deleted = aiolChatMemberMapper.deleteById(chatMember.getId()) > 0;
|
||||
|
||||
if (!deleted) {
|
||||
return Result.error("退出群聊失败");
|
||||
}
|
||||
|
||||
// 6. 检查会话是否还有其他成员,如果没有则删除会话(可选)
|
||||
QueryWrapper<AiolChatMember> remainingMemberWrapper = new QueryWrapper<>();
|
||||
remainingMemberWrapper.eq("chat_id", chatId);
|
||||
long remainingMemberCount = aiolChatMemberMapper.selectCount(remainingMemberWrapper);
|
||||
|
||||
if (remainingMemberCount == 0) {
|
||||
// 如果没有其他成员了,删除会话
|
||||
aiolChatService.removeById(chatId);
|
||||
log.info("会话 {} 无成员,已自动删除", chatId);
|
||||
}
|
||||
|
||||
log.info("用户 {} 成功退出群聊 {}", username, chatId);
|
||||
return Result.OK("退出群聊成功!");
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("退出群聊失败: chatId={}, error={}", chatId, e.getMessage(), e);
|
||||
return Result.error("退出群聊失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,21 @@
|
||||
package org.jeecg.modules.aiol.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.jeecg.modules.aiol.entity.AiolChat;
|
||||
|
||||
/**
|
||||
* @Description: 会话详情DTO,包含未读消息数
|
||||
* @Author: jeecg-boot
|
||||
* @Date: 2025-01-16
|
||||
* @Version: V1.0
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Schema(description = "会话详情,包含未读消息数")
|
||||
public class ChatWithUnreadCountDTO extends AiolChat {
|
||||
|
||||
@Schema(description = "未读消息数")
|
||||
private Integer unreadCount;
|
||||
}
|
@ -60,7 +60,7 @@ public class AiolChatMember implements Serializable {
|
||||
/**最后已读消息id*/
|
||||
@Excel(name = "最后已读消息id", width = 15)
|
||||
@Schema(description = "最后已读消息id")
|
||||
private java.lang.Integer lastReadMsgId;
|
||||
private java.lang.String lastReadMsgId;
|
||||
/**创建人*/
|
||||
@Schema(description = "创建人")
|
||||
private java.lang.String createBy;
|
||||
|
Loading…
x
Reference in New Issue
Block a user