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;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
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.service.IAiolChatService;
import org.jeecg.modules.system.entity.SysUser;
import org.jeecg.modules.system.entity.SysUserRole;
import org.jeecg.modules.system.mapper.SysUserMapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
@ -56,6 +58,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.apache.shiro.authz.annotation.RequiresPermissions;
/**
* @Description: 会话
* @Author: jeecg-boot
@ -108,7 +111,6 @@ public class AiolChatController extends JeecgController<AiolChat, IAiolChatServi
@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);
@ -298,6 +300,10 @@ public class AiolChatController extends JeecgController<AiolChat, IAiolChatServi
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列表
List<String> userIds = chatMembers.stream()
.map(AiolChatMember::getUserId)
@ -307,17 +313,17 @@ public class AiolChatController extends JeecgController<AiolChat, IAiolChatServi
List<SysUser> userList = sysUserMapper.selectByIds(userIds);
// 4. 查询所有用户的教师角色身份
Map<String, Boolean> teacherStatusMap = new java.util.HashMap<>();
Map<String, Boolean> teacherStatusMap = new HashMap<>();
if (!userIds.isEmpty()) {
try {
QueryWrapper<org.jeecg.modules.system.entity.SysUserRole> roleWrapper = new QueryWrapper<>();
QueryWrapper<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);
List<SysUserRole> teacherRoleList = sysUserRoleMapper.selectList(roleWrapper);
// 构建教师身份映射
for (org.jeecg.modules.system.entity.SysUserRole userRole : teacherRoleList) {
for (SysUserRole userRole : teacherRoleList) {
teacherStatusMap.put(userRole.getUserId(), true);
}
} catch (Exception e) {
@ -326,9 +332,9 @@ public class AiolChatController extends JeecgController<AiolChat, IAiolChatServi
}
// 5. 构建返回结果
List<Map<String, Object>> result = new java.util.ArrayList<>();
List<Map<String, Object>> result = new ArrayList<>();
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("realname", user.getRealname());
memberInfo.put("avatar", user.getAvatar());
@ -343,6 +349,15 @@ public class AiolChatController extends JeecgController<AiolChat, IAiolChatServi
memberInfo.put("email", user.getEmail());
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);
}
@ -410,20 +425,24 @@ public class AiolChatController extends JeecgController<AiolChat, IAiolChatServi
// 添加发送者信息
SysUser sender = senderMap.get(message.getSenderId());
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("avatar", sender.getAvatar());
put("username", sender.getUsername());
}});
}
});
} 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("avatar", "");
put("username", "");
}});
}
});
}
result.add(messageInfo);
@ -708,7 +727,8 @@ public class AiolChatController extends JeecgController<AiolChat, IAiolChatServi
* @param operationName 操作名称
* @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. 查询群聊成员是否存在
QueryWrapper<AiolChatMember> memberWrapper = new QueryWrapper<>();
memberWrapper.eq("chat_id", chatId).eq("user_id", userId);
@ -739,12 +759,14 @@ public class AiolChatController extends JeecgController<AiolChat, IAiolChatServi
/**
* 将AiolChat转换为包含未读消息数的DTO
*
* @param chat 会话实体
* @param chatMembers 会话成员列表
* @param userId 当前用户ID
* @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();
// 复制基本属性

View File

@ -11,11 +11,16 @@ import java.net.URLDecoder;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
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.QueryRuleEnum;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.system.vo.LoginUser;
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.service.IAiolChatMemberService;
import org.jeecg.modules.aiol.service.IAiolChatMessageService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
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.ImportParams;
import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.system.base.controller.JeecgController;
import org.springframework.beans.factory.annotation.Autowired;
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.system.query.QueryGenerator;
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.modules.aiol.entity.AiolChatMember;
import org.jeecg.modules.aiol.entity.AiolChatMessage;
import org.jeecg.modules.aiol.service.IAiolChatMemberService;
import org.jeecg.modules.aiol.service.IAiolChatMessageService;
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.ImportParams;
import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.system.base.controller.JeecgController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@ -37,7 +42,9 @@ import com.alibaba.fastjson.JSON;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.constant.CommonConstant;
import org.apache.shiro.authz.annotation.RequiresPermissions;
/**
* @Description: 会话消息
* @Author: jeecg-boot
@ -52,6 +59,11 @@ public class AiolChatMessageController extends JeecgController<AiolChatMessage,
@Autowired
private IAiolChatMessageService aiolChatMessageService;
@Autowired
private ISysBaseAPI sysBaseApi;
@Autowired
private IAiolChatMemberService aiolChatMemberService;
/**
* 分页列表查询
*
@ -69,8 +81,8 @@ public class AiolChatMessageController extends JeecgController<AiolChatMessage,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
HttpServletRequest req) {
QueryWrapper<AiolChatMessage> queryWrapper = QueryGenerator.initQueryWrapper(aiolChatMessage, req.getParameterMap());
QueryWrapper<AiolChatMessage> queryWrapper = QueryGenerator.initQueryWrapper(aiolChatMessage,
req.getParameterMap());
Page<AiolChatMessage> page = new Page<AiolChatMessage>(pageNo, pageSize);
IPage<AiolChatMessage> pageList = aiolChatMessageService.page(page, queryWrapper);
return Result.OK(pageList);
@ -84,12 +96,11 @@ public class AiolChatMessageController extends JeecgController<AiolChatMessage,
*/
@AutoLog(value = "会话消息-添加")
@Operation(summary = "会话消息-添加")
@RequiresPermissions("aiol:aiol_chat_message:add")
@PostMapping(value = "/add")
public Result<String> add(@RequestBody AiolChatMessage aiolChatMessage) {
aiolChatMessageService.save(aiolChatMessage);
return Result.OK("添加成功!");
return Result.OK(aiolChatMessage.getId());
}
/**
@ -179,4 +190,62 @@ public class AiolChatMessageController extends JeecgController<AiolChatMessage,
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. 处理资源关联
if (sectionDTO.getTargetId() != null && !sectionDTO.getTargetId().trim().isEmpty() &&
sectionDTO.getTargetType() != null && !sectionDTO.getTargetType().trim().isEmpty()) {
sectionDTO.getType() != null) {
AiolEntityLink entityLink = new AiolEntityLink();
entityLink.setSourceType("course_section");
entityLink.setSourceId(sectionDTO.getId());
entityLink.setTargetType(sectionDTO.getTargetType());
entityLink.setTargetId(sectionDTO.getTargetId());
entityLink.setCreateBy(sectionDTO.getCreateBy());
entityLink.setCreateTime(new Date());
aiolEntityLinkMapper.insert(entityLink);
aiolEntityLinkService.save(
EntityLinkConst.SourceType.COURSE_SECTION,
sectionDTO.getId(),
getTargetType(sectionDTO.getType()),
sectionDTO.getTargetId()
);
}
return Result.OK(sectionDTO.getId());
@ -125,6 +122,25 @@ public class AiolCourseSectionController extends JeecgController<AiolCourseSecti
}
}
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. 处理资源关联更新
if (sectionDTO.getTargetId() != null && !sectionDTO.getTargetId().trim().isEmpty() &&
sectionDTO.getTargetType() != null && !sectionDTO.getTargetType().trim().isEmpty()) {
sectionDTO.getType() != null) {
// 先删除旧的关联关系
QueryWrapper<AiolEntityLink> deleteWrapper = new QueryWrapper<>();
@ -152,7 +168,12 @@ public class AiolCourseSectionController extends JeecgController<AiolCourseSecti
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 {
// 如果没有提供资源信息删除所有关联关系
QueryWrapper<AiolEntityLink> deleteWrapper = new QueryWrapper<>();

View File

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