feat: 🎸 新增接口

This commit is contained in:
GoCo 2025-09-25 09:41:17 +08:00
parent 035794f916
commit 61d70bb379
4 changed files with 259 additions and 18 deletions

View File

@ -26,6 +26,7 @@ import org.jeecg.modules.aiol.mapper.AiolUserInfoMapper;
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;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import java.util.Random;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.system.api.ISysBaseAPI; import org.jeecg.common.system.api.ISysBaseAPI;
@ -64,6 +65,56 @@ public class AiolClassController extends JeecgController<AiolClass, IAiolClassSe
@Autowired @Autowired
private AiolUserInfoMapper aiolUserInfoMapper; private AiolUserInfoMapper aiolUserInfoMapper;
/**
* 生成8位不重复的邀请码
* @return 邀请码
*/
private String generateUniqueInviteCode() {
String inviteCode;
int maxAttempts = 100; // 最大尝试次数防止无限循环
int attempts = 0;
do {
inviteCode = generateRandomInviteCode();
attempts++;
if (attempts > 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<AiolClass> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("invite_code", inviteCode);
return aiolClassService.count(queryWrapper) > 0;
}
/** /**
* 分页列表查询 * 分页列表查询
* *
@ -99,9 +150,19 @@ public class AiolClassController extends JeecgController<AiolClass, IAiolClassSe
@RequiresPermissions("aiol:aiol_class:add") @RequiresPermissions("aiol:aiol_class:add")
@PostMapping(value = "/add") @PostMapping(value = "/add")
public Result<String> add(@RequestBody AiolClass aiolClass) { public Result<String> add(@RequestBody AiolClass aiolClass) {
aiolClassService.save(aiolClass); try {
// 自动生成8位不重复的邀请码
String inviteCode = generateUniqueInviteCode();
aiolClass.setInviteCode(inviteCode);
return Result.OK("添加成功!"); 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());
}
} }
/** /**

View File

@ -4,18 +4,14 @@ import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors; import java.util.Date;
import java.io.IOException; import java.util.ArrayList;
import java.io.UnsupportedEncodingException;
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.system.query.QueryGenerator; 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.util.JwtUtil;
import org.jeecg.common.system.vo.LoginUser; 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.entity.AiolClassStudent;
import org.jeecg.modules.aiol.service.IAiolClassStudentService; 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 com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j; 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.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.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.ModelAndView; 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.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;
@ -183,4 +171,151 @@ public class AiolClassStudentController extends JeecgController<AiolClassStudent
public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) { public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
return super.importExcel(request, response, AiolClassStudent.class); 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<Map<String, Object>> batchTransfer(@RequestBody Map<String, Object> 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<String> studentIds = (List<String>) 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<String, Object> 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<String, Object> performBatchTransfer(List<String> studentIds, String originalClassId,
String newClassId, LoginUser sysUser) {
Map<String, Object> result = new HashMap<>();
int successCount = 0;
int failCount = 0;
int notFoundCount = 0;
int alreadyInNewClassCount = 0;
List<String> successStudentIds = new ArrayList<>();
List<String> failStudentIds = new ArrayList<>();
List<String> notFoundStudentIds = new ArrayList<>();
List<String> alreadyInNewClassStudentIds = new ArrayList<>();
for (String studentId : studentIds) {
try {
// 1. 查找原班级中的学生记录
QueryWrapper<AiolClassStudent> 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<AiolClassStudent> 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;
}
} }

View File

@ -135,7 +135,7 @@ public class AiolCommentController extends JeecgController<AiolComment, IAiolCom
*/ */
@AutoLog(value = "评论-通过id删除") @AutoLog(value = "评论-通过id删除")
@Operation(summary = "评论-通过id删除") @Operation(summary = "评论-通过id删除")
@RequiresPermissions("aiol:aiol_comment:delete") // @RequiresPermissions("aiol:aiol_comment: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) {
aiolCommentService.removeById(id); aiolCommentService.removeById(id);

View File

@ -12,22 +12,29 @@ import org.jeecg.common.api.vo.Result;
import org.apache.shiro.SecurityUtils; import org.apache.shiro.SecurityUtils;
import org.jeecg.common.system.vo.LoginUser; import org.jeecg.common.system.vo.LoginUser;
import org.springframework.web.bind.annotation.RequestParam; 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.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 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.model.AnnouncementSendModel;
import org.jeecg.modules.system.service.ISysAnnouncementSendService; import org.jeecg.modules.system.service.ISysAnnouncementSendService;
import org.jeecg.modules.system.entity.SysAnnouncementSend; import org.jeecg.modules.system.entity.SysAnnouncementSend;
import org.jeecg.modules.system.entity.SysAnnouncement; import org.jeecg.modules.system.entity.SysAnnouncement;
import org.jeecg.modules.system.service.ISysAnnouncementService; import org.jeecg.modules.system.service.ISysAnnouncementService;
import org.jeecg.common.constant.CommonConstant;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Date;
import lombok.extern.slf4j.Slf4j;
@RestController @RestController
@RequestMapping("/aiol/message") @RequestMapping("/aiol/message")
@Slf4j
public class AiolMessageController { public class AiolMessageController {
@Autowired @Autowired
private ISysBaseAPI sysBaseApi; private ISysBaseAPI sysBaseApi;
@ -215,4 +222,42 @@ public class AiolMessageController {
return Result.error("查询未读消息数量失败: " + e.getMessage()); return Result.error("查询未读消息数量失败: " + e.getMessage());
} }
} }
/**
* @功能标记单条消息已读
* @param sendId 消息发送记录ID
* @return
*/
@GetMapping(value = "/readOne")
public Result<SysAnnouncementSend> readOne(@RequestParam(name = "sendId", required = true) String sendId) {
Result<SysAnnouncementSend> result = new Result<SysAnnouncementSend>();
try {
if (StringUtils.isEmpty(sendId)) {
result.error500("消息ID不能为空");
return result;
}
// 构建更新条件根据sendId和userId更新单条消息
LambdaUpdateWrapper<SysAnnouncementSend> updateWrapper = new UpdateWrapper<SysAnnouncementSend>().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;
}
}
} }