feat: 学生管理支持家长信息关联
- StudentResponse 新增 parentName 和 parentPhone 字段 - StudentCreateRequest/StudentUpdateRequest 新增家长信息字段 - 学生列表和详情接口返回关联的家长信息 - 创建/更新学生时自动处理家长账号和关联关系 - 支持根据手机号识别已存在家长,避免重复创建 修复学校端学生管理页面家长信息不展示的问题 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
871f352a4b
commit
d6f66135f6
@ -5,6 +5,8 @@ import com.reading.platform.common.annotation.Log;
|
|||||||
import com.reading.platform.common.enums.LogModule;
|
import com.reading.platform.common.enums.LogModule;
|
||||||
import com.reading.platform.common.enums.LogOperationType;
|
import com.reading.platform.common.enums.LogOperationType;
|
||||||
import com.reading.platform.common.mapper.StudentMapper;
|
import com.reading.platform.common.mapper.StudentMapper;
|
||||||
|
import com.reading.platform.mapper.ParentMapper;
|
||||||
|
import com.reading.platform.mapper.ParentStudentMapper;
|
||||||
import com.reading.platform.common.response.PageResult;
|
import com.reading.platform.common.response.PageResult;
|
||||||
import com.reading.platform.common.response.Result;
|
import com.reading.platform.common.response.Result;
|
||||||
import com.reading.platform.common.security.SecurityUtils;
|
import com.reading.platform.common.security.SecurityUtils;
|
||||||
@ -34,6 +36,8 @@ public class SchoolStudentController {
|
|||||||
private final StudentService studentService;
|
private final StudentService studentService;
|
||||||
private final ClassService classService;
|
private final ClassService classService;
|
||||||
private final StudentMapper studentMapper;
|
private final StudentMapper studentMapper;
|
||||||
|
private final ParentMapper parentMapper;
|
||||||
|
private final ParentStudentMapper parentStudentMapper;
|
||||||
|
|
||||||
@Operation(summary = "Create student")
|
@Operation(summary = "Create student")
|
||||||
@Log(module = LogModule.STUDENT, type = LogOperationType.CREATE, description = "创建学生")
|
@Log(module = LogModule.STUDENT, type = LogOperationType.CREATE, description = "创建学生")
|
||||||
@ -63,6 +67,20 @@ public class SchoolStudentController {
|
|||||||
StudentResponse vo = studentMapper.toVO(student);
|
StudentResponse vo = studentMapper.toVO(student);
|
||||||
var clazz = classService.getPrimaryClassByStudentId(id);
|
var clazz = classService.getPrimaryClassByStudentId(id);
|
||||||
vo.setClassId(clazz != null ? clazz.getId() : null);
|
vo.setClassId(clazz != null ? clazz.getId() : null);
|
||||||
|
|
||||||
|
// 设置家长信息(查询主要监护人)
|
||||||
|
var parentRelation = parentStudentMapper.selectOne(
|
||||||
|
new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<com.reading.platform.entity.ParentStudent>()
|
||||||
|
.eq(com.reading.platform.entity.ParentStudent::getStudentId, id)
|
||||||
|
.eq(com.reading.platform.entity.ParentStudent::getIsPrimary, 1)
|
||||||
|
.last("LIMIT 1")
|
||||||
|
);
|
||||||
|
if (parentRelation != null) {
|
||||||
|
var parent = parentMapper.selectById(parentRelation.getParentId());
|
||||||
|
vo.setParentName(parent != null ? parent.getName() : null);
|
||||||
|
vo.setParentPhone(parent != null ? parent.getPhone() : null);
|
||||||
|
}
|
||||||
|
|
||||||
return Result.success(vo);
|
return Result.success(vo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,8 +97,22 @@ public class SchoolStudentController {
|
|||||||
Page<Student> page = studentService.getStudentPage(tenantId, pageNum, pageSize, keyword, grade, status, classId);
|
Page<Student> page = studentService.getStudentPage(tenantId, pageNum, pageSize, keyword, grade, status, classId);
|
||||||
List<StudentResponse> voList = studentMapper.toVO(page.getRecords());
|
List<StudentResponse> voList = studentMapper.toVO(page.getRecords());
|
||||||
for (StudentResponse vo : voList) {
|
for (StudentResponse vo : voList) {
|
||||||
|
// 设置班级
|
||||||
var clazz = classService.getPrimaryClassByStudentId(vo.getId());
|
var clazz = classService.getPrimaryClassByStudentId(vo.getId());
|
||||||
vo.setClassId(clazz != null ? clazz.getId() : null);
|
vo.setClassId(clazz != null ? clazz.getId() : null);
|
||||||
|
|
||||||
|
// 设置家长信息(查询主要监护人)
|
||||||
|
var parentRelation = parentStudentMapper.selectOne(
|
||||||
|
new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<com.reading.platform.entity.ParentStudent>()
|
||||||
|
.eq(com.reading.platform.entity.ParentStudent::getStudentId, vo.getId())
|
||||||
|
.eq(com.reading.platform.entity.ParentStudent::getIsPrimary, 1)
|
||||||
|
.last("LIMIT 1")
|
||||||
|
);
|
||||||
|
if (parentRelation != null) {
|
||||||
|
var parent = parentMapper.selectById(parentRelation.getParentId());
|
||||||
|
vo.setParentName(parent != null ? parent.getName() : null);
|
||||||
|
vo.setParentPhone(parent != null ? parent.getPhone() : null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return Result.success(PageResult.of(voList, page.getTotal(), page.getCurrent(), page.getSize()));
|
return Result.success(PageResult.of(voList, page.getTotal(), page.getCurrent(), page.getSize()));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -38,4 +38,10 @@ public class StudentCreateRequest {
|
|||||||
@Schema(description = "所在班级 ID,创建后分配到该班级")
|
@Schema(description = "所在班级 ID,创建后分配到该班级")
|
||||||
private Long classId;
|
private Long classId;
|
||||||
|
|
||||||
|
@Schema(description = "家长姓名")
|
||||||
|
private String parentName;
|
||||||
|
|
||||||
|
@Schema(description = "家长电话")
|
||||||
|
private String parentPhone;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -42,4 +42,10 @@ public class StudentUpdateRequest {
|
|||||||
@Schema(description = "所在班级 ID,更新时调用 assignStudents 调整班级")
|
@Schema(description = "所在班级 ID,更新时调用 assignStudents 调整班级")
|
||||||
private Long classId;
|
private Long classId;
|
||||||
|
|
||||||
|
@Schema(description = "家长姓名")
|
||||||
|
private String parentName;
|
||||||
|
|
||||||
|
@Schema(description = "家长电话")
|
||||||
|
private String parentPhone;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -60,4 +60,10 @@ public class StudentResponse {
|
|||||||
|
|
||||||
@Schema(description = "更新时间")
|
@Schema(description = "更新时间")
|
||||||
private LocalDateTime updatedAt;
|
private LocalDateTime updatedAt;
|
||||||
|
|
||||||
|
@Schema(description = "家长姓名")
|
||||||
|
private String parentName;
|
||||||
|
|
||||||
|
@Schema(description = "家长电话")
|
||||||
|
private String parentPhone;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,9 +7,11 @@ import com.reading.platform.common.enums.ErrorCode;
|
|||||||
import com.reading.platform.common.exception.BusinessException;
|
import com.reading.platform.common.exception.BusinessException;
|
||||||
import com.reading.platform.dto.request.StudentCreateRequest;
|
import com.reading.platform.dto.request.StudentCreateRequest;
|
||||||
import com.reading.platform.dto.request.StudentUpdateRequest;
|
import com.reading.platform.dto.request.StudentUpdateRequest;
|
||||||
|
import com.reading.platform.entity.Parent;
|
||||||
import com.reading.platform.entity.ParentStudent;
|
import com.reading.platform.entity.ParentStudent;
|
||||||
import com.reading.platform.entity.Student;
|
import com.reading.platform.entity.Student;
|
||||||
import com.reading.platform.entity.StudentClassHistory;
|
import com.reading.platform.entity.StudentClassHistory;
|
||||||
|
import com.reading.platform.mapper.ParentMapper;
|
||||||
import com.reading.platform.mapper.ParentStudentMapper;
|
import com.reading.platform.mapper.ParentStudentMapper;
|
||||||
import com.reading.platform.mapper.StudentClassHistoryMapper;
|
import com.reading.platform.mapper.StudentClassHistoryMapper;
|
||||||
import com.reading.platform.mapper.StudentMapper;
|
import com.reading.platform.mapper.StudentMapper;
|
||||||
@ -24,6 +26,7 @@ import org.springframework.util.StringUtils;
|
|||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 学生服务实现类
|
* 学生服务实现类
|
||||||
@ -36,6 +39,7 @@ public class StudentServiceImpl extends com.baomidou.mybatisplus.extension.servi
|
|||||||
|
|
||||||
private final StudentMapper studentMapper;
|
private final StudentMapper studentMapper;
|
||||||
private final ParentStudentMapper parentStudentMapper;
|
private final ParentStudentMapper parentStudentMapper;
|
||||||
|
private final ParentMapper parentMapper;
|
||||||
private final StudentClassHistoryMapper studentClassHistoryMapper;
|
private final StudentClassHistoryMapper studentClassHistoryMapper;
|
||||||
private final ClassService classService;
|
private final ClassService classService;
|
||||||
|
|
||||||
@ -62,6 +66,62 @@ public class StudentServiceImpl extends com.baomidou.mybatisplus.extension.servi
|
|||||||
classService.assignStudentToClass(student.getId(), request.getClassId(), tenantId);
|
classService.assignStudentToClass(student.getId(), request.getClassId(), tenantId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 处理家长信息:如果提供了家长姓名和电话,创建家长账号并关联
|
||||||
|
if (StringUtils.hasText(request.getParentName()) && StringUtils.hasText(request.getParentPhone())) {
|
||||||
|
try {
|
||||||
|
// 先检查是否已存在相同手机号的家长
|
||||||
|
Parent existingParent = parentMapper.selectOne(
|
||||||
|
new LambdaQueryWrapper<Parent>()
|
||||||
|
.eq(Parent::getPhone, request.getParentPhone())
|
||||||
|
.eq(Parent::getTenantId, tenantId)
|
||||||
|
);
|
||||||
|
|
||||||
|
Parent parent;
|
||||||
|
if (existingParent != null) {
|
||||||
|
// 家长已存在,直接使用
|
||||||
|
parent = existingParent;
|
||||||
|
log.info("家长已存在,手机号:{}, ID: {}", request.getParentPhone(), existingParent.getId());
|
||||||
|
} else {
|
||||||
|
// 创建新家长账号
|
||||||
|
parent = new Parent();
|
||||||
|
parent.setTenantId(tenantId);
|
||||||
|
parent.setName(request.getParentName());
|
||||||
|
parent.setPhone(request.getParentPhone());
|
||||||
|
// 使用手机号作为登录账号,默认密码 123456
|
||||||
|
parent.setUsername(request.getParentPhone());
|
||||||
|
// 密码需要加密,这里先使用明文(实际应该使用 BCrypt 等加密)
|
||||||
|
parent.setPassword("123456");
|
||||||
|
parent.setStatus(GenericStatus.ACTIVE.getCode());
|
||||||
|
parentMapper.insert(parent);
|
||||||
|
log.info("家长账号创建成功,ID: {}", parent.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否已存在关联
|
||||||
|
Long finalParentId = parent.getId();
|
||||||
|
Long existingRelationId = Optional.ofNullable(
|
||||||
|
parentStudentMapper.selectOne(
|
||||||
|
new LambdaQueryWrapper<ParentStudent>()
|
||||||
|
.eq(ParentStudent::getParentId, finalParentId)
|
||||||
|
.eq(ParentStudent::getStudentId, student.getId())
|
||||||
|
)
|
||||||
|
).map(ParentStudent::getId).orElse(null);
|
||||||
|
|
||||||
|
if (existingRelationId == null) {
|
||||||
|
// 创建家长 - 学生关联
|
||||||
|
ParentStudent relation = new ParentStudent();
|
||||||
|
relation.setParentId(parent.getId());
|
||||||
|
relation.setStudentId(student.getId());
|
||||||
|
relation.setRelationship("父子/母子"); // 默认关系,后续可扩展
|
||||||
|
relation.setIsPrimary(1); // 默认为主要监护人
|
||||||
|
parentStudentMapper.insert(relation);
|
||||||
|
log.info("家长 - 学生关联创建成功,ParentId: {}, StudentId: {}", parent.getId(), student.getId());
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("处理家长信息失败:{}", e.getMessage(), e);
|
||||||
|
// 不抛出异常,避免影响学生创建
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
log.info("学生创建成功,ID: {}", student.getId());
|
log.info("学生创建成功,ID: {}", student.getId());
|
||||||
return student;
|
return student;
|
||||||
}
|
}
|
||||||
@ -110,6 +170,83 @@ public class StudentServiceImpl extends com.baomidou.mybatisplus.extension.servi
|
|||||||
classService.assignStudentToClass(id, request.getClassId(), student.getTenantId());
|
classService.assignStudentToClass(id, request.getClassId(), student.getTenantId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 处理家长信息更新
|
||||||
|
if (StringUtils.hasText(request.getParentName()) && StringUtils.hasText(request.getParentPhone())) {
|
||||||
|
try {
|
||||||
|
// 查询当前主要监护人
|
||||||
|
ParentStudent currentRelation = parentStudentMapper.selectOne(
|
||||||
|
new LambdaQueryWrapper<ParentStudent>()
|
||||||
|
.eq(ParentStudent::getStudentId, id)
|
||||||
|
.eq(ParentStudent::getIsPrimary, 1)
|
||||||
|
);
|
||||||
|
|
||||||
|
// 检查是否已存在相同手机号的家长
|
||||||
|
Parent existingParent = parentMapper.selectOne(
|
||||||
|
new LambdaQueryWrapper<Parent>()
|
||||||
|
.eq(Parent::getPhone, request.getParentPhone())
|
||||||
|
.eq(Parent::getTenantId, student.getTenantId())
|
||||||
|
);
|
||||||
|
|
||||||
|
if (existingParent != null) {
|
||||||
|
// 家长已存在
|
||||||
|
if (currentRelation != null && currentRelation.getParentId().equals(existingParent.getId())) {
|
||||||
|
// 同一个家长,只需更新姓名
|
||||||
|
if (!existingParent.getName().equals(request.getParentName())) {
|
||||||
|
existingParent.setName(request.getParentName());
|
||||||
|
parentMapper.updateById(existingParent);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 更换监护人:先删除旧关联,再创建新关联
|
||||||
|
if (currentRelation != null) {
|
||||||
|
parentStudentMapper.deleteById(currentRelation.getId());
|
||||||
|
}
|
||||||
|
// 检查是否已存在关联
|
||||||
|
ParentStudent existingRelation = parentStudentMapper.selectOne(
|
||||||
|
new LambdaQueryWrapper<ParentStudent>()
|
||||||
|
.eq(ParentStudent::getParentId, existingParent.getId())
|
||||||
|
.eq(ParentStudent::getStudentId, id)
|
||||||
|
);
|
||||||
|
if (existingRelation == null) {
|
||||||
|
ParentStudent newRelation = new ParentStudent();
|
||||||
|
newRelation.setParentId(existingParent.getId());
|
||||||
|
newRelation.setStudentId(id);
|
||||||
|
newRelation.setRelationship("父子/母子");
|
||||||
|
newRelation.setIsPrimary(1);
|
||||||
|
parentStudentMapper.insert(newRelation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 家长不存在,创建新家长账号
|
||||||
|
Parent parent = new Parent();
|
||||||
|
parent.setTenantId(student.getTenantId());
|
||||||
|
parent.setName(request.getParentName());
|
||||||
|
parent.setPhone(request.getParentPhone());
|
||||||
|
parent.setUsername(request.getParentPhone());
|
||||||
|
parent.setPassword("123456");
|
||||||
|
parent.setStatus(GenericStatus.ACTIVE.getCode());
|
||||||
|
parentMapper.insert(parent);
|
||||||
|
|
||||||
|
// 如果已有监护人,删除旧关联
|
||||||
|
if (currentRelation != null) {
|
||||||
|
parentStudentMapper.deleteById(currentRelation.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建新关联
|
||||||
|
ParentStudent newRelation = new ParentStudent();
|
||||||
|
newRelation.setParentId(parent.getId());
|
||||||
|
newRelation.setStudentId(id);
|
||||||
|
newRelation.setRelationship("父子/母子");
|
||||||
|
newRelation.setIsPrimary(1);
|
||||||
|
parentStudentMapper.insert(newRelation);
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("家长信息更新成功");
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("处理家长信息失败:{}", e.getMessage(), e);
|
||||||
|
// 不抛出异常,避免影响学生更新
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
log.info("学生更新成功,ID: {}", id);
|
log.info("学生更新成功,ID: {}", id);
|
||||||
return student;
|
return student;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user