From ea534f1a9029a9518ce6dae69ae95aa698047374 Mon Sep 17 00:00:00 2001 From: GoCo Date: Tue, 16 Sep 2025 17:27:45 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20=E8=AF=BE=E7=A8=8B?= =?UTF-8?q?=E5=88=97=E8=A1=A8=E6=8E=A5=E5=8F=A3=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E8=AF=BE=E7=A8=8B=E6=8E=A5=E5=8F=A3=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../aiol/constant/EntityLinkConst.java | 2 + .../aiol/controller/AiolCourseController.java | 67 ++++++++++-- .../aiol/controller/AiolUserController.java | 103 ++++++++++++++++++ .../aiol/dto/AiolCourseWithLinkDTO.java | 18 +++ .../modules/aiol/dto/EditProfileDTO.java | 46 ++++++++ .../aiol/service/IAiolEntityLinkService.java | 9 ++ .../impl/AiolEntityLinkServiceImpl.java | 13 +++ 7 files changed, 247 insertions(+), 11 deletions(-) create mode 100644 jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/dto/AiolCourseWithLinkDTO.java create mode 100644 jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/dto/EditProfileDTO.java diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/constant/EntityLinkConst.java b/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/constant/EntityLinkConst.java index 14b7205f..4eddd70e 100644 --- a/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/constant/EntityLinkConst.java +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/constant/EntityLinkConst.java @@ -37,6 +37,8 @@ public final class EntityLinkConst { public static final String COURSE = "course"; // 题库 public static final String REPO = "repo"; + // 班级 + public static final String CLASS = "class"; } /** 资源类型 0:视频,1:图片,2:文档 */ diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/controller/AiolCourseController.java b/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/controller/AiolCourseController.java index da9623d6..f5215fc9 100644 --- a/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/controller/AiolCourseController.java +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/controller/AiolCourseController.java @@ -21,11 +21,14 @@ import org.jeecg.config.shiro.IgnoreAuth; import org.jeecg.modules.aiol.dto.CourseWithTeacherInfo; import org.jeecg.modules.aiol.dto.AiolCourseSaveDTO; import org.jeecg.modules.aiol.dto.TeacherInfo; +import org.jeecg.modules.aiol.dto.AiolCourseWithLinkDTO; import org.jeecg.modules.aiol.entity.*; import org.jeecg.modules.aiol.service.IAiolCourseService; import org.jeecg.modules.aiol.service.IAiolClassService; import org.jeecg.modules.aiol.service.IAiolEntityPermissionService; +import org.jeecg.modules.aiol.service.IAiolEntityLinkService; import org.jeecg.modules.aiol.constant.EntityPermissionConst; +import org.jeecg.modules.aiol.constant.EntityLinkConst; import org.jeecg.modules.aiol.mapper.AiolCourseSignupMapper; import org.jeecg.modules.aiol.mapper.AiolCourseTeacherMapper; import org.jeecg.modules.aiol.mapper.AiolEntityLinkMapper; @@ -70,6 +73,8 @@ import org.apache.shiro.authz.annotation.RequiresPermissions; public class AiolCourseController extends JeecgController { @Autowired private IAiolCourseService aiolCourseService; + @Autowired + private IAiolEntityLinkService entityLinkService; /** * 分页列表查询 @@ -131,14 +136,7 @@ public class AiolCourseController extends JeecgController linkExistsWrapper = new QueryWrapper<>(); + linkExistsWrapper.eq("source_type", EntityLinkConst.SourceType.COURSE) + .eq("source_id", dto.getId()) + .eq("target_type", EntityLinkConst.TargetType.CLASS) + .eq("target_id", clsId.trim()); + AiolEntityLink existed = entityLinkMapper.selectOne(linkExistsWrapper); + if (existed == null) { + AiolEntityLink classLink = new AiolEntityLink(); + classLink.setSourceType(EntityLinkConst.SourceType.COURSE); + classLink.setSourceId(dto.getId()); + classLink.setTargetType(EntityLinkConst.TargetType.CLASS); + classLink.setTargetId(clsId.trim()); + classLink.setCreateBy(dto.getCreateBy()); + classLink.setCreateTime(new Date()); + entityLinkMapper.insert(classLink); + } + // 1. 根据班级ID查询学生列表 QueryWrapper studentWrapper = new QueryWrapper<>(); studentWrapper.eq("class_id", clsId.trim()); @@ -212,7 +228,7 @@ public class AiolCourseController extends JeecgController> queryTeacherCourseList( + public Result> queryTeacherCourseList( @RequestParam(value = "keyword", required = false) String keyword, @RequestParam(value = "status", required = false) Integer status, HttpServletRequest request, HttpServletResponse response) { @@ -670,7 +688,34 @@ public class AiolCourseController extends JeecgController dtoList = new ArrayList<>(); + for (AiolCourse course : resultList) { + AiolCourseWithLinkDTO dto = new AiolCourseWithLinkDTO(); + org.springframework.beans.BeanUtils.copyProperties(course, dto); + + // 课程的分类关联(course_category -> course),使用服务反查分类ID列表 + List categoryIdList = aiolEntityLinkService.listSourceIds( + EntityLinkConst.TargetType.COURSE, + course.getId(), + EntityLinkConst.SourceType.COURSE_CATEGORY); + if (!categoryIdList.isEmpty()) { + dto.setCategoryId(String.join(",", categoryIdList)); + } + + // 查询课程的班级关联(source_type=course, source_id=courseId, target_type=class)使用服务方法 + List classIdList = aiolEntityLinkService.listTargetIds( + EntityLinkConst.SourceType.COURSE, + course.getId(), + EntityLinkConst.TargetType.CLASS); + if (!classIdList.isEmpty()) { + dto.setClassId(String.join(",", classIdList)); + } + + dtoList.add(dto); + } + + return Result.OK(dtoList); } catch (Exception e) { log.error("查询教师课程列表失败: error={}", e.getMessage(), e); diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/controller/AiolUserController.java b/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/controller/AiolUserController.java index 8b976c00..506000f4 100644 --- a/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/controller/AiolUserController.java +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/controller/AiolUserController.java @@ -16,6 +16,7 @@ import org.jeecg.common.util.RedisUtil; import org.jeecg.config.shiro.IgnoreAuth; import org.jeecg.modules.aiol.dto.TeacherInfo; import org.jeecg.modules.aiol.dto.UserInfoResponse; +import org.jeecg.modules.aiol.dto.EditProfileDTO; import org.jeecg.modules.aiol.entity.AiolClass; import org.jeecg.modules.aiol.entity.AiolClassStudent; import org.jeecg.modules.aiol.entity.AiolUserInfo; @@ -342,4 +343,106 @@ public class AiolUserController { return result.error500("注册失败: " + e.getMessage()); } } + + @PostMapping("/edit_profile") + @Operation(summary = "编辑个人信息", description = "更新用户的基本信息和扩展信息,分别存储到sys_user和aiol_user_info表") + @Transactional(rollbackFor = Exception.class) + public Result editProfile(@RequestBody EditProfileDTO profileDTO, HttpServletRequest request) { + try { + // 1. 从JWT中获取当前用户信息 + String username = JwtUtil.getUserNameByToken(request); + if (username == null || username.trim().isEmpty()) { + return Result.error(401, "用户未登录或token无效"); + } + + SysUser currentUser = sysUserService.getUserByName(username); + if (currentUser == null) { + return Result.error(404, "用户不存在"); + } + + String id = currentUser.getId(); + + // 2. 更新sys_user表的基本信息 + SysUser userToUpdate = new SysUser(); + userToUpdate.setId(id); + + if (profileDTO.getRealname() != null) { + userToUpdate.setRealname(profileDTO.getRealname()); + } + if (profileDTO.getAvatar() != null) { + userToUpdate.setAvatar(profileDTO.getAvatar()); + } + if (profileDTO.getBirthday() != null) { + userToUpdate.setBirthday(profileDTO.getBirthday()); + } + if (profileDTO.getSex() != null) { + userToUpdate.setSex(profileDTO.getSex()); + } + if (profileDTO.getEmail() != null) { + userToUpdate.setEmail(profileDTO.getEmail()); + } + if (profileDTO.getPhone() != null) { + userToUpdate.setPhone(profileDTO.getPhone()); + } + + // 设置更新信息 + userToUpdate.setUpdateBy(username); + userToUpdate.setUpdateTime(new Date()); + + boolean userUpdated = sysUserService.updateById(userToUpdate); + if (!userUpdated) { + return Result.error(500, "更新用户基本信息失败"); + } + + // 3. 更新aiol_user_info表的扩展信息 + AiolUserInfo userInfo = userInfoMapper.selectOne( + new QueryWrapper().eq("user_id", id)); + + if (userInfo == null) { + // 如果扩展信息不存在,创建新记录 + userInfo = new AiolUserInfo(); + userInfo.setUserId(id); + userInfo.setCreateBy(username); + userInfo.setCreateTime(new Date()); + } + + // 更新扩展信息字段 + if (profileDTO.getMajor() != null) { + userInfo.setMajor(profileDTO.getMajor()); + } + if (profileDTO.getCollege() != null) { + userInfo.setCollege(profileDTO.getCollege()); + } + if (profileDTO.getEducation() != null) { + userInfo.setEducation(profileDTO.getEducation()); + } + if (profileDTO.getTitle() != null) { + userInfo.setTitle(profileDTO.getTitle()); + } + + // 设置更新信息 + userInfo.setUpdateBy(username); + userInfo.setUpdateTime(new Date()); + + boolean userInfoUpdated; + if (userInfo.getId() == null) { + // 新增记录 + userInfoUpdated = userInfoMapper.insert(userInfo) > 0; + } else { + // 更新记录 + userInfoUpdated = userInfoMapper.updateById(userInfo) > 0; + } + + if (!userInfoUpdated) { + return Result.error(500, "更新用户扩展信息失败"); + } + + log.info("用户个人信息更新成功: userId={}, username={}", id, username); + return Result.OK("个人信息更新成功"); + + } catch (Exception e) { + log.error("编辑个人信息失败: {}", e.getMessage(), e); + return Result.error(500, "编辑个人信息失败: " + e.getMessage()); + } + } } diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/dto/AiolCourseWithLinkDTO.java b/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/dto/AiolCourseWithLinkDTO.java new file mode 100644 index 00000000..5e5e3819 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/dto/AiolCourseWithLinkDTO.java @@ -0,0 +1,18 @@ +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.AiolCourse; + +@Data +@EqualsAndHashCode(callSuper = false) +@Schema(description = "课程DTO,包含分类ID和班级ID(逗号分隔)") +public class AiolCourseWithLinkDTO extends AiolCourse { + + @Schema(description = "课程分类ID,多个以逗号分隔") + private String categoryId; + + @Schema(description = "班级ID,多个以逗号分隔") + private String classId; +} diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/dto/EditProfileDTO.java b/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/dto/EditProfileDTO.java new file mode 100644 index 00000000..0d871085 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/dto/EditProfileDTO.java @@ -0,0 +1,46 @@ +package org.jeecg.modules.aiol.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.Date; + +/** + * 编辑个人信息DTO + */ +@Data +@Schema(description = "编辑个人信息DTO") +public class EditProfileDTO { + + @Schema(description = "真实姓名") + private String realname; + + @Schema(description = "头像") + private String avatar; + + @Schema(description = "生日") + @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", timezone = "GMT+8") + private Date birthday; + + @Schema(description = "性别(1:男 2:女)") + private Integer sex; + + @Schema(description = "邮箱") + private String email; + + @Schema(description = "电话") + private String phone; + + @Schema(description = "专业") + private String major; + + @Schema(description = "学院") + private String college; + + @Schema(description = "学历") + private String education; + + @Schema(description = "职称") + private String title; +} diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/service/IAiolEntityLinkService.java b/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/service/IAiolEntityLinkService.java index 28c1f48f..e7f5efc4 100644 --- a/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/service/IAiolEntityLinkService.java +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/service/IAiolEntityLinkService.java @@ -21,6 +21,15 @@ public interface IAiolEntityLinkService extends IService { */ List listTargetIds(String sourceType, String sourceId, String targetType); + /** + * 根据内容与主体类型查询绑定的 source_id 列表 + * @param targetType 内容类型 + * @param targetId 内容ID + * @param sourceType 主体类型 + * @return source_id 列表(去重) + */ + List listSourceIds(String targetType, String targetId, String sourceType); + /** * 保存主体与内容类型的绑定关系 * @param sourceType 主体类型 diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/service/impl/AiolEntityLinkServiceImpl.java b/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/service/impl/AiolEntityLinkServiceImpl.java index 82f8c3c0..581b276d 100644 --- a/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/service/impl/AiolEntityLinkServiceImpl.java +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/service/impl/AiolEntityLinkServiceImpl.java @@ -32,6 +32,19 @@ public class AiolEntityLinkServiceImpl extends ServiceImpl listSourceIds(String targetType, String targetId, String sourceType) { + LambdaQueryWrapper qw = new LambdaQueryWrapper<>(); + qw.eq(AiolEntityLink::getTargetType, targetType) + .eq(AiolEntityLink::getTargetId, targetId) + .eq(AiolEntityLink::getSourceType, sourceType) + .select(AiolEntityLink::getSourceId); + return this.list(qw).stream() + .map(AiolEntityLink::getSourceId) + .distinct() + .collect(Collectors.toList()); + } + @Override public void save(String sourceType, String sourceId, String targetType, String targetId) { AiolEntityLink entityLink = new AiolEntityLink();