From 61d70bb3792d483fa5d19b2374ae9a0c10b576ec Mon Sep 17 00:00:00 2001 From: GoCo Date: Thu, 25 Sep 2025 09:41:17 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../aiol/controller/AiolClassController.java | 67 ++++++- .../AiolClassStudentController.java | 163 ++++++++++++++++-- .../controller/AiolCommentController.java | 2 +- .../controller/AiolMessageController.java | 45 +++++ 4 files changed, 259 insertions(+), 18 deletions(-) diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/controller/AiolClassController.java b/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/controller/AiolClassController.java index dd3b176b..6f290add 100644 --- a/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/controller/AiolClassController.java +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/controller/AiolClassController.java @@ -26,6 +26,7 @@ import org.jeecg.modules.aiol.mapper.AiolUserInfoMapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import java.util.Random; import lombok.extern.slf4j.Slf4j; import org.jeecg.common.system.api.ISysBaseAPI; @@ -64,6 +65,56 @@ public class AiolClassController extends JeecgController maxAttempts) { + log.error("生成邀请码失败,已达到最大尝试次数: {}", maxAttempts); + throw new RuntimeException("生成邀请码失败,请稍后重试"); + } + } while (isInviteCodeExists(inviteCode)); + + log.info("成功生成邀请码: {}, 尝试次数: {}", inviteCode, attempts); + return inviteCode; + } + + /** + * 生成8位随机邀请码(数字+大写字母) + * @return 8位邀请码 + */ + private String generateRandomInviteCode() { + String characters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + Random random = new Random(); + StringBuilder inviteCode = new StringBuilder(8); + + for (int i = 0; i < 8; i++) { + inviteCode.append(characters.charAt(random.nextInt(characters.length()))); + } + + return inviteCode.toString(); + } + + /** + * 检查邀请码是否已存在 + * @param inviteCode 邀请码 + * @return true-已存在,false-不存在 + */ + private boolean isInviteCodeExists(String inviteCode) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("invite_code", inviteCode); + return aiolClassService.count(queryWrapper) > 0; + } + /** * 分页列表查询 * @@ -99,9 +150,19 @@ public class AiolClassController extends JeecgController add(@RequestBody AiolClass aiolClass) { - aiolClassService.save(aiolClass); - - return Result.OK("添加成功!"); + try { + // 自动生成8位不重复的邀请码 + String inviteCode = generateUniqueInviteCode(); + aiolClass.setInviteCode(inviteCode); + + aiolClassService.save(aiolClass); + + log.info("班级添加成功,班级名: {}, 邀请码: {}", aiolClass.getName(), inviteCode); + return Result.OK(aiolClass.getId()); + } catch (Exception e) { + log.error("添加班级失败: {}", e.getMessage(), e); + return Result.error("添加班级失败: " + e.getMessage()); + } } /** diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/controller/AiolClassStudentController.java b/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/controller/AiolClassStudentController.java index 0ae35820..08876f70 100644 --- a/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/controller/AiolClassStudentController.java +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/controller/AiolClassStudentController.java @@ -4,18 +4,14 @@ import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.stream.Collectors; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.net.URLDecoder; +import java.util.Date; +import java.util.ArrayList; import javax.servlet.http.HttpServletRequest; 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.AiolClassStudent; import org.jeecg.modules.aiol.service.IAiolClassStudentService; @@ -24,19 +20,11 @@ import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import lombok.extern.slf4j.Slf4j; -import org.jeecgframework.poi.excel.ExcelImportUtil; -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.*; -import org.springframework.web.multipart.MultipartFile; -import org.springframework.web.multipart.MultipartHttpServletRequest; import org.springframework.web.servlet.ModelAndView; -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; @@ -183,4 +171,151 @@ public class AiolClassStudentController extends JeecgController importExcel(HttpServletRequest request, HttpServletResponse response) { return super.importExcel(request, response, AiolClassStudent.class); } + + /** + * 批量调班 + * + * @param requestBody 包含学生ID列表、原班级ID和新班级ID + * @param request HTTP请求对象 + * @return 调班结果 + */ + @AutoLog(value = "班级学生-批量调班") + @Operation(summary = "批量调班", description = "将指定学生从原班级调转到新班级") + @PostMapping(value = "/batchTransfer") + public Result> batchTransfer(@RequestBody Map requestBody, + HttpServletRequest request) { + try { + // 1. 获取当前登录用户信息 + String token = request.getHeader(CommonConstant.X_ACCESS_TOKEN); + String username = JwtUtil.getUsername(token); + LoginUser sysUser = sysBaseApi.getUserByName(username); + + if (sysUser == null) { + return Result.error("用户未登录或登录已过期"); + } + + // 2. 从请求体中获取参数 + @SuppressWarnings("unchecked") + List studentIds = (List) requestBody.get("studentIds"); + String originalClassId = (String) requestBody.get("originalClassId"); + String newClassId = (String) requestBody.get("newClassId"); + + // 3. 参数验证 + if (studentIds == null || studentIds.isEmpty()) { + return Result.error("学生ID列表不能为空"); + } + if (originalClassId == null || originalClassId.trim().isEmpty()) { + return Result.error("原班级ID不能为空"); + } + if (newClassId == null || newClassId.trim().isEmpty()) { + return Result.error("新班级ID不能为空"); + } + if (originalClassId.equals(newClassId)) { + return Result.error("原班级和新班级不能相同"); + } + + // 4. 执行批量调班操作 + Map result = performBatchTransfer(studentIds, originalClassId, newClassId, sysUser); + + log.info("用户 {} 执行批量调班操作完成,结果: {}", username, result); + return Result.OK(result); + + } catch (Exception e) { + log.error("批量调班失败: {}", e.getMessage(), e); + return Result.error("批量调班失败: " + e.getMessage()); + } + } + + /** + * 执行批量调班操作 + * + * @param studentIds 学生ID列表 + * @param originalClassId 原班级ID + * @param newClassId 新班级ID + * @param sysUser 当前登录用户 + * @return 调班结果统计 + */ + private Map performBatchTransfer(List studentIds, String originalClassId, + String newClassId, LoginUser sysUser) { + Map result = new HashMap<>(); + int successCount = 0; + int failCount = 0; + int notFoundCount = 0; + int alreadyInNewClassCount = 0; + List successStudentIds = new ArrayList<>(); + List failStudentIds = new ArrayList<>(); + List notFoundStudentIds = new ArrayList<>(); + List alreadyInNewClassStudentIds = new ArrayList<>(); + + for (String studentId : studentIds) { + try { + // 1. 查找原班级中的学生记录 + QueryWrapper originalQuery = new QueryWrapper<>(); + originalQuery.eq("class_id", originalClassId) + .eq("student_id", studentId); + + AiolClassStudent originalRecord = aiolClassStudentService.getOne(originalQuery); + + if (originalRecord == null) { + notFoundCount++; + notFoundStudentIds.add(studentId); + log.warn("学生 {} 在原班级 {} 中不存在", studentId, originalClassId); + continue; + } + + // 2. 检查学生是否已在新班级中 + QueryWrapper newClassQuery = new QueryWrapper<>(); + newClassQuery.eq("class_id", newClassId) + .eq("student_id", studentId); + + AiolClassStudent existingInNewClass = aiolClassStudentService.getOne(newClassQuery); + if (existingInNewClass != null) { + alreadyInNewClassCount++; + alreadyInNewClassStudentIds.add(studentId); + log.warn("学生 {} 已在新班级 {} 中", studentId, newClassId); + continue; + } + + // 3. 执行调班操作:更新原记录的班级ID + originalRecord.setClassId(newClassId); + originalRecord.setUpdateBy(sysUser.getUsername()); + originalRecord.setUpdateTime(new Date()); + + boolean updateResult = aiolClassStudentService.updateById(originalRecord); + + if (updateResult) { + successCount++; + successStudentIds.add(studentId); + log.info("成功将学生 {} 从班级 {} 调转到班级 {}", studentId, originalClassId, newClassId); + } else { + failCount++; + failStudentIds.add(studentId); + log.error("更新学生 {} 的班级信息失败", studentId); + } + + } catch (Exception e) { + failCount++; + failStudentIds.add(studentId); + log.error("处理学生 {} 调班时发生异常: {}", studentId, e.getMessage(), e); + } + } + + // 4. 构建返回结果 + result.put("totalCount", studentIds.size()); + result.put("successCount", successCount); + result.put("failCount", failCount); + result.put("notFoundCount", notFoundCount); + result.put("alreadyInNewClassCount", alreadyInNewClassCount); + result.put("originalClassId", originalClassId); + result.put("newClassId", newClassId); + result.put("successStudentIds", successStudentIds); + result.put("failStudentIds", failStudentIds); + result.put("notFoundStudentIds", notFoundStudentIds); + result.put("alreadyInNewClassStudentIds", alreadyInNewClassStudentIds); + + log.info("批量调班操作完成 - 总数: {}, 成功: {}, 失败: {}, 未找到: {}, 已在新班级: {}", + studentIds.size(), successCount, failCount, notFoundCount, alreadyInNewClassCount); + + return result; + } } diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/controller/AiolCommentController.java b/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/controller/AiolCommentController.java index 5cb181ca..ee400b30 100644 --- a/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/controller/AiolCommentController.java +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/controller/AiolCommentController.java @@ -135,7 +135,7 @@ public class AiolCommentController extends JeecgController delete(@RequestParam(name = "id", required = true) String id) { aiolCommentService.removeById(id); diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/controller/AiolMessageController.java b/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/controller/AiolMessageController.java index 45890619..8b633e6b 100644 --- a/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/controller/AiolMessageController.java +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-aiol/src/main/java/org/jeecg/modules/aiol/controller/AiolMessageController.java @@ -12,22 +12,29 @@ import org.jeecg.common.api.vo.Result; import org.apache.shiro.SecurityUtils; import org.jeecg.common.system.vo.LoginUser; import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.GetMapping; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import org.jeecg.modules.system.model.AnnouncementSendModel; import org.jeecg.modules.system.service.ISysAnnouncementSendService; import org.jeecg.modules.system.entity.SysAnnouncementSend; import org.jeecg.modules.system.entity.SysAnnouncement; import org.jeecg.modules.system.service.ISysAnnouncementService; +import org.jeecg.common.constant.CommonConstant; import org.apache.commons.lang3.StringUtils; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Date; +import lombok.extern.slf4j.Slf4j; @RestController @RequestMapping("/aiol/message") +@Slf4j public class AiolMessageController { @Autowired private ISysBaseAPI sysBaseApi; @@ -215,4 +222,42 @@ public class AiolMessageController { return Result.error("查询未读消息数量失败: " + e.getMessage()); } } + + /** + * @功能:标记单条消息已读 + * @param sendId 消息发送记录ID + * @return + */ + @GetMapping(value = "/readOne") + public Result readOne(@RequestParam(name = "sendId", required = true) String sendId) { + Result result = new Result(); + try { + if (StringUtils.isEmpty(sendId)) { + result.error500("消息ID不能为空"); + return result; + } + + // 构建更新条件:根据sendId和userId更新单条消息 + LambdaUpdateWrapper updateWrapper = new UpdateWrapper().lambda(); + updateWrapper.set(SysAnnouncementSend::getReadFlag, CommonConstant.HAS_READ_FLAG); + updateWrapper.set(SysAnnouncementSend::getReadTime, new Date()); + updateWrapper.eq(SysAnnouncementSend::getId, sendId); + + SysAnnouncementSend announcementSend = new SysAnnouncementSend(); + boolean updateResult = sysAnnouncementSendService.update(announcementSend, updateWrapper); + + if (updateResult) { + result.setSuccess(true); + result.setMessage("消息已标记为已读"); + } else { + result.error500("标记已读失败,可能消息不存在或已被标记"); + } + + return result; + } catch (Exception e) { + log.error("标记单条消息已读失败: " + e.getMessage(), e); + result.error500("标记已读失败: " + e.getMessage()); + return result; + } + } }