From ccce7e66bbf3bf22b57de4146aecae3ad3164f0f Mon Sep 17 00:00:00 2001 From: zhonghua Date: Thu, 19 Mar 2026 14:11:41 +0800 Subject: [PATCH] =?UTF-8?q?feat(school):=20=E6=95=99=E5=B8=88=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E5=89=8D=E5=90=8E=E7=AB=AF=E5=AF=B9=E9=BD=90=20-=20?= =?UTF-8?q?=E6=94=AF=E6=8C=81loginAccount/classIds=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - TeacherCreateRequest: 添加@JsonAlias(loginAccount)支持前端字段 - TeacherCreateRequest/UpdateRequest: 支持classIds班级分配 - TeacherResponse: 返回loginAccount、classIds、classNames、lessonCount - 重置密码接口: 自动生成并返回tempPassword - 创建/更新教师时处理class_teacher关联 Made-with: Cursor --- .../school/SchoolTeacherController.java | 16 ++- .../dto/request/TeacherCreateRequest.java | 10 +- .../dto/request/TeacherUpdateRequest.java | 5 + .../dto/response/TeacherResponse.java | 14 ++- .../platform/service/TeacherService.java | 16 +++ .../service/impl/TeacherServiceImpl.java | 104 ++++++++++++++++++ 6 files changed, 154 insertions(+), 11 deletions(-) diff --git a/reading-platform-java/src/main/java/com/reading/platform/controller/school/SchoolTeacherController.java b/reading-platform-java/src/main/java/com/reading/platform/controller/school/SchoolTeacherController.java index ece4b0d..01229c7 100644 --- a/reading-platform-java/src/main/java/com/reading/platform/controller/school/SchoolTeacherController.java +++ b/reading-platform-java/src/main/java/com/reading/platform/controller/school/SchoolTeacherController.java @@ -1,7 +1,6 @@ package com.reading.platform.controller.school; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.reading.platform.common.mapper.TeacherMapper; import com.reading.platform.common.response.PageResult; import com.reading.platform.common.response.Result; import com.reading.platform.common.security.SecurityUtils; @@ -25,14 +24,13 @@ import java.util.List; public class SchoolTeacherController { private final TeacherService teacherService; - private final TeacherMapper teacherMapper; @Operation(summary = "Create teacher") @PostMapping public Result createTeacher(@Valid @RequestBody TeacherCreateRequest request) { Long tenantId = SecurityUtils.getCurrentTenantId(); Teacher teacher = teacherService.createTeacher(tenantId, request); - return Result.success(teacherMapper.toVO(teacher)); + return Result.success(teacherService.toTeacherResponse(teacher)); } @Operation(summary = "Update teacher") @@ -40,7 +38,7 @@ public class SchoolTeacherController { public Result updateTeacher(@PathVariable Long id, @RequestBody TeacherUpdateRequest request) { Long tenantId = SecurityUtils.getCurrentTenantId(); Teacher teacher = teacherService.updateTeacherWithTenantCheck(id, tenantId, request); - return Result.success(teacherMapper.toVO(teacher)); + return Result.success(teacherService.toTeacherResponse(teacher)); } @Operation(summary = "Get teacher by ID") @@ -48,7 +46,7 @@ public class SchoolTeacherController { public Result getTeacher(@PathVariable Long id) { Long tenantId = SecurityUtils.getCurrentTenantId(); Teacher teacher = teacherService.getTeacherByIdWithTenantCheck(id, tenantId); - return Result.success(teacherMapper.toVO(teacher)); + return Result.success(teacherService.toTeacherResponse(teacher)); } @Operation(summary = "Get teacher page") @@ -60,7 +58,7 @@ public class SchoolTeacherController { @RequestParam(required = false) String status) { Long tenantId = SecurityUtils.getCurrentTenantId(); Page page = teacherService.getTeacherPage(tenantId, pageNum, pageSize, keyword, status); - List voList = teacherMapper.toVO(page.getRecords()); + List voList = teacherService.toTeacherResponseList(page.getRecords()); return Result.success(PageResult.of(voList, page.getTotal(), page.getCurrent(), page.getSize())); } @@ -74,10 +72,10 @@ public class SchoolTeacherController { @Operation(summary = "Reset teacher password") @PostMapping("/{id}/reset-password") - public Result resetPassword(@PathVariable Long id, @RequestParam String newPassword) { + public Result> resetPassword(@PathVariable Long id) { Long tenantId = SecurityUtils.getCurrentTenantId(); - teacherService.resetPasswordWithTenantCheck(id, tenantId, newPassword); - return Result.success(); + String tempPassword = teacherService.resetPasswordAndReturnTemp(id, tenantId); + return Result.success(java.util.Map.of("tempPassword", tempPassword)); } } diff --git a/reading-platform-java/src/main/java/com/reading/platform/dto/request/TeacherCreateRequest.java b/reading-platform-java/src/main/java/com/reading/platform/dto/request/TeacherCreateRequest.java index d287ea0..b7a35e0 100644 --- a/reading-platform-java/src/main/java/com/reading/platform/dto/request/TeacherCreateRequest.java +++ b/reading-platform-java/src/main/java/com/reading/platform/dto/request/TeacherCreateRequest.java @@ -1,15 +1,19 @@ package com.reading.platform.dto.request; +import com.fasterxml.jackson.annotation.JsonAlias; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; import lombok.Data; +import java.util.List; + @Data @Schema(description = "教师创建请求") public class TeacherCreateRequest { @NotBlank(message = "用户名不能为空") - @Schema(description = "用户名") + @JsonAlias("loginAccount") + @Schema(description = "用户名/登录账号") private String username; @NotBlank(message = "密码不能为空") @@ -20,6 +24,7 @@ public class TeacherCreateRequest { @Schema(description = "姓名") private String name; + @NotBlank(message = "手机号不能为空") @Schema(description = "电话") private String phone; @@ -32,4 +37,7 @@ public class TeacherCreateRequest { @Schema(description = "简介") private String bio; + @Schema(description = "负责班级ID列表") + private List classIds; + } diff --git a/reading-platform-java/src/main/java/com/reading/platform/dto/request/TeacherUpdateRequest.java b/reading-platform-java/src/main/java/com/reading/platform/dto/request/TeacherUpdateRequest.java index c81d760..e5943c2 100644 --- a/reading-platform-java/src/main/java/com/reading/platform/dto/request/TeacherUpdateRequest.java +++ b/reading-platform-java/src/main/java/com/reading/platform/dto/request/TeacherUpdateRequest.java @@ -3,6 +3,8 @@ package com.reading.platform.dto.request; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import java.util.List; + @Data @Schema(description = "教师更新请求") public class TeacherUpdateRequest { @@ -28,4 +30,7 @@ public class TeacherUpdateRequest { @Schema(description = "状态") private String status; + @Schema(description = "负责班级ID列表") + private List classIds; + } diff --git a/reading-platform-java/src/main/java/com/reading/platform/dto/response/TeacherResponse.java b/reading-platform-java/src/main/java/com/reading/platform/dto/response/TeacherResponse.java index dbb7b03..4e0042f 100644 --- a/reading-platform-java/src/main/java/com/reading/platform/dto/response/TeacherResponse.java +++ b/reading-platform-java/src/main/java/com/reading/platform/dto/response/TeacherResponse.java @@ -1,10 +1,12 @@ package com.reading.platform.dto.response; +import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; import lombok.Data; import java.time.LocalDateTime; +import java.util.List; /** * 教师响应 @@ -21,7 +23,8 @@ public class TeacherResponse { @Schema(description = "租户 ID") private Long tenantId; - @Schema(description = "用户名") + @JsonProperty("loginAccount") + @Schema(description = "登录账号") private String username; @Schema(description = "姓名") @@ -45,6 +48,15 @@ public class TeacherResponse { @Schema(description = "状态") private String status; + @Schema(description = "负责班级ID列表") + private List classIds; + + @Schema(description = "负责班级名称") + private Object classNames; + + @Schema(description = "授课次数") + private Integer lessonCount; + @Schema(description = "最后登录时间") private LocalDateTime lastLoginAt; diff --git a/reading-platform-java/src/main/java/com/reading/platform/service/TeacherService.java b/reading-platform-java/src/main/java/com/reading/platform/service/TeacherService.java index 00de796..8220f00 100644 --- a/reading-platform-java/src/main/java/com/reading/platform/service/TeacherService.java +++ b/reading-platform-java/src/main/java/com/reading/platform/service/TeacherService.java @@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.IService; import com.reading.platform.dto.request.TeacherCreateRequest; import com.reading.platform.dto.request.TeacherUpdateRequest; +import com.reading.platform.dto.response.TeacherResponse; import com.reading.platform.entity.Teacher; import java.util.List; @@ -63,9 +64,24 @@ public interface TeacherService extends IService { */ void resetPasswordWithTenantCheck(Long id, Long tenantId, String newPassword); + /** + * 重置密码并返回临时密码(带租户验证) + */ + String resetPasswordAndReturnTemp(Long id, Long tenantId); + /** * 根据 ID 列表查询教师 */ List getTeachersByIds(List teacherIds); + /** + * 转换为教师响应(含班级、授课数等扩展信息) + */ + TeacherResponse toTeacherResponse(Teacher teacher); + + /** + * 批量转换为教师响应 + */ + List toTeacherResponseList(List teachers); + } diff --git a/reading-platform-java/src/main/java/com/reading/platform/service/impl/TeacherServiceImpl.java b/reading-platform-java/src/main/java/com/reading/platform/service/impl/TeacherServiceImpl.java index 18dc0e8..c58ac0e 100644 --- a/reading-platform-java/src/main/java/com/reading/platform/service/impl/TeacherServiceImpl.java +++ b/reading-platform-java/src/main/java/com/reading/platform/service/impl/TeacherServiceImpl.java @@ -6,17 +6,28 @@ import com.reading.platform.common.enums.ErrorCode; import com.reading.platform.common.exception.BusinessException; import com.reading.platform.dto.request.TeacherCreateRequest; import com.reading.platform.dto.request.TeacherUpdateRequest; +import com.reading.platform.dto.response.TeacherResponse; +import com.reading.platform.entity.ClassTeacher; +import com.reading.platform.entity.Clazz; +import com.reading.platform.entity.Lesson; import com.reading.platform.entity.Teacher; +import com.reading.platform.mapper.ClassTeacherMapper; +import com.reading.platform.mapper.ClazzMapper; +import com.reading.platform.mapper.LessonMapper; import com.reading.platform.mapper.TeacherMapper; +import com.reading.platform.service.ClassService; import com.reading.platform.service.TeacherService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; +import java.util.ArrayList; import java.util.List; +import java.util.UUID; /** * 教师服务实现类 @@ -28,6 +39,11 @@ public class TeacherServiceImpl extends com.baomidou.mybatisplus.extension.servi implements TeacherService { private final TeacherMapper teacherMapper; + private final com.reading.platform.common.mapper.TeacherMapper teacherVoMapper; + private final ClassTeacherMapper classTeacherMapper; + private final ClazzMapper clazzMapper; + private final LessonMapper lessonMapper; + private final ClassService classService; private final PasswordEncoder passwordEncoder; @Override @@ -57,6 +73,18 @@ public class TeacherServiceImpl extends com.baomidou.mybatisplus.extension.servi teacherMapper.insert(teacher); + // 分配教师到班级 + if (!CollectionUtils.isEmpty(request.getClassIds())) { + for (Long classId : request.getClassIds()) { + classService.getClassByIdWithTenantCheck(classId, tenantId); + ClassTeacher classTeacher = new ClassTeacher(); + classTeacher.setClassId(classId); + classTeacher.setTeacherId(teacher.getId()); + classTeacher.setRole("MAIN"); + classTeacherMapper.insert(classTeacher); + } + } + log.info("教师创建成功,ID: {}", teacher.getId()); return teacher; } @@ -92,6 +120,21 @@ public class TeacherServiceImpl extends com.baomidou.mybatisplus.extension.servi teacherMapper.updateById(teacher); + // 更新教师班级分配 + if (request.getClassIds() != null) { + classTeacherMapper.delete( + new LambdaQueryWrapper().eq(ClassTeacher::getTeacherId, id) + ); + for (Long classId : request.getClassIds()) { + classService.getClassByIdWithTenantCheck(classId, teacher.getTenantId()); + ClassTeacher classTeacher = new ClassTeacher(); + classTeacher.setClassId(classId); + classTeacher.setTeacherId(id); + classTeacher.setRole("MAIN"); + classTeacherMapper.insert(classTeacher); + } + } + log.info("教师更新成功,ID: {}", id); return teacher; } @@ -200,6 +243,18 @@ public class TeacherServiceImpl extends com.baomidou.mybatisplus.extension.servi resetPassword(id, newPassword); } + @Override + @Transactional + public String resetPasswordAndReturnTemp(Long id, Long tenantId) { + log.info("开始重置密码并返回临时密码,ID: {}, tenantId: {}", id, tenantId); + Teacher teacher = getTeacherByIdWithTenantCheck(id, tenantId); + String tempPassword = UUID.randomUUID().toString().replace("-", "").substring(0, 8); + teacher.setPassword(passwordEncoder.encode(tempPassword)); + teacherMapper.updateById(teacher); + log.info("密码重置成功,ID: {}", id); + return tempPassword; + } + @Override public List getTeachersByIds(List teacherIds) { log.debug("根据 ID 列表查询教师,ID 列表:{}", teacherIds); @@ -215,4 +270,53 @@ public class TeacherServiceImpl extends com.baomidou.mybatisplus.extension.servi return teacherMapper.selectList(wrapper); } + @Override + public TeacherResponse toTeacherResponse(Teacher teacher) { + if (teacher == null) return null; + TeacherResponse response = teacherVoMapper.toVO(teacher); + enrichTeacherResponse(response, teacher.getId()); + return response; + } + + @Override + public List toTeacherResponseList(List teachers) { + if (teachers == null) return null; + List list = new ArrayList<>(teachers.size()); + for (Teacher teacher : teachers) { + list.add(toTeacherResponse(teacher)); + } + return list; + } + + private void enrichTeacherResponse(TeacherResponse response, Long teacherId) { + List classTeachers = classTeacherMapper.selectList( + new LambdaQueryWrapper().eq(ClassTeacher::getTeacherId, teacherId) + ); + List classIds = new ArrayList<>(); + List classNames = new ArrayList<>(); + for (ClassTeacher ct : classTeachers) { + classIds.add(ct.getClassId()); + Clazz clazz = clazzMapper.selectById(ct.getClassId()); + if (clazz != null) { + classNames.add(clazz.getName()); + } + } + response.setClassIds(classIds); + response.setClassNames(classNames.isEmpty() ? null : classNames); + + if ("active".equals(response.getStatus())) { + response.setStatus("ACTIVE"); + } + + long lessonCount = 0; + try { + lessonCount = lessonMapper.selectCount( + new LambdaQueryWrapper().eq(Lesson::getTeacherId, teacherId) + ); + } catch (Exception e) { + log.debug("Query lesson count failed: {}", e.getMessage()); + } + response.setLessonCount((int) lessonCount); + } + }