From 5ad38557636dae39a74862e0098994954b369690 Mon Sep 17 00:00:00 2001 From: chenyuan Date: Sat, 1 Aug 2026 14:47:30 +0800 Subject: [PATCH] feat: scope teacher student roster --- .../controller/stu/UserController.java | 71 ++++++++++++++++++- .../stu/UserControllerTeacherAdminTest.java | 39 ++++++++++ 2 files changed, 108 insertions(+), 2 deletions(-) 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 446f7cb..5d9404a 100644 --- a/src/main/java/com/sztzjy/linkCommerce/controller/stu/UserController.java +++ b/src/main/java/com/sztzjy/linkCommerce/controller/stu/UserController.java @@ -962,6 +962,15 @@ public class UserController { } //查询 + ResultEntity> selectStudent(String schoolId, + String schoolClassId, + String name, + String userName, + Integer index, + Integer size) { + return selectStudent(schoolId, schoolClassId, name, userName, index, size, null); + } + @PostMapping("/selectStudent") @ApiOperation("学生管理-查询学生账号信息") @AnonymousAccess @@ -970,7 +979,13 @@ public class UserController { @ApiParam("学生姓名") @RequestParam(required = false) String name, @ApiParam("学生学号") @RequestParam(required = false) String userName, @RequestParam Integer index, - @RequestParam Integer size) { + @RequestParam Integer size, + @RequestParam(required = false) String operatorId) { + Userinfo operator = StringUtils.isBlank(operatorId) ? null : userinfoMapper.selectByPrimaryKey(operatorId); + boolean teacherRosterScope = isSchoolTeacher(operator) && isTeacherRosterMode(operator.getSchoolId()); + if (teacherRosterScope) { + schoolId = operator.getSchoolId(); + } PageHelper.startPage(index, size); UserinfoExample userInfoExample = new UserinfoExample(); UserinfoExample.Criteria criteria = userInfoExample.createCriteria(); @@ -986,6 +1001,13 @@ public class UserController { if (StringUtils.isNotBlank(userName)) { criteria.andUsernameEqualTo(userName); } + if (teacherRosterScope) { + List ownedStudentIds = resolveOwnedRosterStudentIds(operator, schoolClassId); + if (ownedStudentIds == null) { + return new ResultEntity<>(HttpStatus.BAD_REQUEST, "只能查看自己教学班内的学生"); + } + criteria.andUserIdIn(ownedStudentIds.isEmpty() ? Collections.singletonList("__empty__") : ownedStudentIds); + } if (StringUtils.isNotBlank(schoolClassId)) { schoolClass = schoolClassMapper.selectByPrimaryKey(schoolClassId); if (schoolClass != null && "TEACHING".equals(schoolClass.getClassType()) && teachingClassStudentMapper != null) { @@ -1031,6 +1053,35 @@ public class UserController { } //编辑 + private List resolveOwnedRosterStudentIds(Userinfo operator, String teachingClassId) { + if (!isSchoolTeacher(operator) || teachingClassStudentMapper == null) { + return Collections.emptyList(); + } + List teachingClasses; + if (StringUtils.isNotBlank(teachingClassId)) { + SchoolClass teachingClass = schoolClassMapper.selectByPrimaryKey(teachingClassId); + if (!isOwnedTeachingClass(teachingClass, operator.getUserId())) { + return null; + } + teachingClasses = Collections.singletonList(teachingClass); + } else { + SchoolClassExample example = new SchoolClassExample(); + example.createCriteria().andSchoolIdEqualTo(operator.getSchoolId()) + .andCreatedByEqualTo(operator.getUserId()).andClassTypeEqualTo("TEACHING"); + teachingClasses = schoolClassMapper.selectByExample(example); + } + Set studentIds = new LinkedHashSet<>(); + for (SchoolClass teachingClass : teachingClasses == null ? Collections.emptyList() : teachingClasses) { + List members = teachingClassStudentMapper.selectByTeachingClassId(teachingClass.getSchoolClassId()); + for (TeachingClassStudent member : members == null ? Collections.emptyList() : members) { + if (member != null && StringUtils.isNotBlank(member.getStudentUserId())) { + studentIds.add(member.getStudentUserId()); + } + } + } + return new ArrayList<>(studentIds); + } + @PostMapping("/updateStudent") @ApiOperation("学生管理-编辑学生账号信息") @AnonymousAccess @@ -1506,10 +1557,26 @@ public class UserController { @ApiOperation("学生管理-导出") @AnonymousAccess public void exportStudentUserInfo(HttpServletResponse response, - @RequestParam String schoolId) { + @RequestParam String schoolId, + @RequestParam(required = false) String operatorId, + @RequestParam(required = false) String schoolClassId) { + Userinfo operator = StringUtils.isBlank(operatorId) ? null : userinfoMapper.selectByPrimaryKey(operatorId); + boolean teacherRosterScope = isSchoolTeacher(operator) && isTeacherRosterMode(operator.getSchoolId()); + if (teacherRosterScope) { + schoolId = operator.getSchoolId(); + } if (StringUtils.isNotBlank(schoolId)) { UserinfoExample userInfoExample = new UserinfoExample(); userInfoExample.createCriteria().andSchoolIdEqualTo(schoolId).andRoleEqualTo(4); + if (teacherRosterScope) { + List ownedStudentIds = resolveOwnedRosterStudentIds(operator, schoolClassId); + if (ownedStudentIds == null) { + response.setStatus(HttpStatus.BAD_REQUEST.value()); + return; + } + userInfoExample.getOredCriteria().get(0) + .andUserIdIn(ownedStudentIds.isEmpty() ? Collections.singletonList("__empty__") : ownedStudentIds); + } List list = userinfoMapper.selectByExample(userInfoExample); //导出的表名 String title = "学生账号汇总"; diff --git a/src/test/java/com/sztzjy/linkCommerce/controller/stu/UserControllerTeacherAdminTest.java b/src/test/java/com/sztzjy/linkCommerce/controller/stu/UserControllerTeacherAdminTest.java index ba2c108..23a0ef7 100644 --- a/src/test/java/com/sztzjy/linkCommerce/controller/stu/UserControllerTeacherAdminTest.java +++ b/src/test/java/com/sztzjy/linkCommerce/controller/stu/UserControllerTeacherAdminTest.java @@ -162,6 +162,45 @@ class UserControllerTeacherAdminTest { verify(controller.userinfoMapper, never()).deleteByPrimaryKey("teacher-owner"); } + @Test + void teacherRosterListReturnsOnlyMembersOfTheTeachersOwnTeachingClass() { + UserController controller = controllerWithCommonMocks(); + SchoolClass ownedClass = classCreatedBy("teacher-1"); + ownedClass.setSchoolClassId("owned-class"); + TeachingClassStudent member = new TeachingClassStudent(); + member.setTeachingClassId("owned-class"); + member.setStudentUserId("student-owned"); + Userinfo student = student("student-owned", "学生", "20260001", null); + when(controller.schoolProductConfigService.isTeacherRosterManaged("school-1")).thenReturn(true); + when(controller.schoolClassMapper.selectByPrimaryKey("owned-class")).thenReturn(ownedClass); + when(controller.teachingClassStudentMapper.selectByTeachingClassId("owned-class")).thenReturn(Collections.singletonList(member)); + when(controller.userinfoMapper.selectByExample(any(UserinfoExample.class))).thenReturn(Collections.singletonList(student)); + + ResultEntity> result = controller.selectStudent( + "other-school", "owned-class", null, null, 1, 10, "teacher-1"); + + ArgumentCaptor exampleCaptor = ArgumentCaptor.forClass(UserinfoExample.class); + verify(controller.userinfoMapper).selectByExample(exampleCaptor.capture()); + assertEquals(HttpStatus.OK, result.getStatusCode()); + assertTrue(hasUserCondition(exampleCaptor.getValue(), "school_id =", "school-1")); + assertTrue(hasUserCondition(exampleCaptor.getValue(), "user_id in", Collections.singletonList("student-owned"))); + } + + @Test + void teacherRosterListRejectsAnotherTeachersTeachingClass() { + UserController controller = controllerWithCommonMocks(); + SchoolClass foreignClass = classCreatedBy("teacher-2"); + foreignClass.setSchoolClassId("foreign-class"); + when(controller.schoolProductConfigService.isTeacherRosterManaged("school-1")).thenReturn(true); + when(controller.schoolClassMapper.selectByPrimaryKey("foreign-class")).thenReturn(foreignClass); + + ResultEntity> result = controller.selectStudent( + "school-1", "foreign-class", null, null, 1, 10, "teacher-1"); + + assertEquals(HttpStatus.BAD_REQUEST, result.getStatusCode()); + verify(controller.userinfoMapper, never()).selectByExample(any(UserinfoExample.class)); + } + @Test void addSchoolClassStoresCreatorTeacher() { UserController controller = controllerWithCommonMocks();