From 279ccc57d10562dc6f3335ee575b61292fa62bda Mon Sep 17 00:00:00 2001 From: chenyuan Date: Thu, 2 Jul 2026 20:04:56 +0800 Subject: [PATCH] feat: open admin classes to school teachers --- .../controller/stu/UserController.java | 906 +++++++++++++++++- .../entity/dto/SchoolClassDto.java | 15 + .../TeachingClassStudentImportDTO.java | 40 + .../mapper/TeachingClassStudentMapper.java | 19 + .../service/impl/SchoolServiceImpl.java | 65 +- .../mappers/TeachingClassStudentMapper.xml | 59 ++ 6 files changed, 1051 insertions(+), 53 deletions(-) create mode 100644 src/main/java/com/sztzjy/linkCommerce/entity/importDto/TeachingClassStudentImportDTO.java diff --git a/src/main/java/com/sztzjy/linkCommerce/controller/stu/UserController.java b/src/main/java/com/sztzjy/linkCommerce/controller/stu/UserController.java index 92e60e4..0c37fb3 100644 --- a/src/main/java/com/sztzjy/linkCommerce/controller/stu/UserController.java +++ b/src/main/java/com/sztzjy/linkCommerce/controller/stu/UserController.java @@ -10,7 +10,9 @@ import com.sztzjy.linkCommerce.entity.*; import com.sztzjy.linkCommerce.entity.dto.SchoolClassDto; import com.sztzjy.linkCommerce.entity.dto.SchoolFacultyDto; import com.sztzjy.linkCommerce.entity.dto.SchoolMajorDto; +import com.sztzjy.linkCommerce.entity.importDto.SchoolAdminStudentImportDTO; import com.sztzjy.linkCommerce.entity.importDto.StudentImportDTO; +import com.sztzjy.linkCommerce.entity.importDto.TeachingClassStudentImportDTO; import com.sztzjy.linkCommerce.entity.importDto.TeacherImportDTO; import com.sztzjy.linkCommerce.mapper.*; import com.sztzjy.linkCommerce.service.ImportService; @@ -25,6 +27,7 @@ import io.swagger.annotations.ApiParam; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; +import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; @@ -50,6 +53,8 @@ public class UserController { @Autowired TeachingClassStudentMapper teachingClassStudentMapper; @Autowired + CptfController cptfController; + @Autowired Pinyin4jUtil pinyin4jUtil; @Autowired UserInfoService userInfoService; @@ -367,7 +372,8 @@ public class UserController { @ApiParam("班级名称") @RequestParam String className, @RequestParam(required = false) String userId, @RequestParam(required = false) String classType, - @RequestParam(required = false) String sourceClassIds) { + @RequestParam(required = false) String sourceClassIds, + @RequestParam(required = false, defaultValue = "false") Boolean confirmMultiTeachingClass) { //先根据schoolId进行查询 如果不存在则返回 School school = schoolMapper.selectByPrimaryKey(schoolId); if (school == null) { @@ -384,6 +390,10 @@ public class UserController { return new ResultEntity<>(HttpStatus.BAD_REQUEST, "该专业不存在"); } //查询班级名称是否存在 + String requestedClassType = StringUtils.defaultIfBlank(classType, StringUtils.isBlank(userId) ? "ADMIN" : "TEACHING"); + if (!canCreateSchoolClass(userId, schoolId, requestedClassType)) { + return new ResultEntity<>(HttpStatus.BAD_REQUEST, "No permission to add this class type"); + } SchoolClassExample schoolClassExample = new SchoolClassExample(); schoolClassExample.createCriteria().andSchoolIdEqualTo(schoolId).andClassNameEqualTo(className); List schoolClasses = schoolClassMapper.selectByExample(schoolClassExample); @@ -402,12 +412,21 @@ public class UserController { schoolClass.setCreateTime(new Date()); schoolClass.setSchoolId(schoolId); schoolClass.setCreatedBy(userId); - schoolClass.setClassType(StringUtils.defaultIfBlank(classType, StringUtils.isBlank(userId) ? "ADMIN" : "TEACHING")); + schoolClass.setClassType(requestedClassType); schoolClass.setDataSource("LOCAL"); schoolClass.setSourceClassIds(sourceClassIds); + if ("TEACHING".equals(schoolClass.getClassType()) && !Boolean.TRUE.equals(confirmMultiTeachingClass)) { + ResultEntity conflict = buildMultiTeachingClassConflict( + findStudentsByAdminClassIds(parseSourceClassIds(sourceClassIds)), ""); + if (conflict != null) { + return conflict; + } + } + int insert = schoolClassMapper.insert(schoolClass); if (insert == 1) { + createTeachingClassMembersFromSourceClasses(schoolClass); return new ResultEntity<>(HttpStatus.OK, "新增班级成功"); } else { return new ResultEntity<>(HttpStatus.BAD_REQUEST, "新增班级失败"); @@ -471,26 +490,17 @@ public class UserController { return new ResultEntity<>(HttpStatus.BAD_REQUEST, "班级管理-删除失败-权限不足"); } SchoolClass schoolClass = schoolClassMapper.selectByPrimaryKey(schoolClassId); + if (!canModifySchoolClass(userInfo, schoolClass)) { + return new ResultEntity<>(HttpStatus.BAD_REQUEST, "班级管理-删除失败-权限不足"); + } if (classHasStudents(schoolClass)) { return new ResultEntity<>(HttpStatus.BAD_REQUEST, "班级下存在学生,不能删除"); } - if (userInfo.getRole() == 1) { - int i = schoolClassMapper.deleteByPrimaryKey(schoolClassId); - if (i == 1) { - return new ResultEntity<>(HttpStatus.OK, "班级管理-删除成功"); - } - return new ResultEntity<>(HttpStatus.BAD_REQUEST, "班级管理-删除失败"); - } - if (userInfo.getRole() == 3) { - if (isClassOwner(schoolClass, userId)) { - int i = schoolClassMapper.deleteByPrimaryKey(schoolClassId); - if (i == 1) { - return new ResultEntity<>(HttpStatus.OK, "班级管理-删除成功"); - } - return new ResultEntity<>(HttpStatus.BAD_REQUEST, "班级管理-删除失败"); - } + int i = schoolClassMapper.deleteByPrimaryKey(schoolClassId); + if (i == 1) { + return new ResultEntity<>(HttpStatus.OK, "班级管理-删除成功"); } - return new ResultEntity<>(HttpStatus.BAD_REQUEST, "班级管理-删除失败-权限不足"); + return new ResultEntity<>(HttpStatus.BAD_REQUEST, "班级管理-删除失败"); } @@ -506,25 +516,19 @@ public class UserController { if (userInfo == null) { return new ResultEntity<>(HttpStatus.BAD_REQUEST, "班级管理-编辑失败-权限不足"); } - if (userInfo.getRole() == 1) { - int i = schoolClassMapper.updateByPrimaryKeySelective(schoolClass); - if (i == 1) { - return new ResultEntity<>(HttpStatus.OK, "班级管理-编辑成功"); - } - return new ResultEntity<>(HttpStatus.BAD_REQUEST, "班级管理-编辑成功"); - } - if (userInfo.getRole() == 3) { - SchoolClass schoolClass1 = schoolClassMapper.selectByPrimaryKey(schoolClass.getSchoolClassId()); - if (isClassOwner(schoolClass1, userId)) { - schoolClass.setCreatedBy(userId); - int i = schoolClassMapper.updateByPrimaryKeySelective(schoolClass); - if (i == 1) { - return new ResultEntity<>(HttpStatus.OK, "班级管理-编辑成功"); - } - return new ResultEntity<>(HttpStatus.BAD_REQUEST, "班级管理-编辑失败"); - } + SchoolClass existingClass = schoolClassMapper.selectByPrimaryKey(schoolClass.getSchoolClassId()); + if (!canModifySchoolClass(userInfo, existingClass)) { + return new ResultEntity<>(HttpStatus.BAD_REQUEST, "班级管理-编辑失败-权限不足"); + } + schoolClass.setCreatedBy(existingClass.getCreatedBy()); + if (isClassOwner(existingClass, userId)) { + schoolClass.setCreatedBy(userId); } - return new ResultEntity<>(HttpStatus.BAD_REQUEST, "班级管理-编辑失败-权限不足"); + int i = schoolClassMapper.updateByPrimaryKeySelective(schoolClass); + if (i == 1) { + return new ResultEntity<>(HttpStatus.OK, "班级管理-编辑成功"); + } + return new ResultEntity<>(HttpStatus.BAD_REQUEST, "班级管理-编辑失败"); } //新增 同步子系统账户 @@ -830,16 +834,7 @@ public class UserController { int insert = userinfoMapper.insert(userInfo); if (insert == 1) { if ("TEACHING".equals(schoolClass.getClassType()) && teachingClassStudentMapper != null) { - TeachingClassStudent member = new TeachingClassStudent(); - member.setId(UUID.randomUUID().toString()); - member.setTeachingClassId(schoolClassId); - member.setStudentUserId(userInfo.getUserId()); - member.setAdminClassId(adminClassId); - member.setStatus("IN_PROGRESS"); - member.setJoinReason("MANUAL"); - member.setJoinTime(new Date()); - member.setCreateTime(new Date()); - teachingClassStudentMapper.insertSelective(member); + upsertActiveTeachingClassMember(schoolClassId, userInfo, adminClassId, "MANUAL"); } return new ResultEntity<>(HttpStatus.OK, "学生管理-添加学生账号成功"); } else { @@ -918,13 +913,18 @@ public class UserController { @PostMapping("/updateStudent") @ApiOperation("学生管理-编辑学生账号信息") @AnonymousAccess - public ResultEntity updateStudent(@RequestBody Userinfo userInfo, @RequestParam(required = false) String operatorId) { + public ResultEntity updateStudent(@RequestBody Userinfo userInfo, + @RequestParam(required = false) String operatorId, + @RequestParam(required = false) String teachingClassId) { String targetClassId = userInfo.getSchoolClassId(); if (StringUtils.isBlank(targetClassId) && StringUtils.isNotBlank(userInfo.getUserId())) { Userinfo existing = userinfoMapper.selectByPrimaryKey(userInfo.getUserId()); targetClassId = existing == null ? null : existing.getSchoolClassId(); } - if (!canOperateClass(operatorId, targetClassId)) { + boolean canOperate = StringUtils.isNotBlank(teachingClassId) + ? canOperateStudent(operatorId, userInfo.getUserId(), teachingClassId) + : canOperateClass(operatorId, targetClassId); + if (!canOperate) { return new ResultEntity<>(HttpStatus.BAD_REQUEST, "只能维护自己创建班级的学生"); } int i = userinfoMapper.updateByPrimaryKey(userInfo); @@ -938,10 +938,19 @@ public class UserController { @PostMapping("/deleteStudent") @ApiOperation("学生管理-删除") @AnonymousAccess - public ResultEntity deleteStudent(@RequestParam String userId, @RequestParam(required = false) String operatorId) { - if (!canOperateStudent(operatorId, userId)) { + public ResultEntity deleteStudent(@RequestParam String userId, + @RequestParam(required = false) String operatorId, + @RequestParam(required = false) String teachingClassId) { + if (!canOperateStudent(operatorId, userId, teachingClassId)) { return new ResultEntity<>(HttpStatus.BAD_REQUEST, "只能维护自己创建班级的学生"); } + if (StringUtils.isNotBlank(teachingClassId)) { + int removed = teachingClassStudentMapper.deleteByStudentUserIdAndTeachingClassId(userId, teachingClassId); + if (removed >= 1) { + return new ResultEntity<>(HttpStatus.OK, "删除成功!"); + } + return new ResultEntity<>(HttpStatus.BAD_REQUEST, "删除失败!"); + } int i = userinfoMapper.deleteByPrimaryKey(userId); if (i == 1) { return new ResultEntity<>(HttpStatus.OK, "删除成功!"); @@ -953,8 +962,10 @@ public class UserController { @PostMapping("/updateStudentPassword") @ApiOperation("学生管理-初始化密码") @AnonymousAccess - public ResultEntity updateStudentPassword(@RequestParam String userId, @RequestParam(required = false) String operatorId) { - if (!canOperateStudent(operatorId, userId)) { + public ResultEntity updateStudentPassword(@RequestParam String userId, + @RequestParam(required = false) String operatorId, + @RequestParam(required = false) String teachingClassId) { + if (!canOperateStudent(operatorId, userId, teachingClassId)) { return new ResultEntity<>(HttpStatus.BAD_REQUEST, "只能维护自己创建班级的学生"); } Userinfo userInfo = userinfoMapper.selectByPrimaryKey(userId); @@ -975,6 +986,15 @@ public class UserController { if (!isOwnedTeachingClass(schoolClass, operatorId)) { return new ResultEntity<>(HttpStatus.BAD_REQUEST, "只能初始化自己创建的教学班"); } + List members = teachingClassStudentMapper.selectByTeachingClassId(teachingClassId); + if (members == null) { + members = Collections.emptyList(); + } + for (TeachingClassStudent member : members) { + if (member != null && StringUtils.isNotBlank(member.getStudentUserId())) { + cptfController.restartByUserId(member.getStudentUserId()); + } + } return new ResultEntity<>(HttpStatus.OK, "教学班实训数据初始化成功"); } @@ -992,9 +1012,263 @@ public class UserController { && teachingClassStudentMapper.countByStudentUserIdAndTeachingClassId(studentUserId, teachingClassId) <= 0) { return new ResultEntity<>(HttpStatus.BAD_REQUEST, "学生不属于该教学班"); } + cptfController.restartByUserId(studentUserId); return new ResultEntity<>(HttpStatus.OK, "学生实训数据初始化成功"); } + @PostMapping("/uploadTeachingClassStudentMembers") + @ApiOperation("教学班-导入学生成员") + @AnonymousAccess + public ResultEntity uploadTeachingClassStudentMembers(@RequestParam MultipartFile file, + @RequestParam String teachingClassId, + @RequestParam String operatorId, + @RequestParam(required = false, defaultValue = "false") Boolean confirmMultiTeachingClass) { + if (file.isEmpty()) { + return new ResultEntity<>(HttpStatus.BAD_REQUEST, "上传文件不能为空!"); + } + String originalFilename = file.getOriginalFilename(); + if (StringUtils.isBlank(originalFilename) + || (!originalFilename.endsWith(".xls") && !originalFilename.endsWith(".xlsx"))) { + return new ResultEntity<>(HttpStatus.BAD_REQUEST, "请上传Excel文件!"); + } + if (file.getSize() > 10 * 1024 * 1024) { + return new ResultEntity<>(HttpStatus.BAD_REQUEST, "文件大小不能超过10MB!"); + } + try (InputStream inputStream = file.getInputStream()) { + List rows = EasyExcel.read(inputStream) + .head(TeachingClassStudentImportDTO.class) + .sheet() + .doReadSync(); + return importTeachingClassStudentRows(rows, teachingClassId, operatorId, confirmMultiTeachingClass); + } catch (Exception e) { + return new ResultEntity<>(HttpStatus.BAD_REQUEST, "数据校验失败!", e.getMessage()); + } + } + + @PostMapping("/importTeacherStudents") + @ApiOperation("教师端-批量导入学生账号") + @AnonymousAccess + @Transactional(rollbackFor = Exception.class) + public ResultEntity importTeacherStudents(@RequestParam MultipartFile file, + @RequestParam String operatorId) { + ResultEntity fileError = validateTeacherStudentImportFile(file); + if (fileError != null) { + return fileError; + } + try (InputStream inputStream = file.getInputStream()) { + List rows = EasyExcel.read(inputStream) + .head(SchoolAdminStudentImportDTO.class) + .sheet() + .doReadSync(); + return importTeacherStudentRows(rows, operatorId); + } catch (Exception e) { + return new ResultEntity<>(HttpStatus.BAD_REQUEST, "数据校验失败:", e.getMessage()); + } + } + + ResultEntity importTeacherStudentRows(List rows, String operatorId) { + Userinfo operator = userinfoMapper.selectByPrimaryKey(operatorId); + if (!isSchoolTeacher(operator)) { + return new ResultEntity<>(HttpStatus.BAD_REQUEST, "权限不足"); + } + List errors = new ArrayList<>(); + List students = buildTeacherImportStudents(rows, operator, errors); + if (!errors.isEmpty()) { + return new ResultEntity<>(HttpStatus.BAD_REQUEST, "数据校验失败", errors); + } + if (students.isEmpty()) { + return new ResultEntity<>(HttpStatus.BAD_REQUEST, "未读取到可导入的学生数据"); + } + for (Userinfo student : students) { + int inserted = userinfoMapper.insertSelective(student); + if (inserted <= 0) { + throw new IllegalStateException("导入失败"); + } + } + return new ResultEntity<>(HttpStatus.OK, "导入成功,共 " + students.size() + " 条"); + } + + ResultEntity addSchoolClass(String schoolId, + String schoolFacultyId, + String schoolMajorId, + String className, + String userId, + String classType, + String sourceClassIds) { + return addSchoolClass(schoolId, schoolFacultyId, schoolMajorId, className, + userId, classType, sourceClassIds, false); + } + + @PostMapping("/uploadTeachingClassByStudentMembers") + @ApiOperation("教学班-导入名单创建教学班") + @AnonymousAccess + public ResultEntity uploadTeachingClassByStudentMembers(@RequestParam MultipartFile file, + @RequestParam String schoolId, + @RequestParam String schoolFacultyId, + @RequestParam String schoolMajorId, + @RequestParam String className, + @RequestParam String operatorId, + @RequestParam(required = false) String sourceClassIds, + @RequestParam(required = false, defaultValue = "false") Boolean confirmMultiTeachingClass) { + if (file.isEmpty()) { + return new ResultEntity<>(HttpStatus.BAD_REQUEST, "上传文件不能为空!"); + } + String originalFilename = file.getOriginalFilename(); + if (StringUtils.isBlank(originalFilename) + || (!originalFilename.endsWith(".xls") && !originalFilename.endsWith(".xlsx"))) { + return new ResultEntity<>(HttpStatus.BAD_REQUEST, "请上传Excel文件!"); + } + if (file.getSize() > 10 * 1024 * 1024) { + return new ResultEntity<>(HttpStatus.BAD_REQUEST, "文件大小不能超过10MB!"); + } + try (InputStream inputStream = file.getInputStream()) { + List rows = EasyExcel.read(inputStream) + .head(TeachingClassStudentImportDTO.class) + .sheet() + .doReadSync(); + return createTeachingClassByImportRows(rows, schoolId, schoolFacultyId, schoolMajorId, className, operatorId, sourceClassIds, confirmMultiTeachingClass); + } catch (Exception e) { + return new ResultEntity<>(HttpStatus.BAD_REQUEST, "数据校验失败!", e.getMessage()); + } + } + + ResultEntity importTeachingClassStudentRows(List rows, + String teachingClassId, + String operatorId) { + return importTeachingClassStudentRows(rows, teachingClassId, operatorId, false); + } + + ResultEntity importTeachingClassStudentRows(List rows, + String teachingClassId, + String operatorId, + Boolean confirmMultiTeachingClass) { + SchoolClass teachingClass = schoolClassMapper.selectByPrimaryKey(teachingClassId); + if (!isOwnedTeachingClass(teachingClass, operatorId)) { + return new ResultEntity<>(HttpStatus.BAD_REQUEST, "只能导入自己创建教学班的学生"); + } + List sourceClassIds = parseSourceClassIds(teachingClass.getSourceClassIds()); + SchoolMajor teachingMajor = schoolMajorMapper.selectByPrimaryKey(teachingClass.getSchoolMajorId()); + String teachingFacultyId = teachingMajor == null ? null : teachingMajor.getSchoolFacultyId(); + List errors = sourceClassIds.isEmpty() + ? validateTeachingClassImportRowsByMajor(rows, teachingClass.getSchoolId(), teachingFacultyId, teachingClass.getSchoolMajorId()) + : validateTeachingClassStudentRows(rows, teachingClass, sourceClassIds); + if (!errors.isEmpty()) { + return new ResultEntity<>(HttpStatus.BAD_REQUEST, "数据校验失败!", errors); + } + List studentsToAdd = new ArrayList<>(); + for (TeachingClassStudentImportDTO row : rows) { + Userinfo student = sourceClassIds.isEmpty() + ? findAdminClassStudent(row, teachingClass.getSchoolId(), teachingFacultyId, teachingClass.getSchoolMajorId()) + : findAdminClassStudent(row, teachingClass, sourceClassIds); + if (student == null) { + continue; + } + studentsToAdd.add(student); + } + for (Userinfo student : studentsToAdd) { + upsertActiveTeachingClassMember(teachingClassId, student, student.getSchoolClassId(), "IMPORT"); + } + return new ResultEntity<>(HttpStatus.OK, "导入成功!"); + } + + ResultEntity createTeachingClassByImportRows(List rows, + String schoolId, + String schoolFacultyId, + String schoolMajorId, + String className, + String operatorId) { + return createTeachingClassByImportRows(rows, schoolId, schoolFacultyId, schoolMajorId, className, operatorId, false); + } + + ResultEntity createTeachingClassByImportRows(List rows, + String schoolId, + String schoolFacultyId, + String schoolMajorId, + String className, + String operatorId, + Boolean confirmMultiTeachingClass) { + return createTeachingClassByImportRows(rows, schoolId, schoolFacultyId, schoolMajorId, className, operatorId, null, confirmMultiTeachingClass); + } + + ResultEntity createTeachingClassByImportRows(List rows, + String schoolId, + String schoolFacultyId, + String schoolMajorId, + String className, + String operatorId, + String selectedSourceClassIds, + Boolean confirmMultiTeachingClass) { + School school = schoolMapper.selectByPrimaryKey(schoolId); + if (school == null) { + return new ResultEntity<>(HttpStatus.BAD_REQUEST, "该学校不存在"); + } + SchoolFaculty schoolFaculty = schoolFacultyMapper.selectByPrimaryKey(schoolFacultyId); + if (schoolFaculty == null) { + return new ResultEntity<>(HttpStatus.BAD_REQUEST, "该院系不存在"); + } + SchoolMajor schoolMajor = schoolMajorMapper.selectByPrimaryKey(schoolMajorId); + if (schoolMajor == null) { + return new ResultEntity<>(HttpStatus.BAD_REQUEST, "该专业不存在"); + } + if (StringUtils.isBlank(className)) { + return new ResultEntity<>(HttpStatus.BAD_REQUEST, "班级名称不能为空"); + } + SchoolClassExample duplicateExample = new SchoolClassExample(); + duplicateExample.createCriteria().andSchoolIdEqualTo(schoolId).andClassNameEqualTo(className); + if (!schoolClassMapper.selectByExample(duplicateExample).isEmpty()) { + return new ResultEntity<>(HttpStatus.BAD_REQUEST, "班级名称重复"); + } + List selectedSourceClassIdList = parseSourceClassIds(selectedSourceClassIds); + List errors = selectedSourceClassIdList.isEmpty() + ? validateTeachingClassImportRowsByMajor(rows, schoolId, schoolFacultyId, schoolMajorId) + : validateTeachingClassImportRowsBySourceClasses(rows, schoolId, schoolFacultyId, schoolMajorId, selectedSourceClassIdList); + if (!errors.isEmpty()) { + return new ResultEntity<>(HttpStatus.BAD_REQUEST, "数据校验失败!", errors); + } + + List importedStudents = new ArrayList<>(); + LinkedHashSet sourceClassIds = new LinkedHashSet<>(); + SchoolClass importScope = new SchoolClass(); + importScope.setSchoolId(schoolId); + for (TeachingClassStudentImportDTO row : rows) { + Userinfo student = selectedSourceClassIdList.isEmpty() + ? findAdminClassStudent(row, schoolId, schoolFacultyId, schoolMajorId) + : findAdminClassStudent(row, importScope, selectedSourceClassIdList); + if (student == null) { + continue; + } + importedStudents.add(student); + if (StringUtils.isNotBlank(student.getSchoolClassId())) { + sourceClassIds.add(student.getSchoolClassId()); + } + } + if (!selectedSourceClassIdList.isEmpty()) { + sourceClassIds.clear(); + sourceClassIds.addAll(selectedSourceClassIdList); + } + + SchoolClass teachingClass = new SchoolClass(); + teachingClass.setSchoolClassId(UUID.randomUUID().toString()); + teachingClass.setSchoolId(schoolId); + teachingClass.setSchoolMajorId(schoolMajorId); + teachingClass.setClassName(className); + teachingClass.setClassSn(pinyin4jUtil.convertToPinyin(school.getSchoolName()) + "_" + pinyin4jUtil.convertToPinyin(className)); + teachingClass.setCreateTime(new Date()); + teachingClass.setCreatedBy(operatorId); + teachingClass.setClassType("TEACHING"); + teachingClass.setDataSource("LOCAL"); + teachingClass.setSourceClassIds(String.join(",", sourceClassIds)); + int insert = schoolClassMapper.insert(teachingClass); + if (insert != 1) { + return new ResultEntity<>(HttpStatus.BAD_REQUEST, "新增班级失败"); + } + + for (Userinfo student : importedStudents) { + upsertActiveTeachingClassMember(teachingClass.getSchoolClassId(), student, student.getSchoolClassId(), "IMPORT_CREATE"); + } + return new ResultEntity<>(HttpStatus.OK, "导入创建教学班成功"); + } + //微信绑定***** //导入 ***** 创建资金账户 @PostMapping("/uploadStudentUserInfo") @@ -1183,6 +1457,468 @@ public class UserController { && StringUtils.equals(schoolClass.getCreatedBy(), userId); } + private boolean isAdminClass(SchoolClass schoolClass) { + return schoolClass != null + && ("ADMIN".equals(schoolClass.getClassType()) + || (StringUtils.isBlank(schoolClass.getClassType()) && StringUtils.isBlank(schoolClass.getCreatedBy()))); + } + + private void upsertActiveTeachingClassMember(String teachingClassId, + Userinfo student, + String adminClassId, + String joinReason) { + if (teachingClassStudentMapper == null + || StringUtils.isBlank(teachingClassId) + || student == null + || StringUtils.isBlank(student.getUserId())) { + return; + } + teachingClassStudentMapper.exitActiveByStudentUserIdExceptClass(student.getUserId(), teachingClassId); + TeachingClassStudent existing = teachingClassStudentMapper + .selectByStudentUserIdAndTeachingClassId(student.getUserId(), teachingClassId); + if (existing != null) { + teachingClassStudentMapper.updateMembershipToActive( + student.getUserId(), + teachingClassId, + adminClassId, + joinReason); + return; + } + TeachingClassStudent member = new TeachingClassStudent(); + Date now = new Date(); + member.setId(UUID.randomUUID().toString()); + member.setTeachingClassId(teachingClassId); + member.setStudentUserId(student.getUserId()); + member.setAdminClassId(adminClassId); + member.setStatus("IN_PROGRESS"); + member.setJoinReason(joinReason); + member.setJoinTime(now); + member.setCreateTime(now); + teachingClassStudentMapper.insertSelective(member); + } + + private boolean canModifySchoolClass(Userinfo operator, SchoolClass schoolClass) { + if (operator == null || schoolClass == null) { + return false; + } + if ("ZHIYUN".equals(schoolClass.getDataSource())) { + return false; + } + if (isPlatformAdmin(operator)) { + return true; + } + if (!Integer.valueOf(3).equals(operator.getRole())) { + return false; + } + if (isAdminClass(schoolClass)) { + return canManageAdminClass(operator, schoolClass); + } + return isClassOwner(schoolClass, operator.getUserId()); + } + + private ResultEntity buildMultiTeachingClassConflict(List students, String targetTeachingClassId) { + if (students == null || students.isEmpty()) { + return null; + } + List conflicts = new ArrayList<>(); + Set studentIds = new HashSet<>(); + for (Userinfo student : students) { + if (student == null || StringUtils.isBlank(student.getUserId()) || !studentIds.add(student.getUserId())) { + continue; + } + if (teachingClassStudentMapper.countByStudentUserIdExcludingTeachingClass( + student.getUserId(), StringUtils.trimToEmpty(targetTeachingClassId)) > 0) { + conflicts.add(formatStudentConflict(student)); + } + } + if (conflicts.isEmpty()) { + return null; + } + return new ResultEntity<>(HttpStatus.CONFLICT, "部分学生已在其他教学班,确认后可继续操作", conflicts); + } + + private String formatStudentConflict(Userinfo student) { + String name = StringUtils.defaultIfBlank(student.getName(), "未命名学生"); + String username = StringUtils.defaultIfBlank(student.getUsername(), "-"); + return name + "(" + username + ")"; + } + + private List findStudentsByAdminClassIds(List sourceClassIds) { + if (sourceClassIds == null || sourceClassIds.isEmpty()) { + return Collections.emptyList(); + } + UserinfoExample example = new UserinfoExample(); + example.createCriteria() + .andRoleEqualTo(4) + .andSchoolClassIdIn(sourceClassIds); + List students = userinfoMapper.selectByExample(example); + return students == null ? Collections.emptyList() : students; + } + + private void createTeachingClassMembersFromSourceClasses(SchoolClass teachingClass) { + if (teachingClassStudentMapper == null + || teachingClass == null + || !"TEACHING".equals(teachingClass.getClassType()) + || StringUtils.isBlank(teachingClass.getSourceClassIds())) { + return; + } + List sourceClassIds = parseSourceClassIds(teachingClass.getSourceClassIds()); + if (sourceClassIds.isEmpty()) { + return; + } + List students = findStudentsByAdminClassIds(sourceClassIds); + for (Userinfo student : students) { + if (student == null || StringUtils.isBlank(student.getUserId())) { + continue; + } + upsertActiveTeachingClassMember(teachingClass.getSchoolClassId(), student, student.getSchoolClassId(), "ADMIN_CLASS_MERGE"); + } + } + + private List validateTeachingClassStudentRows(List rows, + SchoolClass teachingClass, + List sourceClassIds) { + List errors = new ArrayList<>(); + if (rows == null || rows.isEmpty()) { + errors.add("Excel中没有数据"); + return errors; + } + Set rowKeys = new HashSet<>(); + for (int i = 0; i < rows.size(); i++) { + TeachingClassStudentImportDTO row = rows.get(i); + int rowNum = i + 2; + String studentName = row == null ? "" : StringUtils.trimToEmpty(row.getStudentName()); + String userName = row == null ? "" : StringUtils.trimToEmpty(row.getUserName()); + if (StringUtils.isBlank(studentName)) { + errors.add("第" + rowNum + "行 学生姓名不能为空"); + } + if (StringUtils.isBlank(userName)) { + errors.add("第" + rowNum + "行 学号不能为空"); + } + if (StringUtils.isBlank(studentName) || StringUtils.isBlank(userName)) { + continue; + } + String rowKey = studentName + "#" + userName; + if (!rowKeys.add(rowKey)) { + errors.add("第" + rowNum + "行 学生姓名和学号重复"); + continue; + } + Userinfo student = findAdminClassStudent(row, teachingClass, sourceClassIds); + if (student == null) { + errors.add("第" + rowNum + "行 学生姓名与学号未匹配到来源行政班学生"); + } + } + return errors; + } + + private Userinfo findAdminClassStudent(TeachingClassStudentImportDTO row, + SchoolClass teachingClass, + List sourceClassIds) { + if (row == null || teachingClass == null || sourceClassIds == null || sourceClassIds.isEmpty()) { + return null; + } + UserinfoExample example = new UserinfoExample(); + example.createCriteria() + .andRoleEqualTo(4) + .andSchoolIdEqualTo(teachingClass.getSchoolId()) + .andNameEqualTo(StringUtils.trimToEmpty(row.getStudentName())) + .andUsernameEqualTo(StringUtils.trimToEmpty(row.getUserName())) + .andSchoolClassIdIn(sourceClassIds); + List students = userinfoMapper.selectByExample(example); + if (students == null || students.isEmpty()) { + return null; + } + return students.get(0); + } + + private List validateTeachingClassImportRowsByMajor(List rows, + String schoolId, + String schoolFacultyId, + String schoolMajorId) { + List errors = new ArrayList<>(); + if (rows == null || rows.isEmpty()) { + errors.add("Excel中没有数据"); + return errors; + } + Set rowKeys = new HashSet<>(); + for (int i = 0; i < rows.size(); i++) { + TeachingClassStudentImportDTO row = rows.get(i); + int rowNum = i + 2; + String studentName = row == null ? "" : StringUtils.trimToEmpty(row.getStudentName()); + String userName = row == null ? "" : StringUtils.trimToEmpty(row.getUserName()); + if (StringUtils.isBlank(studentName)) { + errors.add("第" + rowNum + "行 学生姓名不能为空"); + } + if (StringUtils.isBlank(userName)) { + errors.add("第" + rowNum + "行 学号不能为空"); + } + if (StringUtils.isBlank(studentName) || StringUtils.isBlank(userName)) { + continue; + } + String rowKey = studentName + "#" + userName; + if (!rowKeys.add(rowKey)) { + errors.add("第" + rowNum + "行 学生姓名和学号重复"); + continue; + } + if (StringUtils.isNotBlank(row.getSchoolClassName())) { + SchoolClass adminClass = findTeacherImportClass(schoolId, schoolMajorId, StringUtils.trimToEmpty(row.getSchoolClassName())); + if (adminClass == null || !"ADMIN".equals(adminClass.getClassType())) { + errors.add("第" + rowNum + "行 未匹配到行政班:" + row.getSchoolClassName()); + continue; + } + } + Userinfo student = findAdminClassStudent(row, schoolId, schoolFacultyId, schoolMajorId); + if (student == null) { + errors.add("第" + rowNum + "行 学生姓名与学号未匹配到该专业下的行政班学生"); + } + } + return errors; + } + + private List validateTeachingClassImportRowsBySourceClasses(List rows, + String schoolId, + String schoolFacultyId, + String schoolMajorId, + List sourceClassIds) { + List errors = new ArrayList<>(); + if (sourceClassIds == null || sourceClassIds.isEmpty()) { + errors.add("请选择来源行政班"); + return errors; + } + for (String sourceClassId : sourceClassIds) { + SchoolClass sourceClass = schoolClassMapper.selectByPrimaryKey(sourceClassId); + if (sourceClass == null) { + errors.add("来源行政班不存在"); + continue; + } + if (!"ADMIN".equals(sourceClass.getClassType()) + || !schoolId.equals(sourceClass.getSchoolId()) + || !schoolMajorId.equals(sourceClass.getSchoolMajorId())) { + errors.add("来源行政班不属于当前学校和专业"); + } + } + if (!errors.isEmpty()) { + return errors; + } + SchoolClass importScope = new SchoolClass(); + importScope.setSchoolId(schoolId); + List rowErrors = validateTeachingClassStudentRows(rows, importScope, sourceClassIds); + for (String rowError : rowErrors) { + errors.add(rowError.replace("来源行政班学生", "所选来源行政班学生")); + } + return errors; + } + + private Userinfo findAdminClassStudent(TeachingClassStudentImportDTO row, + String schoolId, + String schoolFacultyId, + String schoolMajorId) { + if (row == null) { + return null; + } + UserinfoExample example = new UserinfoExample(); + UserinfoExample.Criteria criteria = example.createCriteria() + .andRoleEqualTo(4) + .andSchoolIdEqualTo(schoolId) + .andSchoolFacultyIdEqualTo(schoolFacultyId) + .andSchoolMajorIdEqualTo(schoolMajorId) + .andNameEqualTo(StringUtils.trimToEmpty(row.getStudentName())) + .andUsernameEqualTo(StringUtils.trimToEmpty(row.getUserName())); + if (StringUtils.isNotBlank(row.getSchoolClassName())) { + SchoolClass adminClass = findTeacherImportClass(schoolId, schoolMajorId, StringUtils.trimToEmpty(row.getSchoolClassName())); + criteria.andSchoolClassIdEqualTo(adminClass == null ? "__missing__" : adminClass.getSchoolClassId()); + } + List students = userinfoMapper.selectByExample(example); + if (students == null || students.isEmpty()) { + return null; + } + return students.get(0); + } + + private ResultEntity validateTeacherStudentImportFile(MultipartFile file) { + if (file == null || file.isEmpty()) { + return new ResultEntity<>(HttpStatus.BAD_REQUEST, "请选择要导入的Excel文件"); + } + String filename = StringUtils.defaultString(file.getOriginalFilename()); + if (!StringUtils.endsWithIgnoreCase(filename, ".xls") && !StringUtils.endsWithIgnoreCase(filename, ".xlsx")) { + return new ResultEntity<>(HttpStatus.BAD_REQUEST, "仅支持xls或xlsx格式文件"); + } + if (file.getSize() > 10 * 1024 * 1024) { + return new ResultEntity<>(HttpStatus.BAD_REQUEST, "文件大小不能超过10MB"); + } + return null; + } + + private List buildTeacherImportStudents(List rows, + Userinfo operator, + List errors) { + List students = new ArrayList<>(); + Set usernames = new HashSet<>(); + if (rows == null) { + return students; + } + for (int i = 0; i < rows.size(); i++) { + SchoolAdminStudentImportDTO row = rows.get(i); + int rowNumber = i + 2; + if (isBlankTeacherStudentImportRow(row)) { + continue; + } + + String name = StringUtils.trimToEmpty(row.getName()); + String username = StringUtils.trimToEmpty(row.getUsername()); + String facultyName = StringUtils.trimToEmpty(row.getSchoolFacultyName()); + String majorName = StringUtils.trimToEmpty(row.getSchoolMajorName()); + String className = StringUtils.trimToEmpty(row.getSchoolClassName()); + String sex = normalizeTeacherImportSex(row.getSex()); + + if (StringUtils.isBlank(name)) { + errors.add("第" + rowNumber + "行:姓名不能为空"); + } + if (StringUtils.isBlank(username)) { + errors.add("第" + rowNumber + "行:学号不能为空"); + } else if (!usernames.add(username)) { + errors.add("第" + rowNumber + "行:学号在导入文件中重复"); + } else if (userInfoService.existsByUserName(username)) { + errors.add("第" + rowNumber + "行:账号已存在"); + } + if (StringUtils.isNotBlank(row.getSex()) && sex == null) { + errors.add("第" + rowNumber + "行:性别请填写男或女"); + } + if (StringUtils.isBlank(facultyName)) { + errors.add("第" + rowNumber + "行:所属院系不能为空"); + } + if (StringUtils.isBlank(majorName)) { + errors.add("第" + rowNumber + "行:所属专业不能为空"); + } + if (StringUtils.isBlank(className)) { + errors.add("第" + rowNumber + "行:所属班级不能为空"); + } + + SchoolFaculty faculty = StringUtils.isBlank(facultyName) ? null : findTeacherImportFaculty(operator.getSchoolId(), facultyName); + SchoolMajor major = null; + SchoolClass schoolClass = null; + if (StringUtils.isNotBlank(facultyName) && faculty == null) { + errors.add("第" + rowNumber + "行:未找到院系“" + facultyName + "”"); + } + if (faculty != null && StringUtils.isNotBlank(majorName)) { + major = findTeacherImportMajor(faculty.getSchoolFacultyId(), majorName); + if (major == null) { + errors.add("第" + rowNumber + "行:院系“" + facultyName + "”下未找到专业“" + majorName + "”"); + } + } + if (major != null && StringUtils.isNotBlank(className)) { + schoolClass = findTeacherImportClass(operator.getSchoolId(), major.getSchoolMajorId(), className); + if (schoolClass == null) { + errors.add("第" + rowNumber + "行:专业“" + majorName + "”下未找到班级“" + className + "”"); + } else if (!isAdminClass(schoolClass)) { + errors.add("第" + rowNumber + "行:学生账号只能导入行政班"); + } else if (!canManageAdminClass(operator, schoolClass)) { + errors.add("第" + rowNumber + "行:只能导入本校行政班"); + } + } + + if (!hasTeacherImportRowError(errors, rowNumber)) { + Userinfo student = new Userinfo(); + student.setUserId(UUID.randomUUID().toString()); + student.setName(name); + student.setUsername(username); + student.setPassword("123qwe"); + student.setSex(StringUtils.defaultString(sex)); + student.setPhone(StringUtils.trimToEmpty(row.getPhone())); + student.setEmail(StringUtils.trimToEmpty(row.getEmail())); + student.setRole(4); + student.setSchoolId(operator.getSchoolId()); + student.setSchoolFacultyId(faculty.getSchoolFacultyId()); + student.setSchoolMajorId(major.getSchoolMajorId()); + student.setSchoolClassId(schoolClass.getSchoolClassId()); + student.setCreateTime(new Date()); + student.setCodeFrom("Excel导入"); + students.add(student); + } + } + return students; + } + + private boolean isBlankTeacherStudentImportRow(SchoolAdminStudentImportDTO row) { + if (row == null) { + return true; + } + return StringUtils.isBlank(row.getName()) + && StringUtils.isBlank(row.getUsername()) + && StringUtils.isBlank(row.getSex()) + && StringUtils.isBlank(row.getSchoolFacultyName()) + && StringUtils.isBlank(row.getSchoolMajorName()) + && StringUtils.isBlank(row.getSchoolClassName()) + && StringUtils.isBlank(row.getPhone()) + && StringUtils.isBlank(row.getEmail()); + } + + private String normalizeTeacherImportSex(String sex) { + String value = StringUtils.trimToEmpty(sex); + if (StringUtils.isBlank(value)) { + return ""; + } + if ("1".equals(value) || "男".equals(value) || "男性".equals(value)) { + return "男"; + } + if ("2".equals(value) || "女".equals(value) || "女性".equals(value)) { + return "女"; + } + return null; + } + + private boolean hasTeacherImportRowError(List errors, int rowNumber) { + String prefix = "第" + rowNumber + "行:"; + for (String error : errors) { + if (error.startsWith(prefix)) { + return true; + } + } + return false; + } + + private SchoolFaculty findTeacherImportFaculty(String schoolId, String facultyName) { + SchoolFacultyExample example = new SchoolFacultyExample(); + example.createCriteria() + .andSchoolIdEqualTo(schoolId) + .andSchoolFacultyNameEqualTo(facultyName); + List faculties = schoolFacultyMapper.selectByExample(example); + return faculties.isEmpty() ? null : faculties.get(0); + } + + private SchoolMajor findTeacherImportMajor(String facultyId, String majorName) { + SchoolMajorExample example = new SchoolMajorExample(); + example.createCriteria() + .andSchoolFacultyIdEqualTo(facultyId) + .andSchoolMajorNameEqualTo(majorName); + List majors = schoolMajorMapper.selectByExample(example); + return majors.isEmpty() ? null : majors.get(0); + } + + private SchoolClass findTeacherImportClass(String schoolId, String majorId, String className) { + SchoolClassExample example = new SchoolClassExample(); + example.createCriteria() + .andSchoolIdEqualTo(schoolId) + .andSchoolMajorIdEqualTo(majorId) + .andClassNameEqualTo(className); + List classes = schoolClassMapper.selectByExample(example); + return classes.isEmpty() ? null : classes.get(0); + } + + private List parseSourceClassIds(String sourceClassIds) { + List ids = new ArrayList<>(); + if (StringUtils.isBlank(sourceClassIds)) { + return ids; + } + for (String sourceClassId : sourceClassIds.split(",")) { + String trimmed = StringUtils.trimToEmpty(sourceClassId); + if (StringUtils.isNotBlank(trimmed) && !ids.contains(trimmed)) { + ids.add(trimmed); + } + } + return ids; + } + private ResultEntity noManagePermission() { return new ResultEntity<>(HttpStatus.BAD_REQUEST, "权限不足"); } @@ -1191,12 +1927,50 @@ public class UserController { return userInfo != null && Integer.valueOf(1).equals(userInfo.getRole()); } + private boolean canCreateSchoolClass(String operatorId, String schoolId, String classType) { + if (StringUtils.isAnyBlank(operatorId, schoolId, classType)) { + return false; + } + Userinfo operator = userinfoMapper.selectByPrimaryKey(operatorId); + if (isPlatformAdmin(operator)) { + return true; + } + if (!Integer.valueOf(3).equals(operator == null ? null : operator.getRole()) + || !StringUtils.equals(operator.getSchoolId(), schoolId)) { + return false; + } + if ("TEACHING".equals(classType)) { + return true; + } + if ("ADMIN".equals(classType)) { + return true; + } + return false; + } + private boolean isTeacherAdmin(Userinfo userInfo) { return userInfo != null && Integer.valueOf(3).equals(userInfo.getRole()) && Boolean.TRUE.equals(userInfo.getTeacherAdmin()); } + private boolean isSchoolTeacher(Userinfo userInfo) { + return userInfo != null + && Integer.valueOf(3).equals(userInfo.getRole()) + && StringUtils.isNotBlank(userInfo.getSchoolId()); + } + + private boolean canManageAdminClass(Userinfo operator, SchoolClass schoolClass) { + if (operator == null || !isAdminClass(schoolClass)) { + return false; + } + if (isPlatformAdmin(operator)) { + return true; + } + return isSchoolTeacher(operator) + && StringUtils.equals(operator.getSchoolId(), schoolClass.getSchoolId()); + } + private boolean canManageSchoolStructure(String operatorId, String schoolId) { if (StringUtils.isAnyBlank(operatorId, schoolId)) { return false; @@ -1238,17 +2012,45 @@ public class UserController { return false; } SchoolClass schoolClass = schoolClassMapper.selectByPrimaryKey(schoolClassId); + if (canManageAdminClass(operator, schoolClass)) { + return true; + } return isClassOwner(schoolClass, operatorId); } private boolean canOperateStudent(String operatorId, String studentId) { + return canOperateStudent(operatorId, studentId, null); + } + + private boolean canOperateStudent(String operatorId, String studentId, String teachingClassId) { Userinfo student = userinfoMapper.selectByPrimaryKey(studentId); if (student == null || !Integer.valueOf(4).equals(student.getRole())) { return false; } + if (StringUtils.isNotBlank(teachingClassId)) { + SchoolClass teachingClass = schoolClassMapper.selectByPrimaryKey(teachingClassId); + return "TEACHING".equals(teachingClass == null ? null : teachingClass.getClassType()) + && canOperateClass(operatorId, teachingClassId) + && teachingClassStudentMapper != null + && teachingClassStudentMapper.countByStudentUserIdAndTeachingClassId(studentId, teachingClassId) > 0; + } return canOperateClass(operatorId, student.getSchoolClassId()); } + @PostMapping("/selectCurrentTeachingClass") + @ApiOperation("学生-查询当前在读教学班") + @AnonymousAccess + public ResultEntity selectCurrentTeachingClass(@RequestParam String userId) { + TeachingClassStudent member = teachingClassStudentMapper == null + ? null + : teachingClassStudentMapper.selectActiveByStudentUserId(userId); + if (member == null || StringUtils.isBlank(member.getTeachingClassId())) { + return new ResultEntity<>(HttpStatus.OK, "当前学生未分配在读教学班"); + } + SchoolClass teachingClass = schoolClassMapper.selectByPrimaryKey(member.getTeachingClassId()); + return new ResultEntity<>(HttpStatus.OK, "查询成功", teachingClass); + } + @ApiOperation("开放接口,自动同步学生信息") @PostMapping("synchronizationStudentInfoByAuto") @AnonymousAccess diff --git a/src/main/java/com/sztzjy/linkCommerce/entity/dto/SchoolClassDto.java b/src/main/java/com/sztzjy/linkCommerce/entity/dto/SchoolClassDto.java index 4ebc9d0..3d3dcf0 100644 --- a/src/main/java/com/sztzjy/linkCommerce/entity/dto/SchoolClassDto.java +++ b/src/main/java/com/sztzjy/linkCommerce/entity/dto/SchoolClassDto.java @@ -9,6 +9,21 @@ public class SchoolClassDto { @ApiModelProperty("学校名称") String schoolName; + @ApiModelProperty("faculty id") + String schoolFacultyId; + + @ApiModelProperty("faculty name") + String schoolFacultyName; + + @ApiModelProperty("major id") + String schoolMajorId; + + @ApiModelProperty("major name") + String schoolMajorName; + + @ApiModelProperty("creator name") + String createdByName; + @ApiModelProperty("schoolClass对象") SchoolClass schoolClass; } diff --git a/src/main/java/com/sztzjy/linkCommerce/entity/importDto/TeachingClassStudentImportDTO.java b/src/main/java/com/sztzjy/linkCommerce/entity/importDto/TeachingClassStudentImportDTO.java new file mode 100644 index 0000000..f2a6330 --- /dev/null +++ b/src/main/java/com/sztzjy/linkCommerce/entity/importDto/TeachingClassStudentImportDTO.java @@ -0,0 +1,40 @@ +package com.sztzjy.linkCommerce.entity.importDto; + +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class TeachingClassStudentImportDTO { + @ExcelProperty("所属院系") + @ApiModelProperty("所属院系") + private String schoolFacultyName; + + @ExcelProperty("所属专业") + @ApiModelProperty("所属专业") + private String schoolMajorName; + + @ExcelProperty("行政班") + @ApiModelProperty("行政班") + private String schoolClassName; + + @ExcelProperty("学生姓名") + @ApiModelProperty("学生姓名") + private String studentName; + + @ExcelProperty("学号") + @ApiModelProperty("学号") + private String userName; + + @ExcelProperty("性别") + @ApiModelProperty("性别") + private String sex; + + @ExcelProperty("手机号") + @ApiModelProperty("手机号") + private String phone; + + @ExcelProperty("邮箱") + @ApiModelProperty("邮箱") + private String email; +} diff --git a/src/main/java/com/sztzjy/linkCommerce/mapper/TeachingClassStudentMapper.java b/src/main/java/com/sztzjy/linkCommerce/mapper/TeachingClassStudentMapper.java index 5136095..373718b 100644 --- a/src/main/java/com/sztzjy/linkCommerce/mapper/TeachingClassStudentMapper.java +++ b/src/main/java/com/sztzjy/linkCommerce/mapper/TeachingClassStudentMapper.java @@ -13,9 +13,28 @@ public interface TeachingClassStudentMapper { long countByStudentUserIdAndTeachingClassId(@Param("studentUserId") String studentUserId, @Param("teachingClassId") String teachingClassId); + long countByStudentUserIdExcludingTeachingClass(@Param("studentUserId") String studentUserId, + @Param("teachingClassId") String teachingClassId); + int insertSelective(TeachingClassStudent record); + TeachingClassStudent selectActiveByStudentUserId(String studentUserId); + + TeachingClassStudent selectByStudentUserIdAndTeachingClassId(@Param("studentUserId") String studentUserId, + @Param("teachingClassId") String teachingClassId); + + int exitActiveByStudentUserIdExceptClass(@Param("studentUserId") String studentUserId, + @Param("teachingClassId") String teachingClassId); + + int updateMembershipToActive(@Param("studentUserId") String studentUserId, + @Param("teachingClassId") String teachingClassId, + @Param("adminClassId") String adminClassId, + @Param("joinReason") String joinReason); + int deleteByTeachingClassId(String teachingClassId); + int deleteByStudentUserIdAndTeachingClassId(@Param("studentUserId") String studentUserId, + @Param("teachingClassId") String teachingClassId); + List selectByTeachingClassId(String teachingClassId); } diff --git a/src/main/java/com/sztzjy/linkCommerce/service/impl/SchoolServiceImpl.java b/src/main/java/com/sztzjy/linkCommerce/service/impl/SchoolServiceImpl.java index dbe1ce7..acbf6e0 100644 --- a/src/main/java/com/sztzjy/linkCommerce/service/impl/SchoolServiceImpl.java +++ b/src/main/java/com/sztzjy/linkCommerce/service/impl/SchoolServiceImpl.java @@ -10,6 +10,7 @@ import com.sztzjy.linkCommerce.mapper.SchoolClassMapper; import com.sztzjy.linkCommerce.mapper.SchoolFacultyMapper; import com.sztzjy.linkCommerce.mapper.SchoolMajorMapper; import com.sztzjy.linkCommerce.mapper.SchoolMapper; +import com.sztzjy.linkCommerce.mapper.UserinfoMapper; import com.sztzjy.linkCommerce.service.SchoolService; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; @@ -17,6 +18,7 @@ import org.springframework.stereotype.Service; import java.util.Date; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.UUID; @@ -32,6 +34,8 @@ public class SchoolServiceImpl implements SchoolService { SchoolMajorMapper schoolMajorMapper; @Autowired SchoolClassMapper schoolClassMapper; + @Autowired + UserinfoMapper userinfoMapper; @Override public Integer addSchool(School school) { @@ -116,12 +120,71 @@ public class SchoolServiceImpl implements SchoolService { List schoolClasses = schoolClassMapper.selectByExample(schoolClassExample); // 将院系信息转换为 DTO + String schoolName = schoolMapper.selectSchoolNameById(schoolId); + List schoolMajorIds = schoolClasses.stream() + .map(SchoolClass::getSchoolMajorId) + .filter(StringUtils::isNotBlank) + .distinct() + .collect(Collectors.toList()); + List schoolMajors; + if (schoolMajorIds.isEmpty()) { + schoolMajors = Collections.emptyList(); + } else { + SchoolMajorExample schoolMajorExample = new SchoolMajorExample(); + schoolMajorExample.createCriteria().andSchoolMajorIdIn(schoolMajorIds); + schoolMajors = schoolMajorMapper.selectByExample(schoolMajorExample); + } + Map schoolMajorMap = schoolMajors.stream() + .collect(Collectors.toMap(SchoolMajor::getSchoolMajorId, schoolMajor -> schoolMajor, (left, right) -> left)); + List schoolFacultyIds = schoolMajors.stream() + .map(SchoolMajor::getSchoolFacultyId) + .filter(StringUtils::isNotBlank) + .distinct() + .collect(Collectors.toList()); + List schoolFaculties; + if (schoolFacultyIds.isEmpty()) { + schoolFaculties = Collections.emptyList(); + } else { + SchoolFacultyExample schoolFacultyExample = new SchoolFacultyExample(); + schoolFacultyExample.createCriteria().andSchoolFacultyIdIn(schoolFacultyIds); + schoolFaculties = schoolFacultyMapper.selectByExample(schoolFacultyExample); + } + Map schoolFacultyMap = schoolFaculties.stream() + .collect(Collectors.toMap(SchoolFaculty::getSchoolFacultyId, schoolFaculty -> schoolFaculty, (left, right) -> left)); + List createdByIds = schoolClasses.stream() + .map(SchoolClass::getCreatedBy) + .filter(StringUtils::isNotBlank) + .distinct() + .collect(Collectors.toList()); + List creators; + if (createdByIds.isEmpty()) { + creators = Collections.emptyList(); + } else { + UserinfoExample userinfoExample = new UserinfoExample(); + userinfoExample.createCriteria().andUserIdIn(createdByIds); + creators = userinfoMapper.selectByExample(userinfoExample); + } + Map creatorMap = creators.stream() + .collect(Collectors.toMap(Userinfo::getUserId, userinfo -> userinfo, (left, right) -> left)); List dtoList = schoolClasses.stream() .map(schoolClass -> { SchoolClassDto dto = new SchoolClassDto(); dto.setSchoolClass(schoolClass); - String schoolName = schoolMapper.selectSchoolNameById(schoolId); dto.setSchoolName(schoolName); + dto.setSchoolMajorId(schoolClass.getSchoolMajorId()); + SchoolMajor schoolMajor = schoolMajorMap.get(schoolClass.getSchoolMajorId()); + if (schoolMajor != null) { + dto.setSchoolMajorName(schoolMajor.getSchoolMajorName()); + dto.setSchoolFacultyId(schoolMajor.getSchoolFacultyId()); + SchoolFaculty schoolFaculty = schoolFacultyMap.get(schoolMajor.getSchoolFacultyId()); + if (schoolFaculty != null) { + dto.setSchoolFacultyName(schoolFaculty.getSchoolFacultyName()); + } + } + Userinfo creator = creatorMap.get(schoolClass.getCreatedBy()); + if (creator != null) { + dto.setCreatedByName(StringUtils.defaultIfBlank(creator.getName(), creator.getUsername())); + } return dto; }) .collect(Collectors.toList()); diff --git a/src/main/resources/mappers/TeachingClassStudentMapper.xml b/src/main/resources/mappers/TeachingClassStudentMapper.xml index 56ed34b..a7b999c 100644 --- a/src/main/resources/mappers/TeachingClassStudentMapper.xml +++ b/src/main/resources/mappers/TeachingClassStudentMapper.xml @@ -20,18 +20,48 @@ + + + + + + @@ -60,8 +90,37 @@ + + update teaching_class_student + set status = 'EXITED', + exit_time = CURRENT_TIMESTAMP + where student_user_id = #{studentUserId,jdbcType=VARCHAR} + and status = 'IN_PROGRESS' + and teaching_class_id != #{teachingClassId,jdbcType=VARCHAR} + + + + update teaching_class_student + set status = 'IN_PROGRESS', + admin_class_id = #{adminClassId,jdbcType=VARCHAR}, + join_reason = #{joinReason,jdbcType=VARCHAR}, + join_time = CURRENT_TIMESTAMP, + exit_time = null + where student_user_id = #{studentUserId,jdbcType=VARCHAR} + and teaching_class_id = #{teachingClassId,jdbcType=VARCHAR} + + delete from teaching_class_student where teaching_class_id = #{teachingClassId,jdbcType=VARCHAR} + + + update teaching_class_student + set status = 'EXITED', + exit_time = CURRENT_TIMESTAMP + where student_user_id = #{studentUserId,jdbcType=VARCHAR} + and teaching_class_id = #{teachingClassId,jdbcType=VARCHAR} + and status = 'IN_PROGRESS' +