学号等

This commit is contained in:
2026-08-27 14:28:08 +08:00
parent 13409be869
commit ac18366bfb
7 changed files with 155 additions and 100 deletions
@@ -40,7 +40,13 @@ public enum SyncDataType
SEND_MOVE_TEACHER("Send-MoveTeacher","教师移组"),
SEND_MOVE_STUDENT("Send-MoveStudent","学生调班"),
SEND_BATCH_TEACHER("Send-BatchAddTeacher","批量添加教师"),
SEND_BATCH_STUDENT("Send-BatchAddStudent","批量添加学生");
SEND_BATCH_STUDENT("Send-BatchAddStudent","批量添加学生"),
SEND_TRANSFER_OUT("Send-TransferOut","用户转出"),
SEND_TRANSFER_IN("Send-TransferIn","用户转入"),
SEND_USEER_STATUS("Send-UserStatus","用户状态");
private String key;
private String name;
@@ -7,13 +7,14 @@ import lombok.NoArgsConstructor;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.util.List;
/**
* @Author wanghu
* @Date 2026-6-10 15:09 (可以根据需要修改)
* @Description:
* @Description:学生转班/转入共用DTO
* - stuId:单个学生ID(转入 setTransferIn 使用)
* - stuIds:批量学生ID列表(批量转班 transferClass 使用)
*/
@Data
@Builder
@@ -21,8 +22,10 @@ import java.util.List;
@AllArgsConstructor
public class StuTransferClassDTO {
@NotNull(message = "学生ID列表不能为空")
@Size(min = 1, message = "至少选择一个学生")
/** 转入单个学生ID(setTransferIn 使用) */
private Integer stuId;
/** 批量转班学生ID列表(transferClass 使用) */
private List<Integer> stuIds;
@NotNull(message = "目标班级ID不能为空")
@@ -22,7 +22,9 @@ import java.util.List;
public class TeaTransferInGroupDTO {
@NotNull(message = "教师ID列表不能为空")
@Size(min = 1, message = "至少选择一个教师")
private List<String> schTeaIds;
private Integer teaId;
private Integer schId;
@NotNull(message = "目标组ID不能为空")
@Min(value=0, message = "至少选择一个组")
@@ -51,4 +51,12 @@ public interface ISendUserBaseService {
List<BoaUser> batchAddStudent(List<SchStudentDTO> stuList);
List<BoaUser> batchAddTeacher(List<SchTeacherDTO> teacherList);
/** 学生转出:将平台用户状态置为转出(state=1) */
void setUserGroupState(Integer userId, Integer groupId, Integer schoolId);
/** 学生转入:将用户转移到目标学校/班级,返回平台用户信息 */
BoaUser transferUserToSchool(Integer userId, Integer fromSchoolId, Integer schoolId, Integer groupId);
void changeUserStatus(Integer userId,boolean disabled);
}
@@ -11,6 +11,8 @@ 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.OpenApiGroupClient;
import com.yunhai.platform.openapi.client.OpenApiUserClient;
import com.yunhai.platform.openapi.client.YschBaseOpenApi;
import com.yunhai.platform.openapi.model.*;
import com.yunhai.platform.utils.exception.DException;
@@ -32,9 +34,18 @@ import java.util.List;
@Service
public class SendUserBaseService implements ISendUserBaseService {
private static final Logger log = LoggerFactory.getLogger(SendUserBaseService.class);
@Autowired
private IComSchTreeService comSchTreeService;
@Autowired
private OpenApiUserClient openApiUserClient;
@Autowired
private OpenApiGroupClient openApiGroupClient;
@SyncOpLog(SyncDataType.SEND_ADD_GROUP)
public BoaGroup addGroup(String name, Integer parentId, Integer sort, NodeType type,Integer schId){
comSchTreeService.clearCache();
@@ -43,7 +54,7 @@ public class SendUserBaseService implements ISendUserBaseService {
group.setParentId(parentId);
group.setSort(sort);
group.setType(type.getId());
return YschBaseOpenApi.addGroup(group);
return openApiGroupClient.addGroup(group);
}
@@ -55,7 +66,7 @@ public class SendUserBaseService implements ISendUserBaseService {
group.setParentId(parentId);
group.setSort(sort);
group.setType(type.getId());
YschBaseOpenApi.editGroup(id,group);
openApiGroupClient.editGroup(id,group);
}
@SyncOpLog(SyncDataType.SEND_MOVE_GROUP)
@@ -64,7 +75,7 @@ public class SendUserBaseService implements ISendUserBaseService {
SysGroupMoveRequest group=new SysGroupMoveRequest();
group.setMoveId(moveId);
group.setPid(pid);
YschBaseOpenApi.moveGroup(schId,group);
openApiGroupClient.moveGroup(schId,group);
}
@SyncOpLog(SyncDataType.SEND_DELETE_GROUP)
@@ -74,7 +85,7 @@ public class SendUserBaseService implements ISendUserBaseService {
BoaGroup group= YschBaseOpenApi.getGroupById(id,false);
if(group!=null)
{
YschBaseOpenApi.deleteGroup(id,schId);
openApiGroupClient.deleteGroup(id,schId);
}
}finally {
@@ -96,7 +107,7 @@ public class SendUserBaseService implements ISendUserBaseService {
sysUser.setPassword(pwd);
sysUser.setConfirmPassword(pwd);
}
return YschBaseOpenApi.addUser(sysUser);
return openApiUserClient.addUser(sysUser);
}
@SyncOpLog(SyncDataType.SEND_ADD_STUDENT)
@@ -112,7 +123,7 @@ public class SendUserBaseService implements ISendUserBaseService {
sysUser.setPassword(pwd);
sysUser.setConfirmPassword(pwd);
}
return YschBaseOpenApi.addUser(sysUser);
return openApiUserClient.addUser(sysUser);
}
@SyncOpLog(SyncDataType.SEND_EDIT_TEACHER)
@@ -131,7 +142,7 @@ public class SendUserBaseService implements ISendUserBaseService {
if (StringUtils.isNotBlank(pwd)) {
user.setPassword(pwd);
}
return YschBaseOpenApi.editUser(teacher.getTeaId(),user);
return openApiUserClient.editUser(teacher.getTeaId(),user);
}
@SyncOpLog(SyncDataType.SEND_EDIT_STUDENT)
@@ -149,7 +160,7 @@ public class SendUserBaseService implements ISendUserBaseService {
if (StringUtils.isNotBlank(pwd)) {
user.setPassword(pwd);
}
return YschBaseOpenApi.editUser(student.getStuId(),user);
return openApiUserClient.editUser(student.getStuId(),user);
}
@@ -165,7 +176,7 @@ public class SendUserBaseService implements ISendUserBaseService {
}
if(deletes!=null&&deletes.size()>0)
{
YschBaseOpenApi.deleteUsers(deletes);
openApiUserClient.deleteUsers(deletes);
}
}
@@ -181,7 +192,7 @@ public class SendUserBaseService implements ISendUserBaseService {
}
if(deletes!=null&&deletes.size()>0)
{
YschBaseOpenApi.deleteUsers(deletes);
openApiUserClient.deleteUsers(deletes);
}
}
@@ -227,7 +238,7 @@ public class SendUserBaseService implements ISendUserBaseService {
}
}
private static final Logger log = LoggerFactory.getLogger(SendUserBaseService.class);
/**
* 导入失败回滚:删除已成功推送到平台的组(年级组/班级组/学段组),避免留下孤儿组。
@@ -257,7 +268,7 @@ public class SendUserBaseService implements ISendUserBaseService {
SysUserMoveRequest move=new SysUserMoveRequest();
move.setUserId(teacher.getUserId());
move.setGroupId(teacher.getGroupId());
YschBaseOpenApi.moveUserToGroup(move);
openApiUserClient.moveUserToGroup(move);
}
}
@@ -269,7 +280,7 @@ public class SendUserBaseService implements ISendUserBaseService {
move.setUserId(stuId);
move.setGroupId(classId);
move.setSchoolId(schId);
YschBaseOpenApi.moveUserToGroup(move);
openApiUserClient.moveUserToGroup(move);
}
}
@@ -294,7 +305,7 @@ public class SendUserBaseService implements ISendUserBaseService {
}
requests.add(sysUser);
}
return YschBaseOpenApi.batchAddUsers(requests);
return openApiUserClient.batchAddUsers(requests);
}
@SyncOpLog(SyncDataType.SEND_BATCH_TEACHER)
@@ -320,8 +331,40 @@ public class SendUserBaseService implements ISendUserBaseService {
}
requests.add(sysUser);
}
return YschBaseOpenApi.batchAddUsers(requests);
return openApiUserClient.batchAddUsers(requests);
}
@SyncOpLog(SyncDataType.SEND_TRANSFER_OUT)
@Override
public void setUserGroupState(Integer userId,Integer groupId,Integer schoolId)
{
//状态设置成1(转出)
SysUserGroupStateRequest request = new SysUserGroupStateRequest();
request.setUserId(userId);
request.setGroupId(groupId);
request.setSchoolId(schoolId);
request.setState(1);
openApiUserClient.setUserGroupState(request);
}
@SyncOpLog(SyncDataType.SEND_TRANSFER_IN)
@Override
public BoaUser transferUserToSchool(Integer userId,Integer fromSchoolId,Integer schoolId,Integer groupId)
{
SysUserTransferSchoolRequest request = new SysUserTransferSchoolRequest();
request.setUserId(userId);
request.setFromSchoolId(fromSchoolId);
request.setSchoolId(schoolId);
request.setGroupId(groupId);
return openApiUserClient.transferUserToSchool(request);
}
@SyncOpLog(SyncDataType.SEND_USEER_STATUS)
@Override
public void changeUserStatus(Integer userId,boolean disabled)
{
openApiUserClient.changeUserStatus(userId,disabled);
}
}
@@ -54,6 +54,9 @@ public class SchStudentTransferService {
Integer targetClassId = model.getTransferClassId();
List<Integer> stuIds = model.getStuIds();
if (stuIds == null || stuIds.isEmpty()) {
throw new DException("学生ID列表不能为空");
}
Date now = new Date();
// 校验目标班级是否存在且属于该校
@@ -136,6 +139,8 @@ public class SchStudentTransferService {
throw new DException("以下学生不存在或不属于该校: " + missing);
}
List<Integer> syncStuIds=students.stream().map(s->s.getStuId()).collect(Collectors.toList());
// 收集受影响的班级ID
Set<Integer> classIds = students.stream()
.map(SchStudent::getClassId)
@@ -159,69 +164,61 @@ public class SchStudentTransferService {
// 异步记录操作日志
logService.setTransferOutLog(user, students, classIds);
for (SchStudent stu:students)
{
sendUserBaseService.setUserGroupState(stu.getStuId(),stu.getGroupId(),stu.getSchId());
}
}
// ==================== 转入 ====================
/**
* 批量转入学生(将学生从其他学校/班级转入到目标班级)
* 转入学生(将学生从其他学校/班级转入到目标班级)
*/
public void setTransferIn(UserContext.UserInfo user, StuTransferClassDTO model) {
Integer targetSchId = user.getSchId();
Integer targetClassId = model.getTransferClassId();
List<Integer> stuIds = model.getStuIds();
Date now = new Date();
// 校验目标班级是否属于本校
schClassRepository.findByClassIdAndSchId(targetClassId, targetSchId)
.orElseThrow(() -> new DException("目标班级不存在"));
// 全局查询所有学生(必须用 findAllById,因为要跨校查)
List<SchStudent> students = schStudentRepository.findAllById(stuIds);
if (students.size() != stuIds.size()) {
Set<Integer> foundIds = students.stream().map(SchStudent::getId).collect(Collectors.toSet());
List<Integer> missing = stuIds.stream().filter(id -> !foundIds.contains(id)).collect(Collectors.toList());
throw new DException("以下学生不存在: " + missing);
// 全局查询学生(必须跨校查,学生可能在其他学校)
if (model.getStuId() == null) {
throw new DException("学生ID不能为空");
}
// 过滤出真正需要更新的学生:排除已在目标学校且已在目标班级的学生
List<SchStudent> toUpdateStudents = students.stream()
.filter(s -> !(s.getSchId().equals(targetSchId) && targetClassId.equals(s.getClassId())))
.collect(Collectors.toList());
SchStudent student = schStudentRepository.findById(model.getStuId())
.orElseThrow(() -> new DException("学生不存在!"));
if (toUpdateStudents.isEmpty()) {
// 所有学生已在本校目标班级,无需操作
return;
// 已在目标学校且已在目标班级的学生无需操作
if (student.getSchId().equals(targetSchId) && targetClassId.equals(student.getClassId())) {
throw new DException("已在目标学校且已在目标班级的学生无需操作!");
}
// 收集受影响的缓存Key(旧班级 + 新班级)
Set<String> cacheKeysToDelete = new HashSet<>();
for (SchStudent student : toUpdateStudents) {
if (student.getClassId() != null) {
String oldCacheKey = RedisConstants.SCHOOL_CLASS_STUDENT + "_"
+ student.getSchId() + "_" + student.getClassId();
cacheKeysToDelete.add(oldCacheKey);
}
if (student.getClassId() != null) {
cacheKeysToDelete.add(RedisConstants.SCHOOL_CLASS_STUDENT + "_"
+ student.getSchId() + "_" + student.getClassId());
}
// 新班级缓存(目标学校+目标班级)
String newCacheKey = RedisConstants.SCHOOL_CLASS_STUDENT + "_"
+ targetSchId + "_" + targetClassId;
cacheKeysToDelete.add(newCacheKey);
// 执行批量更新(更新学校和班级)
List<Integer> idsToUpdate = toUpdateStudents.stream()
.map(SchStudent::getId)
.collect(Collectors.toList());
cacheKeysToDelete.add(RedisConstants.SCHOOL_CLASS_STUDENT + "_"
+ targetSchId + "_" + targetClassId);
// 执行批量更新(更新学校和班级,transferStatus 置为转入 0)
int updated = schStudentRepository.batchUpdateSchIdAndClassId(
idsToUpdate,
Collections.singletonList(student.getId()),
targetSchId,
targetClassId,
now,
user.getUserId()
);
if (updated != idsToUpdate.size()) {
throw new DException("批量更新失败,可能部分学生已被删除或修改,请刷新后重试");
if (updated != 1) {
throw new DException("批量更新失败,可能学生已被删除或修改,请刷新后重试");
}
// 清除缓存(直接按Key删除)
@@ -229,7 +226,10 @@ public class SchStudentTransferService {
redisUtil.del(cacheKey);
}
// 平台同步:转入目标学校/班级(fromSchoolId 取转入前的原学校)
sendUserBaseService.transferUserToSchool(student.getStuId(), student.getSchId(), targetSchId, targetClassId);
// 异步记录操作日志
logService.setTransferInLog(user, toUpdateStudents, targetSchId, targetClassId);
logService.setTransferInLog(user, Collections.singletonList(student), targetSchId, targetClassId);
}
}
@@ -111,6 +111,12 @@ public class SchTeacherRelationService {
throw new DException("转出失败");
}
for (SchTeacher tea: teachers)
{
Integer groupId=tea.getGroupList().stream().map(s->s.getGroupId()).findFirst().get();
sendUserBaseService.setUserGroupState(tea.getTeaId(),groupId,schId);
}
// 5. 异步日志
logService.setTransferOutLogs(user, teachers);
@@ -122,11 +128,15 @@ public class SchTeacherRelationService {
public void setTransferIn(UserContext.UserInfo user, TeaTransferInGroupDTO model) {
Integer targetSchId = user.getSchId();
List<String> schTeaIds = model.getSchTeaIds();
Integer targetGroupId = model.getTransferGroupId();
Integer teaId = model.getTeaId();
Integer fromSchId = model.getSchId();
if (schTeaIds == null || schTeaIds.isEmpty()) {
throw new DException("教师关联列表不能为空");
if (teaId == null || teaId <= 0) {
throw new DException("教师ID不能为空");
}
if (fromSchId == null || fromSchId <= 0) {
throw new DException("原学校ID不能为空");
}
if (targetGroupId == null || targetGroupId <= 0) {
throw new DException("目标组ID不合法");
@@ -135,60 +145,43 @@ public class SchTeacherRelationService {
// 校验目标组属于当前学校
comSchTreeService.validateGroupsBelongToSchool(targetSchId, Collections.singletonList(targetGroupId));
// 解析 schTeaIds
List<SchTeacherGroup> oldRelations = new ArrayList<>();
List<Integer> teaIdList = new ArrayList<>();
for (String item : schTeaIds) {
String[] parts = item.split("_");
if (parts.length != 2) {
throw new DException("无效的教师关联格式: " + item + ",应为 'schId_teaId'");
}
Integer schId, teaId;
try {
schId = Integer.parseInt(parts[0]);
teaId = Integer.parseInt(parts[1]);
} catch (NumberFormatException e) {
throw new DException("教师关联包含非数字字符: " + item);
}
List<SchTeacherGroup> relations = schTeacherGroupRepository.findByTeaIdAndSchId(teaId, schId);
if (relations.isEmpty()) {
throw new DException("教师 teaId=" + teaId + " 在学校 schId=" + schId + " 下无关联记录");
}
oldRelations.addAll(relations);
teaIdList.add(teaId);
// 查询教师在原学校的关联记录(可跨校)
List<SchTeacherGroup> oldRelations = schTeacherGroupRepository.findByTeaIdAndSchId(teaId, fromSchId);
if (oldRelations.isEmpty()) {
throw new DException("教师 teaId=" + teaId + " 在学校 schId=" + fromSchId + " 下无关联记录");
}
teaIdList = teaIdList.stream().distinct().collect(Collectors.toList());
// 删除所有旧关联
if (!oldRelations.isEmpty()) {
schTeacherGroupRepository.deleteAll(oldRelations);
// 已在目标学校且已在目标组,无需操作
boolean alreadyInTarget = oldRelations.stream()
.anyMatch(r -> targetSchId.equals(r.getSchId()) && targetGroupId.equals(r.getGroupId()));
if (alreadyInTarget) {
return;
}
// 插入新关联
List<SchTeacherGroup> newRelations = new ArrayList<>();
for (Integer teaId : teaIdList) {
SchTeacherGroup newRel = new SchTeacherGroup();
newRel.setTeaId(teaId);
newRel.setGroupId(targetGroupId);
newRel.setSchId(targetSchId);
newRel.setTransferStatus(TransferStatus.IN.getId());
newRelations.add(newRel);
}
// 删除原学校旧关联
schTeacherGroupRepository.deleteAll(oldRelations);
if (!newRelations.isEmpty()) {
List<SchTeacher> teachers = schTeacherRepository.findByTeaIdIn(teaIdList);
logService.setTransferInLogs(user, teachers, targetGroupId);
schTeacherGroupRepository.saveAll(newRelations);
}
// 插入目标学校/目标组新关联(transferStatus 置为转入 0)
SchTeacherGroup newRel = new SchTeacherGroup();
newRel.setTeaId(teaId);
newRel.setGroupId(targetGroupId);
newRel.setSchId(targetSchId);
newRel.setTransferStatus(TransferStatus.IN.getId());
schTeacherGroupRepository.save(newRel);
// 平台同步:转入目标学校/目标组
sendUserBaseService.transferUserToSchool(teaId, fromSchId, targetSchId, targetGroupId);
// 异步记录操作日志
schTeacherRepository.findByTeaId(teaId).ifPresent(teacher ->
logService.setTransferInLogs(user, Collections.singletonList(teacher), targetGroupId));
// 清除所有涉及学校的缓存
Set<Integer> involvedSchIds = new HashSet<>();
involvedSchIds.add(targetSchId);
oldRelations.forEach(r -> involvedSchIds.add(r.getSchId()));
cacheService.clearTeacherCaches(involvedSchIds);
}
// ==================== 移动组 ====================