导入同步修改

This commit is contained in:
2026-08-24 18:28:21 +08:00
parent dcb51347dd
commit 431a1415fe
14 changed files with 310 additions and 62 deletions
@@ -5,8 +5,7 @@ import com.yunhai.bschclassmanage.entity.SchTeacher;
import com.yunhai.bschclassmanage.enums.NodeType;
import com.yunhai.bschclassmanage.model.dto.SchStudentDTO;
import com.yunhai.bschclassmanage.model.dto.SchTeacherDTO;
import com.yunhai.bschclassmanage.model.tool.DeleteUser;
import com.yunhai.bschclassmanage.model.tool.SyncUserDTO;
import com.yunhai.bschclassmanage.model.dto.SendMoveGroupUserDTO;
import com.yunhai.platform.utils.model.BoaGroup;
import com.yunhai.platform.utils.model.BoaUser;
import org.springframework.stereotype.Service;
@@ -35,4 +34,18 @@ public interface ISendUserBaseService {
void deleteTeachers(List<Integer> userIds,Integer groupId,Integer schId);
void deleteStudents(List<Integer> userIds,Integer groupId,Integer schId);
/** 导入失败回滚:删除已推送成功的学生平台账号(syncedList 与 groupIds 按下标一一对应) */
void rollbackSyncedStudents(List<BoaUser> syncedList, List<Integer> groupIds, Integer schId);
/** 导入失败回滚:删除已推送成功的教师平台账号(syncedList 与 groupIds 按下标一一对应) */
void rollbackSyncedTeachers(List<BoaUser> syncedList, List<Integer> groupIds, Integer schId);
void moveTeacherToGroup(List<SendMoveGroupUserDTO> teacherList, Integer schId);
void moveStudentToGroup(List<Integer> stuIds,Integer classId,Integer schId);
List<BoaUser> batchAddStudent(List<SchStudentDTO> stuList);
List<BoaUser> batchAddTeacher(List<SchTeacherDTO> teacherList);
}
@@ -15,7 +15,6 @@ import com.yunhai.bschclassmanage.utils.UserContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
@@ -90,8 +89,8 @@ public class SchStudentService implements ISchStudentService {
@OperationLog(module = LogModule.STUDENT)
@Transactional(rollbackFor = Exception.class)
@Override
public void saveStudent(UserContext.UserInfo user, SchStudentDTO entityVO) {
infoService.saveStudent(user, entityVO);
public void saveStudent(UserContext.UserInfo user, SchStudentDTO entityDTO) {
infoService.saveStudent(user, entityDTO);
}
@Transactional(rollbackFor = Exception.class)
@@ -6,13 +6,13 @@ import com.yunhai.bschclassmanage.enums.NodeType;
import com.yunhai.bschclassmanage.enums.UserRole;
import com.yunhai.bschclassmanage.annotation.SyncOpLog;
import com.yunhai.bschclassmanage.enums.SyncDataType;
import com.yunhai.bschclassmanage.model.dto.SchStudentDTO;
import com.yunhai.bschclassmanage.model.dto.SchTeacherDTO;
import com.yunhai.bschclassmanage.model.dto.SendMoveGroupUserDTO;
import com.yunhai.bschclassmanage.service.IComSchTreeService;
import com.yunhai.bschclassmanage.service.ISendUserBaseService;
import com.yunhai.platform.openapi.client.YschBaseOpenApi;
import com.yunhai.platform.openapi.model.SysGroupMoveRequest;
import com.yunhai.platform.openapi.model.SysGroupRequest;
import com.yunhai.platform.openapi.model.SysUserGroupDeleteItem;
import com.yunhai.platform.openapi.model.SysUserRequest;
import com.yunhai.platform.openapi.model.*;
import com.yunhai.platform.utils.exception.DException;
import com.yunhai.platform.utils.model.BoaGroup;
import com.yunhai.platform.utils.model.BoaUser;
@@ -181,23 +181,120 @@ public class SendUserBaseService implements ISendUserBaseService {
}
}
// public void moveTeachertToGroup(List<SchTeacherDTO> teacherList){
// for (SchTeacherDTO teacher :teacherList) {
// SysUserMoveRequest move=new SysUserMoveRequest();
// move.setUserId();
// move.setGroupId();
// move.setSchoolId();
// YschBaseOpenApi.moveUserToGroup(teacher.getTeaId(),teacher.getGroupId());
// }
// }
//
// public void moveStudentToGroup(List<SchTeacherDTO> teacherList){
// for (SchTeacherDTO teacher :teacherList) {
// SysUserMoveRequest move=new SysUserMoveRequest();
// move.setUserId();
// move.setGroupId();
// move.setSchoolId();
// YschBaseOpenApi.moveUserToGroup(teacher.getTeaId(),teacher.getGroupId());
// }
// }
/**
* 导入失败回滚:删除已成功推送到平台的学生账号,避免孤儿账号。
* syncedList 与 groupIds 按下标一一对应(groupId 取自主组 classId)。
*/
public void rollbackSyncedStudents(List<BoaUser> syncedList, List<Integer> groupIds, Integer schId) {
if (syncedList == null || syncedList.isEmpty()) {
return;
}
int n = Math.min(syncedList.size(), groupIds == null ? 0 : groupIds.size());
for (int i = 0; i < n; i++) {
BoaUser boaUser = syncedList.get(i);
if (boaUser == null) {
continue;
}
Integer groupId = groupIds.get(i);
if (groupId != null) {
deleteStudents(Collections.singletonList(boaUser.getId()), groupId, schId);
}
}
}
/**
* 导入失败回滚:删除已成功推送到平台的教师账号,避免孤儿账号。
* syncedList 与 groupIds 按下标一一对应(groupId 取自主组)。
*/
public void rollbackSyncedTeachers(List<BoaUser> syncedList, List<Integer> groupIds, Integer schId) {
if (syncedList == null || syncedList.isEmpty()) {
return;
}
int n = Math.min(syncedList.size(), groupIds == null ? 0 : groupIds.size());
for (int i = 0; i < n; i++) {
BoaUser boaUser = syncedList.get(i);
if (boaUser == null) {
continue;
}
Integer groupId = groupIds.get(i);
if (groupId != null) {
deleteTeachers(Collections.singletonList(boaUser.getId()), groupId, schId);
}
}
}
//移动教师
@SyncOpLog(SyncDataType.SEND_MOVE_TEACHER)
public void moveTeacherToGroup(List<SendMoveGroupUserDTO> teacherList,Integer schId){
for (SendMoveGroupUserDTO teacher :teacherList) {
SysUserMoveRequest move=new SysUserMoveRequest();
move.setUserId(teacher.getUserId());
move.setGroupId(teacher.getGroupId());
YschBaseOpenApi.moveUserToGroup(move);
}
}
//学生调班
@SyncOpLog(SyncDataType.SEND_MOVE_STUDENT)
public void moveStudentToGroup(List<Integer> stuIds,Integer classId,Integer schId){
for (Integer stuId :stuIds) {
SysUserMoveRequest move=new SysUserMoveRequest();
move.setUserId(stuId);
move.setGroupId(classId);
move.setSchoolId(schId);
YschBaseOpenApi.moveUserToGroup(move);
}
}
@SyncOpLog(SyncDataType.SEND_BATCH_STUDENT)
public List<BoaUser> batchAddStudent(List<SchStudentDTO> stuList){
if (stuList == null || stuList.isEmpty()) {
return new ArrayList<>();
}
List<SysUserRequest> requests = new ArrayList<>();
for (SchStudentDTO stu : stuList) {
SysUserRequest sysUser = new SysUserRequest();
sysUser.setAccount(stu.getAccount());
sysUser.setRealName(stu.getName());
sysUser.setGender(stu.getGender());
sysUser.setIdcard(stu.getIdCard());
sysUser.setGroupId(stu.getGroupId());
sysUser.setRoles(Arrays.asList(UserRole.STU_USER.getValue()));
String pwd = stu.getPwd();
if (StringUtils.isNotBlank(pwd)) {
sysUser.setPassword(pwd);
sysUser.setConfirmPassword(pwd);
}
requests.add(sysUser);
}
return YschBaseOpenApi.batchAddUsers(requests);
}
@SyncOpLog(SyncDataType.SEND_BATCH_TEACHER)
public List<BoaUser> batchAddTeacher(List<SchTeacherDTO> teacherList)
{
if (teacherList == null || teacherList.isEmpty()) {
return new ArrayList<>();
}
List<SysUserRequest> requests = new ArrayList<>();
for (SchTeacherDTO teacher : teacherList) {
SysUserRequest sysUser = new SysUserRequest();
sysUser.setAccount(teacher.getAccount());
sysUser.setRealName(teacher.getName());
sysUser.setGender(teacher.getGender());
sysUser.setIdcard(teacher.getIdCard());
sysUser.setPhone(teacher.getTel());
sysUser.setGroupId(teacher.getGroupId());
sysUser.setRoles(Arrays.asList(UserRole.TEACHER_USER.getValue()));
String pwd = teacher.getPwd();
if (StringUtils.isNotBlank(pwd)) {
sysUser.setPassword(pwd);
sysUser.setConfirmPassword(pwd);
}
requests.add(sysUser);
}
return YschBaseOpenApi.batchAddUsers(requests);
}
}
@@ -12,6 +12,7 @@ import com.yunhai.bschclassmanage.enums.StuAbnormalStatus;
import com.yunhai.bschclassmanage.enums.TransferStatus;
import com.yunhai.bschclassmanage.enums.UserGender;
import com.yunhai.bschclassmanage.enums.UserStatus;
import com.yunhai.bschclassmanage.model.dto.SchStudentDTO;
import com.yunhai.bschclassmanage.model.excel.ErrorExcelColumn;
import com.yunhai.bschclassmanage.model.excel.StudentClassNoExcelColumn;
import com.yunhai.bschclassmanage.model.excel.StudentExcelColumn;
@@ -20,10 +21,13 @@ import com.yunhai.bschclassmanage.model.vo.SelectIntVO;
import com.yunhai.bschclassmanage.service.IBaseSchsystemGradeService;
import com.yunhai.bschclassmanage.service.IComSchTreeService;
import com.yunhai.bschclassmanage.service.ISchClassService;
import com.yunhai.bschclassmanage.service.ISendUserBaseService;
import com.yunhai.bschclassmanage.utils.EasyPoiUtils;
import com.yunhai.bschclassmanage.utils.UserContext;
import com.yunhai.bschclassmanage.utils.ValidateUtil;
import com.yunhai.bschclassmanage.utils.ValidationUtil;
import com.yunhai.platform.openapi.client.YschBaseOpenApi;
import com.yunhai.platform.utils.model.BoaUser;
import com.yunhai.platform.utils.exception.DException;
import com.yunhai.platform.utils.exception.ErrorCode;
import lombok.extern.slf4j.Slf4j;
@@ -59,6 +63,10 @@ public class SchStudentImportService {
@Autowired
private IComSchTreeService comSchTreeService;
@Autowired
private ISendUserBaseService sendUserBaseService;
@Autowired
private SchStudentCacheService cacheService;
@@ -77,6 +85,9 @@ public class SchStudentImportService {
Integer userId = user.getUserId();
Date now = new Date();
// 提到 try 外,供 catch 回滚时访问
List<SchStudentDTO> saveStudentList = new ArrayList<>();
List<BoaUser> syncStudentList = null;
// 使用 try-with-resources 确保流关闭
try (InputStream is = file.getInputStream()) {
// 1. 加载基础数据(放在 try 内,若加载失败也回滚)
@@ -109,7 +120,6 @@ public class SchStudentImportService {
}
// 4. 业务校验与转换
List<SchStudent> saveStudentList = new ArrayList<>();
int currentRow = params.getTitleRows() + params.getHeadRows() + 1; // 从第3行开始
for (StudentExcelColumn item : list) {
@@ -122,8 +132,7 @@ public class SchStudentImportService {
continue;
}
}
SchStudent stu = new SchStudent();
SchStudentDTO stu = new SchStudentDTO();
// 账号
{
Optional<SchStudent> accountOpt = schStudentRepository.findByAccount(item.getAccount());
@@ -133,10 +142,12 @@ public class SchStudentImportService {
"禁止将" + comSchTreeService.getSchoolName(accountOpt.get().getSchId()) + "正常学生导入!"));
continue;
} else {
BeanUtils.copyProperties(accountOpt.get(), stu);
stu.setUpdateDate(now);
stu.setUpdateUserId(userId);
oldClassId = accountOpt.get().getClassId();
errorMsgArr.add(new ErrorExcelColumn(currentRow, item.getStuName(),"学生账号已存在!"));
continue;
// BeanUtils.copyProperties(accountOpt.get(), stu);
// stu.setUpdateDate(now);
// stu.setUpdateUserId(userId);
// oldClassId = accountOpt.get().getClassId();
}
} else {
stu.setId(0);
@@ -190,7 +201,7 @@ public class SchStudentImportService {
}
// 密码(暂时忽略,或可设置默认密码,但原代码无处理)
stu.setPwd(item.getPassword());
// 身份证
if (StringUtils.isNotBlank(item.getIdCard())) {
if (!ValidateUtil.isValidIdCard(item.getIdCard())) {
@@ -250,19 +261,36 @@ public class SchStudentImportService {
throw new DException(ErrorCode.CUSTOM,"导入失败,请检查错误列表",errorMsgArr);
}
// 6. 批量保存
schStudentRepository.saveAll(saveStudentList);
// 6. 先推送平台用户(返回平台用户ID),顺序与 saveStudentList 一致
syncStudentList = sendUserBaseService.batchAddStudent(saveStudentList);
// 按顺序回填平台用户ID(stuId),batchAddUsers 返回顺序与传入一致
for (int i = 0; i < saveStudentList.size(); i++) {
if (i < syncStudentList.size() && syncStudentList.get(i) != null) {
saveStudentList.get(i).setStuId(syncStudentList.get(i).getId());
}
}
// 7. 异步记录导入日志
logService.importLogs(user, saveStudentList, gradeList, schClassList);
// 7. DTO 不能直接传给 saveAll(泛型不变性:List<SchStudentDTO> 非 List<SchStudent>),转实体并保留已回填的 stuId
List<SchStudent> studentEntities = saveStudentList.stream().map(dto -> {
SchStudent s = new SchStudent();
BeanUtils.copyProperties(dto, s);
return s;
}).collect(Collectors.toList());
List<SchStudent> savedStudentList = schStudentRepository.saveAll(studentEntities);
// 8. 清除受影响的班级缓存
// 8. 异步记录导入日志
logService.importLogs(user, savedStudentList, gradeList, schClassList);
// 9. 清除受影响的班级缓存
cacheService.clearClassStudentCaches(schId, classIds);
} catch (DException e) {
throw e;
} catch (Exception e) {
// 其他所有未预期的异常(包括数据库、IO等)
// 导入失败:回滚已成功推送到平台的学生账号,避免孤儿账号
List<Integer> groupIds = saveStudentList.stream()
.map(SchStudentDTO::getGroupId).collect(Collectors.toList());
sendUserBaseService.rollbackSyncedStudents(syncStudentList, groupIds, schId);
log.error("导入班级学生时发生系统异常,操作人:" + user.getUserName(), e);
throw new DException(ErrorCode.INTERNAL_SERVER_ERROR,"导入失败,请联系管理员",null,e);
}
@@ -1,6 +1,7 @@
package com.yunhai.bschclassmanage.service.impl.student;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SimplePropertyPreFilter;
import com.yunhai.bschclassmanage.Repository.SchClassRepository;
import com.yunhai.bschclassmanage.entity.OperationLogRecord;
import com.yunhai.bschclassmanage.entity.SchClass;
@@ -8,6 +9,7 @@ import com.yunhai.bschclassmanage.entity.SchStudent;
import com.yunhai.bschclassmanage.enums.StuAbnormalStatus;
import com.yunhai.bschclassmanage.enums.TransferStatus;
import com.yunhai.bschclassmanage.model.constant.LogModule;
import com.yunhai.bschclassmanage.model.dto.SchStudentDTO;
import com.yunhai.bschclassmanage.model.vo.BaseSchClassVO;
import com.yunhai.bschclassmanage.model.vo.SelectIntVO;
import com.yunhai.bschclassmanage.service.IBaseSchsystemGradeService;
@@ -37,6 +39,13 @@ public class SchStudentLogService {
@Autowired
private ILogService logService;
/** 学生对象序列化时排除敏感字段(密码),防止明文进入日志内容/调试日志 */
private static final SimplePropertyPreFilter NO_PWD_FILTER = new SimplePropertyPreFilter();
static {
NO_PWD_FILTER.getExcludes().add("pwd");
}
@Autowired
private ISchClassService schClassService;
@@ -387,7 +396,7 @@ public class SchStudentLogService {
if (!logRecords.isEmpty()) {
logService.saveAllLogAsync(logRecords);
}
log.debug("操作人:{},删除学生日志:{}", user.getUserName(), JSON.toJSONString(students));
log.debug("操作人:{},删除学生日志:{}", user.getUserName(), JSON.toJSONString(students, NO_PWD_FILTER));
} catch (Exception e) {
log.error("记录批量删除学生日志失败", e);
}
@@ -414,10 +423,10 @@ public class SchStudentLogService {
.map(SelectIntVO::getName)
.findFirst()
.orElse("未知年级");
content = "导入学生[" + stu.getName() + "]成功,用户信息:" + JSON.toJSONString(stu)
content = "导入学生[" + stu.getName() + "]成功,用户信息:" + JSON.toJSONString(stu, NO_PWD_FILTER)
+ ",所在年级班级:" + gradeName + schClassOpt.get().getName();
} else {
content = "导入学生[" + stu.getName() + "]成功,用户信息:" + JSON.toJSONString(stu) + ",班级:未知";
content = "导入学生[" + stu.getName() + "]成功,用户信息:" + JSON.toJSONString(stu, NO_PWD_FILTER) + ",班级:未知";
}
OperationLogRecord log = logService.buildLogRecord(user, MODULE_STUDENT, content, now);
logs.add(log);
@@ -425,7 +434,7 @@ public class SchStudentLogService {
if (!logs.isEmpty()) {
logService.saveAllLogAsync(logs);
}
log.debug("操作人:{},学生导入日志成功: {}", user.getUserName(), JSON.toJSONString(saveStudentList));
log.debug("操作人:{},学生导入日志成功: {}", user.getUserName(), JSON.toJSONString(saveStudentList, NO_PWD_FILTER));
} catch (Exception e) {
log.error("操作人:" + user.getUserName() + ",学生导入日志失败: {}", e.getMessage(), e);
}
@@ -5,6 +5,7 @@ import com.yunhai.bschclassmanage.Repository.SchStudentRepository;
import com.yunhai.bschclassmanage.entity.SchStudent;
import com.yunhai.bschclassmanage.enums.TransferStatus;
import com.yunhai.bschclassmanage.model.dto.StuTransferClassDTO;
import com.yunhai.bschclassmanage.service.ISendUserBaseService;
import com.yunhai.bschclassmanage.utils.RedisConstants;
import com.yunhai.bschclassmanage.utils.RedisUtil;
import com.yunhai.bschclassmanage.utils.UserContext;
@@ -34,6 +35,9 @@ public class SchStudentTransferService {
@Autowired
private SchStudentCacheService cacheService;
@Autowired
private ISendUserBaseService sendUserBaseService;
@Autowired
private SchStudentLogService logService;
@@ -93,6 +97,8 @@ public class SchStudentTransferService {
// 清除缓存(新旧班级都要清除)
cacheService.clearClassStudentCaches(schId, affectedClassIds);
sendUserBaseService.moveStudentToGroup(model.getStuIds(),model.getTransferClassId(),schId);
// 异步记录操作日志
logService.transferClassLogs(user, students, targetClassId, affectedClassIds);
}
@@ -9,15 +9,18 @@ import com.yunhai.bschclassmanage.entity.SchTeacherGroup;
import com.yunhai.bschclassmanage.enums.TransferStatus;
import com.yunhai.bschclassmanage.enums.UserGender;
import com.yunhai.bschclassmanage.enums.UserStatus;
import com.yunhai.bschclassmanage.model.dto.SchTeacherDTO;
import com.yunhai.bschclassmanage.model.excel.ErrorExcelColumn;
import com.yunhai.bschclassmanage.model.excel.TeacherExcelColumn;
import com.yunhai.bschclassmanage.model.vo.SelectIntVO;
import com.yunhai.bschclassmanage.service.IComSchTreeService;
import com.yunhai.bschclassmanage.service.ISendUserBaseService;
import com.yunhai.bschclassmanage.utils.UserContext;
import com.yunhai.bschclassmanage.utils.ValidateUtil;
import com.yunhai.bschclassmanage.utils.ValidationUtil;
import com.yunhai.platform.utils.exception.DException;
import com.yunhai.platform.utils.exception.ErrorCode;
import com.yunhai.platform.utils.model.BoaUser;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
@@ -44,6 +47,10 @@ public class SchTeacherImportService {
@Autowired
private IComSchTreeService comSchTreeService;
@Autowired
private ISendUserBaseService sendUserBaseService;
@Autowired
private SchTeacherCacheService cacheService;
@@ -59,6 +66,9 @@ public class SchTeacherImportService {
Integer userId = user.getUserId();
Date now = new Date();
// 提到 try 外,供 catch 回滚时访问
List<SchTeacherDTO> teachers = new ArrayList<>();
List<BoaUser> syncTeacherList = null;
try {
List<SelectIntVO> teaGroupNameList = comSchTreeService.getTeaGroupNameList(schId, null);
List<TeacherExcelColumn> list = ExcelImportUtil.importExcel(file.getInputStream(), TeacherExcelColumn.class, params);
@@ -69,10 +79,9 @@ public class SchTeacherImportService {
List<SchTeacher> teachersByAccounts = getTeachersByAccounts(accountList);
List<SchTeacher> schTeacherList = cacheService.getSchTeacherList(schId);
List<SchTeacher> teachers = new ArrayList<>();
int rows = 0;
for (TeacherExcelColumn item : list) {
SchTeacher teacher = new SchTeacher();
SchTeacherDTO teacher = new SchTeacherDTO();
List<SchTeacherGroup> teacherGroupList = new ArrayList<>();
rows += 2;
@@ -85,14 +94,17 @@ public class SchTeacherImportService {
}
Optional<SchTeacher> schTeacherOpt = teachersByAccounts.stream().filter(s -> s.getAccount().equals(item.getAccount())).findFirst();
if (schTeacherOpt.isPresent()) {
BeanUtils.copyProperties(schTeacherOpt.get(), teacher);
teacher.setUpdateDate(now);
teacher.setUpdateUserId(userId);
// BeanUtils.copyProperties(schTeacherOpt.get(), teacher);
// teacher.setUpdateDate(now);
// teacher.setUpdateUserId(userId);
errorMsgArr.add(new ErrorExcelColumn(rows, item.getAccount(), TeacherExcelColumn.ACCOUNT + "教师已存在!"));
continue;
} else {
teacher.setCreateDate(now);
teacher.setCreateUserId(userId);
teacher.setAccount(item.getAccount());
teacher.setStatus(UserStatus.NORMAL.getId());
teacher.setPwd(item.getPassword());
}
}
//姓名
@@ -133,6 +145,10 @@ public class SchTeacherImportService {
teacherGroupList.add(teacherGroup);
}
teacher.setGroupList(teacherGroupList);
// 主组取第一个组(DTO.groupId 有 @NotNull/@Min 校验,平台推送 batchAddTeacher 也需要主组)
if (!teacherGroupList.isEmpty()) {
teacher.setGroupId(teacherGroupList.get(0).getGroupId());
}
}
//身份证
{
@@ -190,13 +206,30 @@ public class SchTeacherImportService {
throw new DException(ErrorCode.CUSTOM,"导入失败,请检查错误列表",errorMsgArr);
}
List<SchTeacher> saveList = schTeacherRepository.saveAll(teachers);
// 推送平台用户:必须用原 DTO 列表(含 pwd);saveAll 返回的实体不含密码
syncTeacherList = sendUserBaseService.batchAddTeacher(teachers);
// 按顺序回填平台用户ID(batchAddUsers 返回顺序与传入一致)
for (int i = 0; i < teachers.size(); i++) {
if (i < syncTeacherList.size() && syncTeacherList.get(i) != null) {
teachers.get(i).setTeaId(syncTeacherList.get(i).getId());
}
}
// DTO 不能直接传给 saveAll(泛型不变性:List<SchTeacherDTO> 非 List<SchTeacher>),需转实体并保留已回填的 teaId/groupList
List<SchTeacher> teacherEntities = teachers.stream().map(dto -> {
SchTeacher t = new SchTeacher();
BeanUtils.copyProperties(dto, t);
return t;
}).collect(Collectors.toList());
List<SchTeacher> saveList = schTeacherRepository.saveAll(teacherEntities);
List<SchTeacherGroup> schTeacherGroupList = new ArrayList<>();
for (SchTeacher teacher : saveList) {
teacher.setTeaId(teacher.getId());
// teaId 已是平台推送返回的用户ID(batchAddTeacher 已回填),勿用本地 id 覆盖
for (SchTeacherGroup group : teacher.getGroupList()) {
group.setTeaId(teacher.getId());
group.setTeaId(teacher.getTeaId());
}
schTeacherGroupList.addAll(teacher.getGroupList());
}
@@ -213,9 +246,16 @@ public class SchTeacherImportService {
// 清除缓存
cacheService.clearTeacherCache(schId);
} catch (DException e) {
throw e;
} catch (Exception e) {
// 导入失败:回滚已成功推送到平台的教师账号,避免孤儿账号
List<Integer> groupIds = teachers.stream()
.map(SchTeacherDTO::getGroupId).collect(Collectors.toList());
sendUserBaseService.rollbackSyncedTeachers(syncTeacherList, groupIds, schId);
log.error("操作人:" + user.getUserName() + ",导入教师日志失败: {}", e.getMessage(), e);
throw new DException("导入失败,请联系管理员! </br> 错误详情: </br>" + e.getMessage());
}
@@ -6,9 +6,11 @@ import com.yunhai.bschclassmanage.Repository.SchTeacherRepository;
import com.yunhai.bschclassmanage.entity.SchTeacher;
import com.yunhai.bschclassmanage.entity.SchTeacherGroup;
import com.yunhai.bschclassmanage.enums.TransferStatus;
import com.yunhai.bschclassmanage.model.dto.SendMoveGroupUserDTO;
import com.yunhai.bschclassmanage.model.dto.TeaTransferGroupDTO;
import com.yunhai.bschclassmanage.model.dto.TeaTransferInGroupDTO;
import com.yunhai.bschclassmanage.service.IComSchTreeService;
import com.yunhai.bschclassmanage.service.ISendUserBaseService;
import com.yunhai.bschclassmanage.utils.OtherUtil;
import com.yunhai.bschclassmanage.utils.UserContext;
import com.yunhai.platform.utils.exception.DException;
@@ -42,6 +44,9 @@ public class SchTeacherRelationService {
@Autowired
private SchTeacherCacheService cacheService;
@Autowired
private ISendUserBaseService sendUserBaseService;
@Autowired
private SchTeacherLogService logService; // 异步日志
@@ -256,6 +261,17 @@ public class SchTeacherRelationService {
schTeacherGroupRepository.saveAll(newRelations);
}
List<SendMoveGroupUserDTO> teacherList = newRelations.stream()
.map(rel -> {
SendMoveGroupUserDTO dto = new SendMoveGroupUserDTO();
dto.setUserId(rel.getTeaId());
dto.setGroupId(rel.getGroupId());
return dto;
})
.collect(Collectors.toList());
sendUserBaseService.moveTeacherToGroup(teacherList,schId);
// 清除缓存
cacheService.clearTeacherCache(schId);
}