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 new file mode 100644 index 00000000..10b966c0 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/controller/AiolUserController.java @@ -0,0 +1,194 @@ +package org.jeecg.modules.aiol.controller; + +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.extern.slf4j.Slf4j; +import org.jeecg.common.api.vo.Result; +import org.jeecg.common.constant.CommonConstant; +import org.jeecg.common.system.api.ISysBaseAPI; +import org.jeecg.common.system.util.JwtUtil; +import org.jeecg.common.system.vo.DictModel; +import org.jeecg.common.util.PasswordUtil; +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.entity.AiolUserInfo; +import org.jeecg.modules.aiol.mapper.AiolUserInfoMapper; +import org.jeecg.modules.aiol.service.IAiolUserInfoService; +import org.jeecg.modules.system.entity.SysUser; +import org.jeecg.modules.system.service.ISysUserService; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@Tag(name = "前台用户") +@RestController +@RequestMapping("/aiol/aiolUser") +@Slf4j +public class AiolUserController { + @Autowired + private ISysUserService sysUserService; + @Autowired + private RedisUtil redisUtil; + @Autowired + private IAiolUserInfoService userBizService; + @Autowired + private AiolUserInfoMapper userInfoMapper; + @Autowired + private ISysBaseAPI sysBaseApi; + + @PostMapping("/login") + @Operation(summary = "用户登录") + @IgnoreAuth + public Result login(@RequestBody Map user, HttpServletRequest request) { + Result result = new Result(); + String username = user.get("username"); + String password = user.get("password"); + if (isLoginFailOvertimes(username)) { + return result.error500("该用户登录失败次数过多,请于10分钟后再次登录!"); + } + + // step.2 校验用户是否存在且有效 + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(SysUser::getUsername, username); + SysUser sysUser = sysUserService.getOne(queryWrapper); + Result checkResult = sysUserService.checkUserIsEffective(sysUser); + if (!checkResult.isSuccess()) { + return result.error500(checkResult.getMessage()); + } + + // step.3 校验用户名或密码是否正确 + String userpassword = PasswordUtil.encrypt(username, password, sysUser.getSalt()); + String syspassword = sysUser.getPassword(); + if (!syspassword.equals(userpassword)) { + addLoginFailOvertimes(username); + result.error500("用户名或密码错误"); + return result; + } + + // step.4 登录成功获取用户信息 + JSONObject obj = new JSONObject(new LinkedHashMap<>()); + // 1.生成token + String token = JwtUtil.sign(username, syspassword); + // 设置token缓存有效时间 + redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token); + redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME * 2 / 1000); + obj.put("token", token); + + // TODO 查询用户信息 + + result.setResult(obj); + result.success("登录成功"); + return result; + } + + /** + * 登录失败超出次数5 返回true + * + * @param username + * @return + */ + private boolean isLoginFailOvertimes(String username) { + String key = CommonConstant.LOGIN_FAIL + username; + Object failTime = redisUtil.get(key); + if (failTime != null) { + Integer val = Integer.parseInt(failTime.toString()); + if (val > 5) { + return true; + } + } + return false; + } + + /** + * 记录登录失败次数 + * + * @param username + */ + private void addLoginFailOvertimes(String username) { + String key = CommonConstant.LOGIN_FAIL + username; + Object failTime = redisUtil.get(key); + Integer val = 0; + if (failTime != null) { + val = Integer.parseInt(failTime.toString()); + } + // 10分钟,一分钟为60s + redisUtil.set(key, ++val, 600); + } + + @GetMapping("/all_teachers") + @Operation(summary = "查询师资力量", description = "categoryId为all则查询全部") + @IgnoreAuth + public Result> queryAllTeachers(@RequestParam("categoryId") String categoryId) { + List list = userBizService.queryAllTeachers(categoryId); + return Result.OK(list); + } + + @GetMapping("/info") + @Operation(summary = "查询用户信息", description = "通过JWT token获取当前用户的详细信息,包括基本信息、角色和扩展信息") + public Result queryUserInfo(HttpServletRequest request) { + try { + // 1. 从JWT中获取用户名 + String username = JwtUtil.getUserNameByToken(request); + if (username == null || username.trim().isEmpty()) { + return Result.error(401, "用户未登录或token无效"); + } + + // 2. 根据用户名查询系统用户信息 + SysUser sysUser = sysUserService.getUserByName(username); + if (sysUser == null) { + return Result.error(404, "用户不存在"); + } + + // 3. 查询用户角色 + List roles = sysUserService.getUserRolesSet(username).stream() + .collect(Collectors.toList()); + + // 4. 根据用户ID查询user_info表信息 + AiolUserInfo userInfo = userInfoMapper.selectOne( + new QueryWrapper().eq("user_id", sysUser.getId())); + + // 5. 构建返回结果 + UserInfoResponse response = new UserInfoResponse(); + + // 基本用户信息 + UserInfoResponse.BaseInfo baseInfo = new UserInfoResponse.BaseInfo(); + BeanUtils.copyProperties(sysUser, baseInfo); + response.setBaseInfo(baseInfo); + response.setRoles(roles); + + // 扩展用户信息 + if (userInfo != null) { + UserInfoResponse.ExtendedInfo extendedInfo = new UserInfoResponse.ExtendedInfo(); + BeanUtils.copyProperties(userInfo, extendedInfo); + response.setExtendedInfo(extendedInfo); + } + + return Result.OK(response); + } catch (Exception e) { + log.error("查询用户信息失败:" + e.getMessage(), e); + return Result.error(500, "查询用户信息失败:" + e.getMessage()); + } + } + + @GetMapping("/schools") + @Operation(summary = "查询学校列表") + @IgnoreAuth + public Result> querySchools() { + List list = sysBaseApi.getDictItems("school_list"); + List schools = list.stream() + .map(d -> d.getLabel()) + .collect(Collectors.toList()); + return Result.OK(schools); + } +} diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/service/IAiolUserInfoService.java b/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/service/IAiolUserInfoService.java index 6e5c1624..d179a558 100644 --- a/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/service/IAiolUserInfoService.java +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/service/IAiolUserInfoService.java @@ -1,8 +1,11 @@ package org.jeecg.modules.aiol.service; +import org.jeecg.modules.aiol.dto.TeacherInfo; import org.jeecg.modules.aiol.entity.AiolUserInfo; import com.baomidou.mybatisplus.extension.service.IService; +import java.util.List; + /** * @Description: 用户信息 * @Author: jeecg-boot @@ -10,5 +13,9 @@ import com.baomidou.mybatisplus.extension.service.IService; * @Version: V1.0 */ public interface IAiolUserInfoService extends IService { - + /** + * 师资力量 + * @return + */ + List queryAllTeachers(String categoryId); } diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/service/impl/AiolUserInfoServiceImpl.java b/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/service/impl/AiolUserInfoServiceImpl.java index a08f6365..c1ac1edd 100644 --- a/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/service/impl/AiolUserInfoServiceImpl.java +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/service/impl/AiolUserInfoServiceImpl.java @@ -1,12 +1,30 @@ package org.jeecg.modules.aiol.service.impl; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import org.jeecg.modules.aiol.constant.EntityLinkConst; +import org.jeecg.modules.aiol.dto.TeacherInfo; +import org.jeecg.modules.aiol.entity.AiolCourse; +import org.jeecg.modules.aiol.entity.AiolCourseTeacher; import org.jeecg.modules.aiol.entity.AiolUserInfo; +import org.jeecg.modules.aiol.mapper.AiolCourseMapper; +import org.jeecg.modules.aiol.mapper.AiolCourseTeacherMapper; +import org.jeecg.modules.aiol.mapper.AiolEntityLinkMapper; import org.jeecg.modules.aiol.mapper.AiolUserInfoMapper; +import org.jeecg.modules.aiol.service.IAiolEntityLinkService; import org.jeecg.modules.aiol.service.IAiolUserInfoService; +import org.jeecg.modules.system.entity.SysUser; +import org.jeecg.modules.system.mapper.SysUserMapper; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + /** * @Description: 用户信息 * @Author: jeecg-boot @@ -15,5 +33,62 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; */ @Service public class AiolUserInfoServiceImpl extends ServiceImpl implements IAiolUserInfoService { + @Autowired + private AiolCourseMapper courseMapper; + @Autowired + private AiolEntityLinkMapper entityLinkMapper; + @Autowired + private IAiolEntityLinkService entityLinkBizService; + @Autowired + private AiolCourseTeacherMapper courseTeacherMapper; + @Autowired + private AiolUserInfoMapper userInfoMapper; + @Autowired + private SysUserMapper sysUserMapper; + @Override + public List queryAllTeachers(String categoryId) { + // categoryId为all则查询全部 + // TODO 存入redis缓存 + + // 1 根据课程分类,查询该分类下的课程; all 则查询全部课程 + // 2 遍历课程,根据课程id查询该课程的授课教师 + // 3 将授课教师信息封装成TeacherInfo对象 + // 4 返回授课教师列表(去重) + + // 1 根据课程分类,查询该分类下的课程 + List courseIds; + if ("all".equals(categoryId)) { + // 查询全部课程 + List courseList = courseMapper.selectList(null); + courseIds = courseList.stream().map(AiolCourse::getId).collect(Collectors.toList()); + } else { + courseIds = entityLinkBizService.listTargetIds(EntityLinkConst.SourceType.COURSE_CATEGORY, categoryId, EntityLinkConst.TargetType.COURSE); + } + Set teacherIds = new HashSet<>(); + List result = new ArrayList<>(); + for (String courseId : courseIds) { + // 2 根据课程id查询该课程的授课教师 + List courseTeachers = courseTeacherMapper.selectList(new LambdaQueryWrapper().eq(AiolCourseTeacher::getCourseId, courseId)); + // 3 将授课教师信息封装成TeacherInfo对象 + for (AiolCourseTeacher courseTeacher : courseTeachers) { + // 4 将授课教师信息封装成TeacherInfo对象,去重 + AiolUserInfo userInfo = userInfoMapper.selectOne(new LambdaQueryWrapper().eq(AiolUserInfo::getUserId, courseTeacher.getTeacherId())); + SysUser sysUser = sysUserMapper.selectById(courseTeacher.getTeacherId()); + TeacherInfo teacherInfo = new TeacherInfo(); + teacherInfo.setId(courseTeacher.getTeacherId()); + teacherInfo.setName(sysUser.getRealname()); + teacherInfo.setAvatar(sysUser.getAvatar()); + teacherInfo.setTitle(userInfo.getTitle()); + teacherInfo.setTag(userInfo.getTag()); + teacherInfo.setSortOrder(userInfo.getSortOrder()); + if (!teacherIds.contains(courseTeacher.getTeacherId())) { + result.add(teacherInfo); + teacherIds.add(courseTeacher.getTeacherId()); + } + } + } + + return result; + } }