feat: 🎸 课程章节新增 编辑targetid参数 & 查询群聊用户增加返回字段 &新增发送消息接口

This commit is contained in:
GoCo 2025-09-22 20:07:09 +08:00
parent 61e35598b3
commit b13795a3b7
5 changed files with 444 additions and 332 deletions

View File

@ -1,5 +1,6 @@
package org.jeecg.modules.aiol.controller; package org.jeecg.modules.aiol.controller;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@ -33,6 +34,7 @@ import org.jeecg.modules.system.mapper.SysUserRoleMapper;
import org.jeecg.modules.aiol.constant.RoleConst; import org.jeecg.modules.aiol.constant.RoleConst;
import org.jeecg.modules.aiol.service.IAiolChatService; import org.jeecg.modules.aiol.service.IAiolChatService;
import org.jeecg.modules.system.entity.SysUser; import org.jeecg.modules.system.entity.SysUser;
import org.jeecg.modules.system.entity.SysUserRole;
import org.jeecg.modules.system.mapper.SysUserMapper; import org.jeecg.modules.system.mapper.SysUserMapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
@ -56,149 +58,149 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import org.jeecg.common.aspect.annotation.AutoLog; import org.jeecg.common.aspect.annotation.AutoLog;
import org.apache.shiro.authz.annotation.RequiresPermissions; import org.apache.shiro.authz.annotation.RequiresPermissions;
/**
/**
* @Description: 会话 * @Description: 会话
* @Author: jeecg-boot * @Author: jeecg-boot
* @Date: 2025-09-11 * @Date: 2025-09-11
* @Version: V1.0 * @Version: V1.0
*/ */
@Tag(name="会话") @Tag(name = "会话")
@RestController @RestController
@RequestMapping("/aiol/aiolChat") @RequestMapping("/aiol/aiolChat")
@Slf4j @Slf4j
public class AiolChatController extends JeecgController<AiolChat, IAiolChatService> { public class AiolChatController extends JeecgController<AiolChat, IAiolChatService> {
@Autowired @Autowired
private IAiolChatService aiolChatService; private IAiolChatService aiolChatService;
@Autowired
private AiolChatMemberMapper aiolChatMemberMapper;
@Autowired
private ISysBaseAPI sysBaseApi;
@Autowired
private SysUserMapper sysUserMapper;
@Autowired
private AiolChatMessageMapper aiolChatMessageMapper;
@Autowired
private AiolClassMapper aiolClassMapper;
@Autowired
private AiolClassStudentMapper aiolClassStudentMapper;
@Autowired
private SysUserRoleMapper sysUserRoleMapper;
/**
* 分页列表查询
*
* @param aiolChat
* @param pageNo
* @param pageSize
* @param req
* @return
*/
//@AutoLog(value = "会话-分页列表查询")
@Operation(summary="会话-分页列表查询")
@GetMapping(value = "/list")
public Result<IPage<AiolChat>> queryPageList(AiolChat aiolChat,
@RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
@RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
HttpServletRequest req) {
@Autowired
private AiolChatMemberMapper aiolChatMemberMapper;
QueryWrapper<AiolChat> queryWrapper = QueryGenerator.initQueryWrapper(aiolChat, req.getParameterMap()); @Autowired
Page<AiolChat> page = new Page<AiolChat>(pageNo, pageSize); private ISysBaseAPI sysBaseApi;
IPage<AiolChat> pageList = aiolChatService.page(page, queryWrapper);
return Result.OK(pageList);
}
/**
* 添加
*
* @param aiolChat
* @return
*/
@AutoLog(value = "会话-添加")
@Operation(summary="会话-添加")
@RequiresPermissions("aiol:aiol_chat:add")
@PostMapping(value = "/add")
public Result<String> add(@RequestBody AiolChat aiolChat) {
aiolChatService.save(aiolChat);
return Result.OK("添加成功!"); @Autowired
} private SysUserMapper sysUserMapper;
/** @Autowired
* 编辑 private AiolChatMessageMapper aiolChatMessageMapper;
*
* @param aiolChat @Autowired
* @return private AiolClassMapper aiolClassMapper;
*/
@AutoLog(value = "会话-编辑") @Autowired
@Operation(summary="会话-编辑") private AiolClassStudentMapper aiolClassStudentMapper;
@RequiresPermissions("aiol:aiol_chat:edit")
@RequestMapping(value = "/edit", method = {RequestMethod.PUT,RequestMethod.POST}) @Autowired
public Result<String> edit(@RequestBody AiolChat aiolChat) { private SysUserRoleMapper sysUserRoleMapper;
aiolChatService.updateById(aiolChat);
return Result.OK("编辑成功!");
}
/**
* 通过id删除
*
* @param id
* @return
*/
@AutoLog(value = "会话-通过id删除")
@Operation(summary="会话-通过id删除")
@RequiresPermissions("aiol:aiol_chat:delete")
@DeleteMapping(value = "/delete")
public Result<String> delete(@RequestParam(name="id",required=true) String id) {
aiolChatService.removeById(id);
return Result.OK("删除成功!");
}
/**
* 批量删除
*
* @param ids
* @return
*/
@AutoLog(value = "会话-批量删除")
@Operation(summary="会话-批量删除")
@RequiresPermissions("aiol:aiol_chat:deleteBatch")
@DeleteMapping(value = "/deleteBatch")
public Result<String> deleteBatch(@RequestParam(name="ids",required=true) String ids) {
this.aiolChatService.removeByIds(Arrays.asList(ids.split(",")));
return Result.OK("批量删除成功!");
}
/**
* 通过id查询
*
* @param id
* @return
*/
//@AutoLog(value = "会话-通过id查询")
@Operation(summary="会话-通过id查询")
@GetMapping(value = "/queryById")
public Result<AiolChat> queryById(@RequestParam(name="id",required=true) String id) {
AiolChat aiolChat = aiolChatService.getById(id);
if(aiolChat==null) {
return Result.error("未找到对应数据");
}
return Result.OK(aiolChat);
}
/** /**
* 导出excel * 分页列表查询
* *
* @param request * @param aiolChat
* @param aiolChat * @param pageNo
*/ * @param pageSize
* @param req
* @return
*/
// @AutoLog(value = "会话-分页列表查询")
@Operation(summary = "会话-分页列表查询")
@GetMapping(value = "/list")
public Result<IPage<AiolChat>> queryPageList(AiolChat aiolChat,
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
HttpServletRequest req) {
QueryWrapper<AiolChat> queryWrapper = QueryGenerator.initQueryWrapper(aiolChat, req.getParameterMap());
Page<AiolChat> page = new Page<AiolChat>(pageNo, pageSize);
IPage<AiolChat> pageList = aiolChatService.page(page, queryWrapper);
return Result.OK(pageList);
}
/**
* 添加
*
* @param aiolChat
* @return
*/
@AutoLog(value = "会话-添加")
@Operation(summary = "会话-添加")
@RequiresPermissions("aiol:aiol_chat:add")
@PostMapping(value = "/add")
public Result<String> add(@RequestBody AiolChat aiolChat) {
aiolChatService.save(aiolChat);
return Result.OK("添加成功!");
}
/**
* 编辑
*
* @param aiolChat
* @return
*/
@AutoLog(value = "会话-编辑")
@Operation(summary = "会话-编辑")
@RequiresPermissions("aiol:aiol_chat:edit")
@RequestMapping(value = "/edit", method = { RequestMethod.PUT, RequestMethod.POST })
public Result<String> edit(@RequestBody AiolChat aiolChat) {
aiolChatService.updateById(aiolChat);
return Result.OK("编辑成功!");
}
/**
* 通过id删除
*
* @param id
* @return
*/
@AutoLog(value = "会话-通过id删除")
@Operation(summary = "会话-通过id删除")
@RequiresPermissions("aiol:aiol_chat:delete")
@DeleteMapping(value = "/delete")
public Result<String> delete(@RequestParam(name = "id", required = true) String id) {
aiolChatService.removeById(id);
return Result.OK("删除成功!");
}
/**
* 批量删除
*
* @param ids
* @return
*/
@AutoLog(value = "会话-批量删除")
@Operation(summary = "会话-批量删除")
@RequiresPermissions("aiol:aiol_chat:deleteBatch")
@DeleteMapping(value = "/deleteBatch")
public Result<String> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
this.aiolChatService.removeByIds(Arrays.asList(ids.split(",")));
return Result.OK("批量删除成功!");
}
/**
* 通过id查询
*
* @param id
* @return
*/
// @AutoLog(value = "会话-通过id查询")
@Operation(summary = "会话-通过id查询")
@GetMapping(value = "/queryById")
public Result<AiolChat> queryById(@RequestParam(name = "id", required = true) String id) {
AiolChat aiolChat = aiolChatService.getById(id);
if (aiolChat == null) {
return Result.error("未找到对应数据");
}
return Result.OK(aiolChat);
}
/**
* 导出excel
*
* @param request
* @param aiolChat
*/
@RequiresPermissions("aiol:aiol_chat:exportXls") @RequiresPermissions("aiol:aiol_chat:exportXls")
@RequestMapping(value = "/exportXls") @RequestMapping(value = "/exportXls")
public ModelAndView exportXls(HttpServletRequest request, AiolChat aiolChat) { public ModelAndView exportXls(HttpServletRequest request, AiolChat aiolChat) {
@ -206,12 +208,12 @@ public class AiolChatController extends JeecgController<AiolChat, IAiolChatServi
} }
/** /**
* 通过excel导入数据 * 通过excel导入数据
* *
* @param request * @param request
* @param response * @param response
* @return * @return
*/ */
@RequiresPermissions("aiol:aiol_chat:importExcel") @RequiresPermissions("aiol:aiol_chat:importExcel")
@RequestMapping(value = "/importExcel", method = RequestMethod.POST) @RequestMapping(value = "/importExcel", method = RequestMethod.POST)
public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) { public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
@ -233,46 +235,46 @@ public class AiolChatController extends JeecgController<AiolChat, IAiolChatServi
if (token == null || token.trim().isEmpty()) { if (token == null || token.trim().isEmpty()) {
return Result.error("用户未登录"); return Result.error("用户未登录");
} }
String username = JwtUtil.getUsername(token); String username = JwtUtil.getUsername(token);
LoginUser sysUser = sysBaseApi.getUserByName(username); LoginUser sysUser = sysBaseApi.getUserByName(username);
if (sysUser == null) { if (sysUser == null) {
return Result.error("用户信息不存在"); return Result.error("用户信息不存在");
} }
// 2. 根据用户ID查询会话成员表获取chat_id列表和last_read_msg_id // 2. 根据用户ID查询会话成员表获取chat_id列表和last_read_msg_id
QueryWrapper<AiolChatMember> memberWrapper = new QueryWrapper<>(); QueryWrapper<AiolChatMember> memberWrapper = new QueryWrapper<>();
memberWrapper.eq("user_id", sysUser.getId()); memberWrapper.eq("user_id", sysUser.getId());
List<AiolChatMember> chatMembers = aiolChatMemberMapper.selectList(memberWrapper); List<AiolChatMember> chatMembers = aiolChatMemberMapper.selectList(memberWrapper);
if (chatMembers.isEmpty()) { if (chatMembers.isEmpty()) {
return Result.OK(new java.util.ArrayList<>()); return Result.OK(new java.util.ArrayList<>());
} }
// 3. 提取chat_id列表 // 3. 提取chat_id列表
List<String> chatIds = chatMembers.stream() List<String> chatIds = chatMembers.stream()
.map(AiolChatMember::getChatId) .map(AiolChatMember::getChatId)
.collect(Collectors.toList()); .collect(Collectors.toList());
// 4. 根据chat_id列表查询会话详情 // 4. 根据chat_id列表查询会话详情
QueryWrapper<AiolChat> chatWrapper = new QueryWrapper<>(); QueryWrapper<AiolChat> chatWrapper = new QueryWrapper<>();
chatWrapper.in("id", chatIds); chatWrapper.in("id", chatIds);
chatWrapper.orderByDesc("create_time"); chatWrapper.orderByDesc("create_time");
List<AiolChat> chatList = aiolChatService.list(chatWrapper); List<AiolChat> chatList = aiolChatService.list(chatWrapper);
// 5. 转换为包含未读消息数的DTO列表 // 5. 转换为包含未读消息数的DTO列表
List<ChatWithUnreadCountDTO> resultList = new java.util.ArrayList<>(); List<ChatWithUnreadCountDTO> resultList = new java.util.ArrayList<>();
for (AiolChat chat : chatList) { for (AiolChat chat : chatList) {
ChatWithUnreadCountDTO chatDTO = convertToChatWithUnreadCount(chat, chatMembers, sysUser.getId()); ChatWithUnreadCountDTO chatDTO = convertToChatWithUnreadCount(chat, chatMembers, sysUser.getId());
resultList.add(chatDTO); resultList.add(chatDTO);
} }
log.info("用户 {} 查询到 {} 个会话", username, resultList.size()); log.info("用户 {} 查询到 {} 个会话", username, resultList.size());
return Result.OK(resultList); return Result.OK(resultList);
} catch (Exception e) { } catch (Exception e) {
log.error("查询用户会话列表失败: {}", e.getMessage(), e); log.error("查询用户会话列表失败: {}", e.getMessage(), e);
return Result.error("查询会话列表失败: " + e.getMessage()); return Result.error("查询会话列表失败: " + e.getMessage());
@ -293,62 +295,75 @@ public class AiolChatController extends JeecgController<AiolChat, IAiolChatServi
QueryWrapper<AiolChatMember> memberWrapper = new QueryWrapper<>(); QueryWrapper<AiolChatMember> memberWrapper = new QueryWrapper<>();
memberWrapper.eq("chat_id", chatId); memberWrapper.eq("chat_id", chatId);
List<AiolChatMember> chatMembers = aiolChatMemberMapper.selectList(memberWrapper); List<AiolChatMember> chatMembers = aiolChatMemberMapper.selectList(memberWrapper);
if (chatMembers.isEmpty()) { if (chatMembers.isEmpty()) {
return Result.OK(new java.util.ArrayList<>()); return Result.OK(new java.util.ArrayList<>());
} }
// 将成员列表按userId建立映射便于取出member相关字段
Map<String, AiolChatMember> userIdToMemberMap = chatMembers.stream()
.collect(Collectors.toMap(AiolChatMember::getUserId, m -> m, (a, b) -> a));
// 2. 提取用户ID列表 // 2. 提取用户ID列表
List<String> userIds = chatMembers.stream() List<String> userIds = chatMembers.stream()
.map(AiolChatMember::getUserId) .map(AiolChatMember::getUserId)
.collect(Collectors.toList()); .collect(Collectors.toList());
// 3. 查询用户信息 // 3. 查询用户信息
List<SysUser> userList = sysUserMapper.selectByIds(userIds); List<SysUser> userList = sysUserMapper.selectByIds(userIds);
// 4. 查询所有用户的教师角色身份 // 4. 查询所有用户的教师角色身份
Map<String, Boolean> teacherStatusMap = new java.util.HashMap<>(); Map<String, Boolean> teacherStatusMap = new HashMap<>();
if (!userIds.isEmpty()) { if (!userIds.isEmpty()) {
try { try {
QueryWrapper<org.jeecg.modules.system.entity.SysUserRole> roleWrapper = new QueryWrapper<>(); QueryWrapper<SysUserRole> roleWrapper = new QueryWrapper<>();
roleWrapper.eq("role_id", RoleConst.TEACHER_ROLE_ID) roleWrapper.eq("role_id", RoleConst.TEACHER_ROLE_ID)
.in("user_id", userIds); .in("user_id", userIds);
List<org.jeecg.modules.system.entity.SysUserRole> teacherRoleList = sysUserRoleMapper.selectList(roleWrapper); List<SysUserRole> teacherRoleList = sysUserRoleMapper.selectList(roleWrapper);
// 构建教师身份映射 // 构建教师身份映射
for (org.jeecg.modules.system.entity.SysUserRole userRole : teacherRoleList) { for (SysUserRole userRole : teacherRoleList) {
teacherStatusMap.put(userRole.getUserId(), true); teacherStatusMap.put(userRole.getUserId(), true);
} }
} catch (Exception e) { } catch (Exception e) {
log.warn("查询教师角色身份失败: error={}", e.getMessage()); log.warn("查询教师角色身份失败: error={}", e.getMessage());
} }
} }
// 5. 构建返回结果 // 5. 构建返回结果
List<Map<String, Object>> result = new java.util.ArrayList<>(); List<Map<String, Object>> result = new ArrayList<>();
for (SysUser user : userList) { for (SysUser user : userList) {
Map<String, Object> memberInfo = new java.util.HashMap<>(); Map<String, Object> memberInfo = new HashMap<>();
memberInfo.put("id", user.getId()); memberInfo.put("id", user.getId());
memberInfo.put("realname", user.getRealname()); memberInfo.put("realname", user.getRealname());
memberInfo.put("avatar", user.getAvatar()); memberInfo.put("avatar", user.getAvatar());
// 添加教师身份标记 // 添加教师身份标记
boolean isTeacher = teacherStatusMap.getOrDefault(user.getId(), false); boolean isTeacher = teacherStatusMap.getOrDefault(user.getId(), false);
memberInfo.put("isTeacher", isTeacher); memberInfo.put("isTeacher", isTeacher);
// 可选添加更多用户信息 // 可选添加更多用户信息
memberInfo.put("username", user.getUsername()); memberInfo.put("username", user.getUsername());
memberInfo.put("phone", user.getPhone()); memberInfo.put("phone", user.getPhone());
memberInfo.put("email", user.getEmail()); memberInfo.put("email", user.getEmail());
memberInfo.put("sex", user.getSex()); memberInfo.put("sex", user.getSex());
// 新增返回aiol_chat_member表中的角色与设置字段
AiolChatMember member = userIdToMemberMap.get(user.getId());
if (member != null) {
memberInfo.put("role", member.getRole());
memberInfo.put("izMuted", member.getIzMuted());
memberInfo.put("izNotDisturb", member.getIzNotDisturb());
memberInfo.put("lastReadMsgId", member.getLastReadMsgId());
}
result.add(memberInfo); result.add(memberInfo);
} }
log.info("查询会话 {} 的成员列表,共 {} 个成员", chatId, result.size()); log.info("查询会话 {} 的成员列表,共 {} 个成员", chatId, result.size());
return Result.OK(result); return Result.OK(result);
} catch (Exception e) { } catch (Exception e) {
log.error("查询会话成员列表失败: chatId={}, error={}", chatId, e.getMessage(), e); log.error("查询会话成员列表失败: chatId={}, error={}", chatId, e.getMessage(), e);
return Result.error("查询会话成员列表失败: " + e.getMessage()); return Result.error("查询会话成员列表失败: " + e.getMessage());
@ -358,8 +373,8 @@ public class AiolChatController extends JeecgController<AiolChat, IAiolChatServi
/** /**
* 查询会话消息列表 * 查询会话消息列表
* *
* @param chatId 会话ID * @param chatId 会话ID
* @param pageNo 页码 * @param pageNo 页码
* @param pageSize 每页大小 * @param pageSize 每页大小
* @return * @return
*/ */
@ -372,29 +387,29 @@ public class AiolChatController extends JeecgController<AiolChat, IAiolChatServi
QueryWrapper<AiolChatMessage> messageWrapper = new QueryWrapper<>(); QueryWrapper<AiolChatMessage> messageWrapper = new QueryWrapper<>();
messageWrapper.eq("chat_id", chatId); messageWrapper.eq("chat_id", chatId);
messageWrapper.orderByDesc("create_time"); messageWrapper.orderByDesc("create_time");
List<AiolChatMessage> messageList = aiolChatMessageMapper.selectList(messageWrapper); List<AiolChatMessage> messageList = aiolChatMessageMapper.selectList(messageWrapper);
if (messageList.isEmpty()) { if (messageList.isEmpty()) {
return Result.OK(new java.util.ArrayList<>()); return Result.OK(new java.util.ArrayList<>());
} }
// 2. 提取发送者ID列表 // 2. 提取发送者ID列表
List<String> senderIds = messageList.stream() List<String> senderIds = messageList.stream()
.map(AiolChatMessage::getSenderId) .map(AiolChatMessage::getSenderId)
.distinct() .distinct()
.collect(Collectors.toList()); .collect(Collectors.toList());
// 3. 查询发送者信息 // 3. 查询发送者信息
List<SysUser> senderList = sysUserMapper.selectByIds(senderIds); List<SysUser> senderList = sysUserMapper.selectByIds(senderIds);
Map<String, SysUser> senderMap = senderList.stream() Map<String, SysUser> senderMap = senderList.stream()
.collect(Collectors.toMap(SysUser::getId, user -> user)); .collect(Collectors.toMap(SysUser::getId, user -> user));
// 4. 构建返回结果包含发送者信息 // 4. 构建返回结果包含发送者信息
List<Map<String, Object>> result = new java.util.ArrayList<>(); List<Map<String, Object>> result = new java.util.ArrayList<>();
for (AiolChatMessage message : messageList) { for (AiolChatMessage message : messageList) {
Map<String, Object> messageInfo = new java.util.HashMap<>(); Map<String, Object> messageInfo = new java.util.HashMap<>();
// 添加消息基本信息 // 添加消息基本信息
messageInfo.put("id", message.getId()); messageInfo.put("id", message.getId());
messageInfo.put("chatId", message.getChatId()); messageInfo.put("chatId", message.getChatId());
@ -406,32 +421,36 @@ public class AiolChatController extends JeecgController<AiolChat, IAiolChatServi
messageInfo.put("fileName", message.getFileName()); messageInfo.put("fileName", message.getFileName());
messageInfo.put("fileSize", message.getFileSize()); messageInfo.put("fileSize", message.getFileSize());
messageInfo.put("createTime", message.getCreateTime()); messageInfo.put("createTime", message.getCreateTime());
// 添加发送者信息 // 添加发送者信息
SysUser sender = senderMap.get(message.getSenderId()); SysUser sender = senderMap.get(message.getSenderId());
if (sender != null) { if (sender != null) {
messageInfo.put("senderInfo", new java.util.HashMap<String, Object>() {{ messageInfo.put("senderInfo", new java.util.HashMap<String, Object>() {
put("id", sender.getId()); {
put("realname", sender.getRealname()); put("id", sender.getId());
put("avatar", sender.getAvatar()); put("realname", sender.getRealname());
put("username", sender.getUsername()); put("avatar", sender.getAvatar());
}}); put("username", sender.getUsername());
}
});
} else { } else {
// 如果找不到发送者信息设置默认值 // 如果找不到发送者信息设置默认值
messageInfo.put("senderInfo", new java.util.HashMap<String, Object>() {{ messageInfo.put("senderInfo", new java.util.HashMap<String, Object>() {
put("id", message.getSenderId()); {
put("realname", "未知用户"); put("id", message.getSenderId());
put("avatar", ""); put("realname", "未知用户");
put("username", ""); put("avatar", "");
}}); put("username", "");
}
});
} }
result.add(messageInfo); result.add(messageInfo);
} }
log.info("查询会话 {} 的消息列表,共 {} 条消息", chatId, result.size()); log.info("查询会话 {} 的消息列表,共 {} 条消息", chatId, result.size());
return Result.OK(result); return Result.OK(result);
} catch (Exception e) { } catch (Exception e) {
log.error("查询会话消息列表失败: chatId={}, error={}", chatId, e.getMessage(), e); log.error("查询会话消息列表失败: chatId={}, error={}", chatId, e.getMessage(), e);
return Result.error("查询会话消息列表失败: " + e.getMessage()); return Result.error("查询会话消息列表失败: " + e.getMessage());
@ -453,7 +472,7 @@ public class AiolChatController extends JeecgController<AiolChat, IAiolChatServi
if (chat == null) { if (chat == null) {
return Result.error("会话不存在"); return Result.error("会话不存在");
} }
// 2. 构建返回结果 // 2. 构建返回结果
Map<String, Object> result = new java.util.HashMap<>(); Map<String, Object> result = new java.util.HashMap<>();
result.put("id", chat.getId()); result.put("id", chat.getId());
@ -467,7 +486,7 @@ public class AiolChatController extends JeecgController<AiolChat, IAiolChatServi
result.put("createTime", chat.getCreateTime()); result.put("createTime", chat.getCreateTime());
result.put("updateBy", chat.getUpdateBy()); result.put("updateBy", chat.getUpdateBy());
result.put("updateTime", chat.getUpdateTime()); result.put("updateTime", chat.getUpdateTime());
// 3. 如果是群聊类型type==1查询班级信息 // 3. 如果是群聊类型type==1查询班级信息
if (chat.getType() != null && chat.getType() == 1 && chat.getRefId() != null) { if (chat.getType() != null && chat.getType() == 1 && chat.getRefId() != null) {
try { try {
@ -481,30 +500,30 @@ public class AiolChatController extends JeecgController<AiolChat, IAiolChatServi
classInfo.put("inviteCode", aiolClass.getInviteCode()); classInfo.put("inviteCode", aiolClass.getInviteCode());
classInfo.put("createBy", aiolClass.getCreateBy()); classInfo.put("createBy", aiolClass.getCreateBy());
classInfo.put("createTime", aiolClass.getCreateTime()); classInfo.put("createTime", aiolClass.getCreateTime());
// 查询班级人数 // 查询班级人数
QueryWrapper<AiolClassStudent> studentWrapper = new QueryWrapper<>(); QueryWrapper<AiolClassStudent> studentWrapper = new QueryWrapper<>();
studentWrapper.eq("class_id", aiolClass.getId()); studentWrapper.eq("class_id", aiolClass.getId());
long studentCount = aiolClassStudentMapper.selectCount(studentWrapper); long studentCount = aiolClassStudentMapper.selectCount(studentWrapper);
classInfo.put("studentCount", studentCount); classInfo.put("studentCount", studentCount);
result.put("classInfo", classInfo); result.put("classInfo", classInfo);
} else { } else {
log.warn("群聊会话 {} 关联的班级 {} 不存在", chatId, chat.getRefId()); log.warn("群聊会话 {} 关联的班级 {} 不存在", chatId, chat.getRefId());
result.put("classInfo", null); result.put("classInfo", null);
} }
} catch (Exception e) { } catch (Exception e) {
log.error("查询群聊班级信息失败: chatId={}, refId={}, error={}", log.error("查询群聊班级信息失败: chatId={}, refId={}, error={}",
chatId, chat.getRefId(), e.getMessage(), e); chatId, chat.getRefId(), e.getMessage(), e);
result.put("classInfo", null); result.put("classInfo", null);
} }
} else { } else {
result.put("classInfo", null); result.put("classInfo", null);
} }
log.info("查询会话详情成功: chatId={}, type={}", chatId, chat.getType()); log.info("查询会话详情成功: chatId={}, type={}", chatId, chat.getType());
return Result.OK(result); return Result.OK(result);
} catch (Exception e) { } catch (Exception e) {
log.error("查询会话详情失败: chatId={}, error={}", chatId, e.getMessage(), e); log.error("查询会话详情失败: chatId={}, error={}", chatId, e.getMessage(), e);
return Result.error("查询会话详情失败: " + e.getMessage()); return Result.error("查询会话详情失败: " + e.getMessage());
@ -586,9 +605,9 @@ public class AiolChatController extends JeecgController<AiolChat, IAiolChatServi
/** /**
* 通用更新会话设置的方法 * 通用更新会话设置的方法
* *
* @param chatId 会话ID * @param chatId 会话ID
* @param fieldName 字段名 * @param fieldName 字段名
* @param value 字段值 * @param value 字段值
* @param operationName 操作名称 * @param operationName 操作名称
* @return * @return
*/ */
@ -628,8 +647,8 @@ public class AiolChatController extends JeecgController<AiolChat, IAiolChatServi
@AutoLog(value = "会话-禁言群聊成员") @AutoLog(value = "会话-禁言群聊成员")
@Operation(summary = "禁言群聊成员", description = "禁言指定群聊成员设置iz_muted字段为1") @Operation(summary = "禁言群聊成员", description = "禁言指定群聊成员设置iz_muted字段为1")
@PostMapping(value = "/{chatId}/mute_member/{userId}") @PostMapping(value = "/{chatId}/mute_member/{userId}")
public Result<String> muteMember(@PathVariable(value = "chatId") String chatId, public Result<String> muteMember(@PathVariable(value = "chatId") String chatId,
@PathVariable(value = "userId") String userId) { @PathVariable(value = "userId") String userId) {
try { try {
return updateMemberSetting(chatId, userId, "iz_muted", 1, "禁言群聊成员"); return updateMemberSetting(chatId, userId, "iz_muted", 1, "禁言群聊成员");
} catch (Exception e) { } catch (Exception e) {
@ -648,8 +667,8 @@ public class AiolChatController extends JeecgController<AiolChat, IAiolChatServi
@AutoLog(value = "会话-解除禁言群聊成员") @AutoLog(value = "会话-解除禁言群聊成员")
@Operation(summary = "解除禁言群聊成员", description = "解除指定群聊成员的禁言状态设置iz_muted字段为0") @Operation(summary = "解除禁言群聊成员", description = "解除指定群聊成员的禁言状态设置iz_muted字段为0")
@PostMapping(value = "/{chatId}/unmute_member/{userId}") @PostMapping(value = "/{chatId}/unmute_member/{userId}")
public Result<String> unmuteMember(@PathVariable(value = "chatId") String chatId, public Result<String> unmuteMember(@PathVariable(value = "chatId") String chatId,
@PathVariable(value = "userId") String userId) { @PathVariable(value = "userId") String userId) {
try { try {
return updateMemberSetting(chatId, userId, "iz_muted", 0, "解除禁言群聊成员"); return updateMemberSetting(chatId, userId, "iz_muted", 0, "解除禁言群聊成员");
} catch (Exception e) { } catch (Exception e) {
@ -668,8 +687,8 @@ public class AiolChatController extends JeecgController<AiolChat, IAiolChatServi
@AutoLog(value = "会话-开启免打扰") @AutoLog(value = "会话-开启免打扰")
@Operation(summary = "开启免打扰", description = "为指定用户开启群聊免打扰功能设置iz_not_disturb字段为1") @Operation(summary = "开启免打扰", description = "为指定用户开启群聊免打扰功能设置iz_not_disturb字段为1")
@PostMapping(value = "/{chatId}/enable_not_disturb/{userId}") @PostMapping(value = "/{chatId}/enable_not_disturb/{userId}")
public Result<String> enableNotDisturb(@PathVariable(value = "chatId") String chatId, public Result<String> enableNotDisturb(@PathVariable(value = "chatId") String chatId,
@PathVariable(value = "userId") String userId) { @PathVariable(value = "userId") String userId) {
try { try {
return updateMemberSetting(chatId, userId, "iz_not_disturb", 1, "开启免打扰"); return updateMemberSetting(chatId, userId, "iz_not_disturb", 1, "开启免打扰");
} catch (Exception e) { } catch (Exception e) {
@ -688,8 +707,8 @@ public class AiolChatController extends JeecgController<AiolChat, IAiolChatServi
@AutoLog(value = "会话-关闭免打扰") @AutoLog(value = "会话-关闭免打扰")
@Operation(summary = "关闭免打扰", description = "为指定用户关闭群聊免打扰功能设置iz_not_disturb字段为0") @Operation(summary = "关闭免打扰", description = "为指定用户关闭群聊免打扰功能设置iz_not_disturb字段为0")
@PostMapping(value = "/{chatId}/disable_not_disturb/{userId}") @PostMapping(value = "/{chatId}/disable_not_disturb/{userId}")
public Result<String> disableNotDisturb(@PathVariable(value = "chatId") String chatId, public Result<String> disableNotDisturb(@PathVariable(value = "chatId") String chatId,
@PathVariable(value = "userId") String userId) { @PathVariable(value = "userId") String userId) {
try { try {
return updateMemberSetting(chatId, userId, "iz_not_disturb", 0, "关闭免打扰"); return updateMemberSetting(chatId, userId, "iz_not_disturb", 0, "关闭免打扰");
} catch (Exception e) { } catch (Exception e) {
@ -701,19 +720,20 @@ public class AiolChatController extends JeecgController<AiolChat, IAiolChatServi
/** /**
* 通用更新群聊成员设置的方法 * 通用更新群聊成员设置的方法
* *
* @param chatId 会话ID * @param chatId 会话ID
* @param userId 用户ID * @param userId 用户ID
* @param fieldName 字段名 * @param fieldName 字段名
* @param value 字段值 * @param value 字段值
* @param operationName 操作名称 * @param operationName 操作名称
* @return * @return
*/ */
private Result<String> updateMemberSetting(String chatId, String userId, String fieldName, Integer value, String operationName) { private Result<String> updateMemberSetting(String chatId, String userId, String fieldName, Integer value,
String operationName) {
// 1. 查询群聊成员是否存在 // 1. 查询群聊成员是否存在
QueryWrapper<AiolChatMember> memberWrapper = new QueryWrapper<>(); QueryWrapper<AiolChatMember> memberWrapper = new QueryWrapper<>();
memberWrapper.eq("chat_id", chatId).eq("user_id", userId); memberWrapper.eq("chat_id", chatId).eq("user_id", userId);
AiolChatMember chatMember = aiolChatMemberMapper.selectOne(memberWrapper); AiolChatMember chatMember = aiolChatMemberMapper.selectOne(memberWrapper);
if (chatMember == null) { if (chatMember == null) {
return Result.error("该用户不是群聊成员或会话不存在"); return Result.error("该用户不是群聊成员或会话不存在");
} }
@ -739,14 +759,16 @@ public class AiolChatController extends JeecgController<AiolChat, IAiolChatServi
/** /**
* 将AiolChat转换为包含未读消息数的DTO * 将AiolChat转换为包含未读消息数的DTO
* @param chat 会话实体 *
* @param chat 会话实体
* @param chatMembers 会话成员列表 * @param chatMembers 会话成员列表
* @param userId 当前用户ID * @param userId 当前用户ID
* @return 包含未读消息数的DTO * @return 包含未读消息数的DTO
*/ */
private ChatWithUnreadCountDTO convertToChatWithUnreadCount(AiolChat chat, List<AiolChatMember> chatMembers, String userId) { private ChatWithUnreadCountDTO convertToChatWithUnreadCount(AiolChat chat, List<AiolChatMember> chatMembers,
String userId) {
ChatWithUnreadCountDTO chatDTO = new ChatWithUnreadCountDTO(); ChatWithUnreadCountDTO chatDTO = new ChatWithUnreadCountDTO();
// 复制基本属性 // 复制基本属性
chatDTO.setId(chat.getId()); chatDTO.setId(chat.getId());
chatDTO.setType(chat.getType()); chatDTO.setType(chat.getType());
@ -759,40 +781,40 @@ public class AiolChatController extends JeecgController<AiolChat, IAiolChatServi
chatDTO.setCreateTime(chat.getCreateTime()); chatDTO.setCreateTime(chat.getCreateTime());
chatDTO.setUpdateBy(chat.getUpdateBy()); chatDTO.setUpdateBy(chat.getUpdateBy());
chatDTO.setUpdateTime(chat.getUpdateTime()); chatDTO.setUpdateTime(chat.getUpdateTime());
try { try {
// 1. 计算未读消息数 // 1. 计算未读消息数
AiolChatMember currentUserMember = chatMembers.stream() AiolChatMember currentUserMember = chatMembers.stream()
.filter(member -> member.getChatId().equals(chat.getId()) && member.getUserId().equals(userId)) .filter(member -> member.getChatId().equals(chat.getId()) && member.getUserId().equals(userId))
.findFirst() .findFirst()
.orElse(null); .orElse(null);
int unreadCount = 0; int unreadCount = 0;
if (currentUserMember != null) { if (currentUserMember != null) {
String lastReadMsgId = currentUserMember.getLastReadMsgId(); String lastReadMsgId = currentUserMember.getLastReadMsgId();
// 查询该会话中last_read_msg_id之后的消息数量 // 查询该会话中last_read_msg_id之后的消息数量
QueryWrapper<AiolChatMessage> messageWrapper = new QueryWrapper<>(); QueryWrapper<AiolChatMessage> messageWrapper = new QueryWrapper<>();
messageWrapper.eq("chat_id", chat.getId()); messageWrapper.eq("chat_id", chat.getId());
if (lastReadMsgId != null && !lastReadMsgId.trim().isEmpty()) { if (lastReadMsgId != null && !lastReadMsgId.trim().isEmpty()) {
// 如果有最后读取的消息ID查询该消息之后的消息 // 如果有最后读取的消息ID查询该消息之后的消息
QueryWrapper<AiolChatMessage> lastReadMsgWrapper = new QueryWrapper<>(); QueryWrapper<AiolChatMessage> lastReadMsgWrapper = new QueryWrapper<>();
lastReadMsgWrapper.eq("chat_id", chat.getId()).eq("id", lastReadMsgId); lastReadMsgWrapper.eq("chat_id", chat.getId()).eq("id", lastReadMsgId);
AiolChatMessage lastReadMsg = aiolChatMessageMapper.selectOne(lastReadMsgWrapper); AiolChatMessage lastReadMsg = aiolChatMessageMapper.selectOne(lastReadMsgWrapper);
if (lastReadMsg != null) { if (lastReadMsg != null) {
// 查询创建时间晚于最后读取消息的消息数量 // 查询创建时间晚于最后读取消息的消息数量
messageWrapper.gt("create_time", lastReadMsg.getCreateTime()); messageWrapper.gt("create_time", lastReadMsg.getCreateTime());
} }
} }
Long count = aiolChatMessageMapper.selectCount(messageWrapper); Long count = aiolChatMessageMapper.selectCount(messageWrapper);
unreadCount = count != null ? count.intValue() : 0; unreadCount = count != null ? count.intValue() : 0;
} }
chatDTO.setUnreadCount(unreadCount); chatDTO.setUnreadCount(unreadCount);
// 2. 处理私聊类型的会话获取对方用户信息 // 2. 处理私聊类型的会话获取对方用户信息
if (chat.getType() != null && chat.getType() == 0) { if (chat.getType() != null && chat.getType() == 0) {
// 私聊类型需要获取对方用户信息 // 私聊类型需要获取对方用户信息
@ -800,13 +822,13 @@ public class AiolChatController extends JeecgController<AiolChat, IAiolChatServi
// 查询该会话的成员排除当前用户 // 查询该会话的成员排除当前用户
QueryWrapper<AiolChatMember> otherMemberWrapper = new QueryWrapper<>(); QueryWrapper<AiolChatMember> otherMemberWrapper = new QueryWrapper<>();
otherMemberWrapper.eq("chat_id", chat.getId()) otherMemberWrapper.eq("chat_id", chat.getId())
.ne("user_id", userId); .ne("user_id", userId);
List<AiolChatMember> otherMembers = aiolChatMemberMapper.selectList(otherMemberWrapper); List<AiolChatMember> otherMembers = aiolChatMemberMapper.selectList(otherMemberWrapper);
if (!otherMembers.isEmpty()) { if (!otherMembers.isEmpty()) {
// 获取对方用户ID // 获取对方用户ID
String otherUserId = otherMembers.get(0).getUserId(); String otherUserId = otherMembers.get(0).getUserId();
// 查询对方用户信息 // 查询对方用户信息
SysUser otherUser = sysUserMapper.selectById(otherUserId); SysUser otherUser = sysUserMapper.selectById(otherUserId);
if (otherUser != null) { if (otherUser != null) {
@ -819,70 +841,70 @@ public class AiolChatController extends JeecgController<AiolChat, IAiolChatServi
log.warn("获取私聊对方用户信息失败: chatId={}, error={}", chat.getId(), e.getMessage()); log.warn("获取私聊对方用户信息失败: chatId={}, error={}", chat.getId(), e.getMessage());
} }
} }
} catch (Exception e) { } catch (Exception e) {
log.error("转换会话信息失败: chatId={}, error={}", chat.getId(), e.getMessage(), e); log.error("转换会话信息失败: chatId={}, error={}", chat.getId(), e.getMessage(), e);
// 即使转换失败也返回基本的会话信息 // 即使转换失败也返回基本的会话信息
chatDTO.setUnreadCount(0); chatDTO.setUnreadCount(0);
} }
return chatDTO; return chatDTO;
} }
/** /**
* 更新用户最后读取的消息ID * 更新用户最后读取的消息ID
* *
* @param chatId 会话ID * @param chatId 会话ID
* @param messageId 消息ID * @param messageId 消息ID
* @param request HTTP请求对象 * @param request HTTP请求对象
* @return * @return
*/ */
@AutoLog(value = "会话-更新最后读取消息ID") @AutoLog(value = "会话-更新最后读取消息ID")
@Operation(summary = "更新最后读取消息ID", description = "更新当前用户在指定会话中的最后读取消息ID") @Operation(summary = "更新最后读取消息ID", description = "更新当前用户在指定会话中的最后读取消息ID")
@PostMapping(value = "/{chatId}/update_last_read/{messageId}") @PostMapping(value = "/{chatId}/update_last_read/{messageId}")
public Result<String> updateLastReadMsgId(@PathVariable(value = "chatId") String chatId, public Result<String> updateLastReadMsgId(@PathVariable(value = "chatId") String chatId,
@PathVariable(value = "messageId") String messageId, @PathVariable(value = "messageId") String messageId,
HttpServletRequest request) { HttpServletRequest request) {
try { try {
// 1. 从token获取当前用户信息 // 1. 从token获取当前用户信息
String token = request.getHeader(CommonConstant.X_ACCESS_TOKEN); String token = request.getHeader(CommonConstant.X_ACCESS_TOKEN);
if (token == null || token.trim().isEmpty()) { if (token == null || token.trim().isEmpty()) {
return Result.error("用户未登录"); return Result.error("用户未登录");
} }
String username = JwtUtil.getUsername(token); String username = JwtUtil.getUsername(token);
LoginUser sysUser = sysBaseApi.getUserByName(username); LoginUser sysUser = sysBaseApi.getUserByName(username);
if (sysUser == null) { if (sysUser == null) {
return Result.error("用户信息不存在"); return Result.error("用户信息不存在");
} }
// 2. 查询群聊成员是否存在 // 2. 查询群聊成员是否存在
QueryWrapper<AiolChatMember> memberWrapper = new QueryWrapper<>(); QueryWrapper<AiolChatMember> memberWrapper = new QueryWrapper<>();
memberWrapper.eq("chat_id", chatId).eq("user_id", sysUser.getId()); memberWrapper.eq("chat_id", chatId).eq("user_id", sysUser.getId());
AiolChatMember chatMember = aiolChatMemberMapper.selectOne(memberWrapper); AiolChatMember chatMember = aiolChatMemberMapper.selectOne(memberWrapper);
if (chatMember == null) { if (chatMember == null) {
return Result.error("该用户不是群聊成员或会话不存在"); return Result.error("该用户不是群聊成员或会话不存在");
} }
// 3. 验证消息是否存在 // 3. 验证消息是否存在
AiolChatMessage message = aiolChatMessageMapper.selectById(messageId); AiolChatMessage message = aiolChatMessageMapper.selectById(messageId);
if (message == null || !message.getChatId().equals(chatId)) { if (message == null || !message.getChatId().equals(chatId)) {
return Result.error("消息不存在或不属于该会话"); return Result.error("消息不存在或不属于该会话");
} }
// 4. 更新最后读取的消息ID // 4. 更新最后读取的消息ID
chatMember.setLastReadMsgId(messageId); chatMember.setLastReadMsgId(messageId);
boolean updated = aiolChatMemberMapper.updateById(chatMember) > 0; boolean updated = aiolChatMemberMapper.updateById(chatMember) > 0;
if (!updated) { if (!updated) {
return Result.error("更新失败"); return Result.error("更新失败");
} }
log.info("用户 {} 更新会话 {} 的最后读取消息ID为 {}", username, chatId, messageId); log.info("用户 {} 更新会话 {} 的最后读取消息ID为 {}", username, chatId, messageId);
return Result.OK("更新成功!"); return Result.OK("更新成功!");
} catch (Exception e) { } catch (Exception e) {
log.error("更新最后读取消息ID失败: chatId={}, messageId={}, error={}", chatId, messageId, e.getMessage(), e); log.error("更新最后读取消息ID失败: chatId={}, messageId={}, error={}", chatId, messageId, e.getMessage(), e);
return Result.error("更新失败: " + e.getMessage()); return Result.error("更新失败: " + e.getMessage());
@ -892,7 +914,7 @@ public class AiolChatController extends JeecgController<AiolChat, IAiolChatServi
/** /**
* 退出群聊 * 退出群聊
* *
* @param chatId 会话ID * @param chatId 会话ID
* @param request HTTP请求对象 * @param request HTTP请求对象
* @return * @return
*/ */
@ -900,36 +922,36 @@ public class AiolChatController extends JeecgController<AiolChat, IAiolChatServi
@Operation(summary = "退出群聊", description = "当前用户退出指定的群聊会话从aiol_chat_member表中删除用户记录") @Operation(summary = "退出群聊", description = "当前用户退出指定的群聊会话从aiol_chat_member表中删除用户记录")
@DeleteMapping(value = "/{chatId}/exit") @DeleteMapping(value = "/{chatId}/exit")
public Result<String> exitChat(@PathVariable(value = "chatId") String chatId, public Result<String> exitChat(@PathVariable(value = "chatId") String chatId,
HttpServletRequest request) { HttpServletRequest request) {
try { try {
// 1. 从token获取当前用户信息 // 1. 从token获取当前用户信息
String token = request.getHeader(CommonConstant.X_ACCESS_TOKEN); String token = request.getHeader(CommonConstant.X_ACCESS_TOKEN);
if (token == null || token.trim().isEmpty()) { if (token == null || token.trim().isEmpty()) {
return Result.error("用户未登录"); return Result.error("用户未登录");
} }
String username = JwtUtil.getUsername(token); String username = JwtUtil.getUsername(token);
LoginUser sysUser = sysBaseApi.getUserByName(username); LoginUser sysUser = sysBaseApi.getUserByName(username);
if (sysUser == null) { if (sysUser == null) {
return Result.error("用户信息不存在"); return Result.error("用户信息不存在");
} }
// 2. 验证会话是否存在 // 2. 验证会话是否存在
AiolChat chat = aiolChatService.getById(chatId); AiolChat chat = aiolChatService.getById(chatId);
if (chat == null) { if (chat == null) {
return Result.error("会话不存在"); return Result.error("会话不存在");
} }
// 3. 查询用户是否为该会话的成员 // 3. 查询用户是否为该会话的成员
QueryWrapper<AiolChatMember> memberWrapper = new QueryWrapper<>(); QueryWrapper<AiolChatMember> memberWrapper = new QueryWrapper<>();
memberWrapper.eq("chat_id", chatId).eq("user_id", sysUser.getId()); memberWrapper.eq("chat_id", chatId).eq("user_id", sysUser.getId());
AiolChatMember chatMember = aiolChatMemberMapper.selectOne(memberWrapper); AiolChatMember chatMember = aiolChatMemberMapper.selectOne(memberWrapper);
if (chatMember == null) { if (chatMember == null) {
return Result.error("您不是该会话的成员"); return Result.error("您不是该会话的成员");
} }
// 4. 检查是否为会话创建者可选不允许创建者退出 // 4. 检查是否为会话创建者可选不允许创建者退出
if (chat.getCreateBy() != null && chat.getCreateBy().equals(sysUser.getId())) { if (chat.getCreateBy() != null && chat.getCreateBy().equals(sysUser.getId())) {
// 可选如果创建者退出需要转移创建者权限或不允许退出 // 可选如果创建者退出需要转移创建者权限或不允许退出
@ -937,28 +959,28 @@ public class AiolChatController extends JeecgController<AiolChat, IAiolChatServi
// 这里可以选择是否允许创建者退出或者需要先转移权限 // 这里可以选择是否允许创建者退出或者需要先转移权限
// return Result.error("群聊创建者不能直接退出,请先转移群主权限"); // return Result.error("群聊创建者不能直接退出,请先转移群主权限");
} }
// 5. 从会话成员表中删除该用户 // 5. 从会话成员表中删除该用户
boolean deleted = aiolChatMemberMapper.deleteById(chatMember.getId()) > 0; boolean deleted = aiolChatMemberMapper.deleteById(chatMember.getId()) > 0;
if (!deleted) { if (!deleted) {
return Result.error("退出群聊失败"); return Result.error("退出群聊失败");
} }
// 6. 检查会话是否还有其他成员如果没有则删除会话可选 // 6. 检查会话是否还有其他成员如果没有则删除会话可选
QueryWrapper<AiolChatMember> remainingMemberWrapper = new QueryWrapper<>(); QueryWrapper<AiolChatMember> remainingMemberWrapper = new QueryWrapper<>();
remainingMemberWrapper.eq("chat_id", chatId); remainingMemberWrapper.eq("chat_id", chatId);
long remainingMemberCount = aiolChatMemberMapper.selectCount(remainingMemberWrapper); long remainingMemberCount = aiolChatMemberMapper.selectCount(remainingMemberWrapper);
if (remainingMemberCount == 0) { if (remainingMemberCount == 0) {
// 如果没有其他成员了删除会话 // 如果没有其他成员了删除会话
aiolChatService.removeById(chatId); aiolChatService.removeById(chatId);
log.info("会话 {} 无成员,已自动删除", chatId); log.info("会话 {} 无成员,已自动删除", chatId);
} }
log.info("用户 {} 成功退出群聊 {}", username, chatId); log.info("用户 {} 成功退出群聊 {}", username, chatId);
return Result.OK("退出群聊成功!"); return Result.OK("退出群聊成功!");
} catch (Exception e) { } catch (Exception e) {
log.error("退出群聊失败: chatId={}, error={}", chatId, e.getMessage(), e); log.error("退出群聊失败: chatId={}, error={}", chatId, e.getMessage(), e);
return Result.error("退出群聊失败: " + e.getMessage()); return Result.error("退出群聊失败: " + e.getMessage());

View File

@ -11,11 +11,16 @@ import java.net.URLDecoder;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.jeecg.common.api.vo.Result; import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.system.query.QueryGenerator; import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.system.query.QueryRuleEnum; import org.jeecg.common.system.query.QueryRuleEnum;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.oConvertUtils; import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.aiol.entity.AiolChatMember; import org.jeecg.modules.aiol.entity.AiolChatMember;
import org.jeecg.modules.aiol.entity.AiolChatMessage;
import org.jeecg.modules.aiol.service.IAiolChatMemberService; import org.jeecg.modules.aiol.service.IAiolChatMemberService;
import org.jeecg.modules.aiol.service.IAiolChatMessageService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
@ -27,6 +32,7 @@ import org.jeecgframework.poi.excel.def.NormalExcelConstants;
import org.jeecgframework.poi.excel.entity.ExportParams; import org.jeecgframework.poi.excel.entity.ExportParams;
import org.jeecgframework.poi.excel.entity.ImportParams; import org.jeecgframework.poi.excel.entity.ImportParams;
import org.jeecgframework.poi.excel.view.JeecgEntityExcelView; import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.system.base.controller.JeecgController; import org.jeecg.common.system.base.controller.JeecgController;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;

View File

@ -13,8 +13,12 @@ import javax.servlet.http.HttpServletResponse;
import org.jeecg.common.api.vo.Result; import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.query.QueryGenerator; import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.system.query.QueryRuleEnum; import org.jeecg.common.system.query.QueryRuleEnum;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.oConvertUtils; import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.aiol.entity.AiolChatMember;
import org.jeecg.modules.aiol.entity.AiolChatMessage; import org.jeecg.modules.aiol.entity.AiolChatMessage;
import org.jeecg.modules.aiol.service.IAiolChatMemberService;
import org.jeecg.modules.aiol.service.IAiolChatMessageService; import org.jeecg.modules.aiol.service.IAiolChatMessageService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
@ -27,6 +31,7 @@ import org.jeecgframework.poi.excel.def.NormalExcelConstants;
import org.jeecgframework.poi.excel.entity.ExportParams; import org.jeecgframework.poi.excel.entity.ExportParams;
import org.jeecgframework.poi.excel.entity.ImportParams; import org.jeecgframework.poi.excel.entity.ImportParams;
import org.jeecgframework.poi.excel.view.JeecgEntityExcelView; import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.system.base.controller.JeecgController; import org.jeecg.common.system.base.controller.JeecgController;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
@ -37,21 +42,28 @@ import com.alibaba.fastjson.JSON;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import org.jeecg.common.aspect.annotation.AutoLog; import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.constant.CommonConstant;
import org.apache.shiro.authz.annotation.RequiresPermissions; import org.apache.shiro.authz.annotation.RequiresPermissions;
/**
/**
* @Description: 会话消息 * @Description: 会话消息
* @Author: jeecg-boot * @Author: jeecg-boot
* @Date: 2025-09-11 * @Date: 2025-09-11
* @Version: V1.0 * @Version: V1.0
*/ */
@Tag(name="会话消息") @Tag(name = "会话消息")
@RestController @RestController
@RequestMapping("/aiol/aiolChatMessage") @RequestMapping("/aiol/aiolChatMessage")
@Slf4j @Slf4j
public class AiolChatMessageController extends JeecgController<AiolChatMessage, IAiolChatMessageService> { public class AiolChatMessageController extends JeecgController<AiolChatMessage, IAiolChatMessageService> {
@Autowired @Autowired
private IAiolChatMessageService aiolChatMessageService; private IAiolChatMessageService aiolChatMessageService;
@Autowired
private ISysBaseAPI sysBaseApi;
@Autowired
private IAiolChatMemberService aiolChatMemberService;
/** /**
* 分页列表查询 * 分页列表查询
* *
@ -61,122 +73,179 @@ public class AiolChatMessageController extends JeecgController<AiolChatMessage,
* @param req * @param req
* @return * @return
*/ */
//@AutoLog(value = "会话消息-分页列表查询") // @AutoLog(value = "会话消息-分页列表查询")
@Operation(summary="会话消息-分页列表查询") @Operation(summary = "会话消息-分页列表查询")
@GetMapping(value = "/list") @GetMapping(value = "/list")
public Result<IPage<AiolChatMessage>> queryPageList(AiolChatMessage aiolChatMessage, public Result<IPage<AiolChatMessage>> queryPageList(AiolChatMessage aiolChatMessage,
@RequestParam(name="pageNo", defaultValue="1") Integer pageNo, @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name="pageSize", defaultValue="10") Integer pageSize, @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
HttpServletRequest req) { HttpServletRequest req) {
QueryWrapper<AiolChatMessage> queryWrapper = QueryGenerator.initQueryWrapper(aiolChatMessage,
QueryWrapper<AiolChatMessage> queryWrapper = QueryGenerator.initQueryWrapper(aiolChatMessage, req.getParameterMap()); req.getParameterMap());
Page<AiolChatMessage> page = new Page<AiolChatMessage>(pageNo, pageSize); Page<AiolChatMessage> page = new Page<AiolChatMessage>(pageNo, pageSize);
IPage<AiolChatMessage> pageList = aiolChatMessageService.page(page, queryWrapper); IPage<AiolChatMessage> pageList = aiolChatMessageService.page(page, queryWrapper);
return Result.OK(pageList); return Result.OK(pageList);
} }
/** /**
* 添加 * 添加
* *
* @param aiolChatMessage * @param aiolChatMessage
* @return * @return
*/ */
@AutoLog(value = "会话消息-添加") @AutoLog(value = "会话消息-添加")
@Operation(summary="会话消息-添加") @Operation(summary = "会话消息-添加")
@RequiresPermissions("aiol:aiol_chat_message:add")
@PostMapping(value = "/add") @PostMapping(value = "/add")
public Result<String> add(@RequestBody AiolChatMessage aiolChatMessage) { public Result<String> add(@RequestBody AiolChatMessage aiolChatMessage) {
aiolChatMessageService.save(aiolChatMessage); aiolChatMessageService.save(aiolChatMessage);
return Result.OK("添加成功!"); return Result.OK(aiolChatMessage.getId());
} }
/** /**
* 编辑 * 编辑
* *
* @param aiolChatMessage * @param aiolChatMessage
* @return * @return
*/ */
@AutoLog(value = "会话消息-编辑") @AutoLog(value = "会话消息-编辑")
@Operation(summary="会话消息-编辑") @Operation(summary = "会话消息-编辑")
@RequiresPermissions("aiol:aiol_chat_message:edit") @RequiresPermissions("aiol:aiol_chat_message:edit")
@RequestMapping(value = "/edit", method = {RequestMethod.PUT,RequestMethod.POST}) @RequestMapping(value = "/edit", method = { RequestMethod.PUT, RequestMethod.POST })
public Result<String> edit(@RequestBody AiolChatMessage aiolChatMessage) { public Result<String> edit(@RequestBody AiolChatMessage aiolChatMessage) {
aiolChatMessageService.updateById(aiolChatMessage); aiolChatMessageService.updateById(aiolChatMessage);
return Result.OK("编辑成功!"); return Result.OK("编辑成功!");
} }
/** /**
* 通过id删除 * 通过id删除
* *
* @param id * @param id
* @return * @return
*/ */
@AutoLog(value = "会话消息-通过id删除") @AutoLog(value = "会话消息-通过id删除")
@Operation(summary="会话消息-通过id删除") @Operation(summary = "会话消息-通过id删除")
@RequiresPermissions("aiol:aiol_chat_message:delete") @RequiresPermissions("aiol:aiol_chat_message:delete")
@DeleteMapping(value = "/delete") @DeleteMapping(value = "/delete")
public Result<String> delete(@RequestParam(name="id",required=true) String id) { public Result<String> delete(@RequestParam(name = "id", required = true) String id) {
aiolChatMessageService.removeById(id); aiolChatMessageService.removeById(id);
return Result.OK("删除成功!"); return Result.OK("删除成功!");
} }
/** /**
* 批量删除 * 批量删除
* *
* @param ids * @param ids
* @return * @return
*/ */
@AutoLog(value = "会话消息-批量删除") @AutoLog(value = "会话消息-批量删除")
@Operation(summary="会话消息-批量删除") @Operation(summary = "会话消息-批量删除")
@RequiresPermissions("aiol:aiol_chat_message:deleteBatch") @RequiresPermissions("aiol:aiol_chat_message:deleteBatch")
@DeleteMapping(value = "/deleteBatch") @DeleteMapping(value = "/deleteBatch")
public Result<String> deleteBatch(@RequestParam(name="ids",required=true) String ids) { public Result<String> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
this.aiolChatMessageService.removeByIds(Arrays.asList(ids.split(","))); this.aiolChatMessageService.removeByIds(Arrays.asList(ids.split(",")));
return Result.OK("批量删除成功!"); return Result.OK("批量删除成功!");
} }
/** /**
* 通过id查询 * 通过id查询
* *
* @param id * @param id
* @return * @return
*/ */
//@AutoLog(value = "会话消息-通过id查询") // @AutoLog(value = "会话消息-通过id查询")
@Operation(summary="会话消息-通过id查询") @Operation(summary = "会话消息-通过id查询")
@GetMapping(value = "/queryById") @GetMapping(value = "/queryById")
public Result<AiolChatMessage> queryById(@RequestParam(name="id",required=true) String id) { public Result<AiolChatMessage> queryById(@RequestParam(name = "id", required = true) String id) {
AiolChatMessage aiolChatMessage = aiolChatMessageService.getById(id); AiolChatMessage aiolChatMessage = aiolChatMessageService.getById(id);
if(aiolChatMessage==null) { if (aiolChatMessage == null) {
return Result.error("未找到对应数据"); return Result.error("未找到对应数据");
} }
return Result.OK(aiolChatMessage); return Result.OK(aiolChatMessage);
} }
/** /**
* 导出excel * 导出excel
* *
* @param request * @param request
* @param aiolChatMessage * @param aiolChatMessage
*/ */
@RequiresPermissions("aiol:aiol_chat_message:exportXls") @RequiresPermissions("aiol:aiol_chat_message:exportXls")
@RequestMapping(value = "/exportXls") @RequestMapping(value = "/exportXls")
public ModelAndView exportXls(HttpServletRequest request, AiolChatMessage aiolChatMessage) { public ModelAndView exportXls(HttpServletRequest request, AiolChatMessage aiolChatMessage) {
return super.exportXls(request, aiolChatMessage, AiolChatMessage.class, "会话消息"); return super.exportXls(request, aiolChatMessage, AiolChatMessage.class, "会话消息");
} }
/** /**
* 通过excel导入数据 * 通过excel导入数据
* *
* @param request * @param request
* @param response * @param response
* @return * @return
*/ */
@RequiresPermissions("aiol:aiol_chat_message:importExcel") @RequiresPermissions("aiol:aiol_chat_message:importExcel")
@RequestMapping(value = "/importExcel", method = RequestMethod.POST) @RequestMapping(value = "/importExcel", method = RequestMethod.POST)
public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) { public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
return super.importExcel(request, response, AiolChatMessage.class); return super.importExcel(request, response, AiolChatMessage.class);
} }
/**
* 发送消息
* 前端传递 chat_idcontentmessage_typefile_urlsender_id 从token获取
*/
@AutoLog(value = "会话用户-发送消息")
@Operation(summary = "会话用户-发送消息", description = "发送会话消息sender_id从token获取")
@PostMapping(value = "/send")
public Result<String> sendMessage(@RequestBody Map<String, Object> body, 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. 解析参数
String chatId = body.get("chat_id") != null ? String.valueOf(body.get("chat_id")) : null;
String content = body.get("content") != null ? String.valueOf(body.get("content")) : null;
Integer messageType = body.get("message_type") != null
? Integer.parseInt(String.valueOf(body.get("message_type")))
: 0;
String fileUrl = body.get("file_url") != null ? String.valueOf(body.get("file_url")) : null;
if (chatId == null || chatId.trim().isEmpty()) {
return Result.error("chat_id不能为空");
}
// 3. 校验用户是否在该会话中
QueryWrapper<AiolChatMember> memberWrapper = new QueryWrapper<>();
memberWrapper.eq("chat_id", chatId).eq("user_id", sysUser.getId());
AiolChatMember chatMember = aiolChatMemberService.getOne(memberWrapper);
if (chatMember == null) {
return Result.error("您不是该会话的成员");
}
// 4. 组装消息并保存
AiolChatMessage message = new AiolChatMessage();
message.setChatId(chatId);
message.setSenderId(sysUser.getId());
message.setContent(content);
message.setMessageType(messageType);
message.setStatus(0);
message.setFileUrl(fileUrl);
aiolChatMessageService.save(message);
log.info("用户 {} 在会话 {} 发送消息成功, messageId={}", username, chatId, message.getId());
return Result.OK(message.getId());
} catch (Exception e) {
log.error("发送消息失败: error={}", e.getMessage(), e);
return Result.error("发送消息失败: " + e.getMessage());
}
}
} }

View File

@ -105,17 +105,14 @@ public class AiolCourseSectionController extends JeecgController<AiolCourseSecti
// 2. 处理资源关联 // 2. 处理资源关联
if (sectionDTO.getTargetId() != null && !sectionDTO.getTargetId().trim().isEmpty() && if (sectionDTO.getTargetId() != null && !sectionDTO.getTargetId().trim().isEmpty() &&
sectionDTO.getTargetType() != null && !sectionDTO.getTargetType().trim().isEmpty()) { sectionDTO.getType() != null) {
AiolEntityLink entityLink = new AiolEntityLink(); aiolEntityLinkService.save(
entityLink.setSourceType("course_section"); EntityLinkConst.SourceType.COURSE_SECTION,
entityLink.setSourceId(sectionDTO.getId()); sectionDTO.getId(),
entityLink.setTargetType(sectionDTO.getTargetType()); getTargetType(sectionDTO.getType()),
entityLink.setTargetId(sectionDTO.getTargetId()); sectionDTO.getTargetId()
entityLink.setCreateBy(sectionDTO.getCreateBy()); );
entityLink.setCreateTime(new Date());
aiolEntityLinkMapper.insert(entityLink);
} }
return Result.OK(sectionDTO.getId()); return Result.OK(sectionDTO.getId());
@ -124,6 +121,25 @@ public class AiolCourseSectionController extends JeecgController<AiolCourseSecti
return Result.error("添加课程章节失败: " + e.getMessage()); return Result.error("添加课程章节失败: " + e.getMessage());
} }
} }
private String getTargetType(Integer type) {
switch (type) {
case 0:
return EntityLinkConst.TargetType.RESOURCE;
case 1:
return EntityLinkConst.TargetType.RESOURCE;
case 2:
return EntityLinkConst.TargetType.EXAM;
case 3:
return EntityLinkConst.TargetType.HOMEWORK;
case 4:
return EntityLinkConst.TargetType.EXAM;
case 5:
return EntityLinkConst.TargetType.DISCUSSION;
default:
return null;
}
}
/** /**
* 编辑 * 编辑
@ -143,7 +159,7 @@ public class AiolCourseSectionController extends JeecgController<AiolCourseSecti
// 2. 处理资源关联更新 // 2. 处理资源关联更新
if (sectionDTO.getTargetId() != null && !sectionDTO.getTargetId().trim().isEmpty() && if (sectionDTO.getTargetId() != null && !sectionDTO.getTargetId().trim().isEmpty() &&
sectionDTO.getTargetType() != null && !sectionDTO.getTargetType().trim().isEmpty()) { sectionDTO.getType() != null) {
// 先删除旧的关联关系 // 先删除旧的关联关系
QueryWrapper<AiolEntityLink> deleteWrapper = new QueryWrapper<>(); QueryWrapper<AiolEntityLink> deleteWrapper = new QueryWrapper<>();
@ -152,7 +168,12 @@ public class AiolCourseSectionController extends JeecgController<AiolCourseSecti
aiolEntityLinkMapper.delete(deleteWrapper); aiolEntityLinkMapper.delete(deleteWrapper);
// 创建新的关联关系 // 创建新的关联关系
aiolEntityLinkService.save(EntityLinkConst.SourceType.COURSE_SECTION, sectionDTO.getId(), sectionDTO.getTargetType(), sectionDTO.getTargetId()); aiolEntityLinkService.save(
EntityLinkConst.SourceType.COURSE_SECTION,
sectionDTO.getId(),
getTargetType(sectionDTO.getType()),
sectionDTO.getTargetId()
);
} else { } else {
// 如果没有提供资源信息删除所有关联关系 // 如果没有提供资源信息删除所有关联关系
QueryWrapper<AiolEntityLink> deleteWrapper = new QueryWrapper<>(); QueryWrapper<AiolEntityLink> deleteWrapper = new QueryWrapper<>();

View File

@ -21,10 +21,4 @@ public class AiolCourseSectionDTO extends AiolCourseSection {
*/ */
@Schema(description = "资源ID") @Schema(description = "资源ID")
private String targetId; private String targetId;
/**
* 资源类型
*/
@Schema(description = "资源类型")
private String targetType;
} }