课表申请功能重写 bug修复

This commit is contained in:
liumengyu
2026-08-25 18:47:22 +08:00
parent aa4145fd33
commit a30b963dea
58 changed files with 1203 additions and 1632 deletions
@@ -18,7 +18,6 @@ import com.roomroot.jwgl.dto.courserunning.StudentLeaveApplyDTO;
import com.roomroot.jwgl.dto.courserunning.StudentLeaveAuditDTO;
import com.roomroot.jwgl.dto.courserunning.StudentLeaveQueryDTO;
import com.roomroot.jwgl.dto.courserunning.OperationAnalysisQueryDTO;
import com.roomroot.jwgl.dto.courserunning.ScheduleAdjustStrategyDTO;
import com.roomroot.jwgl.unit.PageResult;
import com.roomroot.jwgl.vo.courserunning.AdjustableLessonVO;
import com.roomroot.jwgl.vo.courserunning.CourseRunningImportResultVO;
@@ -37,7 +36,6 @@ import com.roomroot.jwgl.vo.courserunning.OperationOverviewVO;
import com.roomroot.jwgl.vo.courserunning.CourseCompletionByDeptVO;
import com.roomroot.jwgl.vo.courserunning.VenueUsageRateVO;
import com.roomroot.jwgl.vo.courserunning.ScheduleAdjustTrendVO;
import com.roomroot.jwgl.vo.courserunning.ScheduleAdjustStrategyVO;
import java.util.List;
@@ -215,101 +213,23 @@ public interface CourseRunningImportService {
/**
* 教研室审批调课申请。
* <p>
* 教研室审批教员提交的调课申请,包含同意、发回、拒绝三种处理方式。
* 同意时同步更新课次数据,发回时记录发回原因,拒绝时标记申请为已拒绝。
* 教研室审批调课申请。点审批即已查收,审批人同时记为查收人。
* 同意后写回课次;发回、拒绝也记为已查收。
* </p>
*
* @param dto 教研室审批参数
*/
void auditByTeachingOffice(ScheduleAdjustAuditDTO dto);
/**
* 教研室查收调课申请。
* <p>
* 教研室查收调课申请,标记查收状态和查收时间。
* </p>
*
* @param ssdksqbh 调课申请编号
* @param csrbh 查收人编号
*/
void receiveByTeachingOffice(String ssdksqbh, String csrbh);
/**
* 教学系审批调课申请。
* <p>
* 教学系审批教研室已同意的调课申请,包含同意、发回、拒绝三种处理方式。
* 教学系同意后流转到机关审批。
* </p>
*
* @param dto 教学系审批参数
*/
void auditByTeachingDepartment(ScheduleAdjustAuditDTO dto);
/**
* 机关审批调课申请。
* <p>
* 机关审批教研室已同意的调课申请,包含同意、发回、拒绝三种处理方式。
* 机关全部同意后调课申请最终生效,课次按调整后的内容执行。
* </p>
*
* @param dto 机关审批参数
*/
void auditByAuthority(ScheduleAdjustAuditDTO dto);
/**
* 机关查收调课申请。
* <p>
* 机关查收调课申请,标记查收状态和查收时间。
* </p>
*
* @param ssdksqbh 调课申请编号
* @param jgbh 机关编号
* @param csrbh 查收人编号
*/
void receiveByAuthority(String ssdksqbh, String jgbh, String csrbh);
/**
* 撤销调课申请。
* <p>
* 教员撤销自己提交的、未经过审批的调课申请。
* 软删除调课申请,标记删除状态为1。
* 教员撤销未经过审批的调课申请。列表已按登录教员过滤。
* </p>
*
* @param ssdksqbh 调课申请编号
* @param sqjybh 申请教员编号(用于权限校验)
*/
void cancelScheduleAdjust(String ssdksqbh, String sqjybh);
// ==================== 调课策略管理 ====================
/**
* 查询调课策略列表。
* <p>
* 支持按策略类型筛选,返回所有策略(含停用)。
* </p>
*
* @param cllx 策略类型:TIME_LIMIT/AUTO_APPROVE,为空时查询全部
* @return 调课策略列表
*/
List<ScheduleAdjustStrategyVO> listScheduleAdjustStrategies(String cllx);
/**
* 保存调课策略(新增或修改)。
* <p>
* 策略编号为空时执行新增,非空时执行修改。
* </p>
*
* @param dto 策略参数
* @return 策略编号
*/
String saveScheduleAdjustStrategy(ScheduleAdjustStrategyDTO dto);
/**
* 删除调课策略。
*
* @param clbh 策略编号
*/
void deleteScheduleAdjustStrategy(String clbh);
void cancelScheduleAdjust(String ssdksqbh);
// ==================== 教学保障管理 ====================
@@ -76,6 +76,16 @@ public interface FacultyService {
*/
JYB getJYBById(String jYBH);
/**
* 从 Excel(.xls/.xlsx) 导入教员
*/
int importJYBFromExcel(MultipartFile file) throws Exception;
/**
* 导出教员到 Excel(.xlsx)
*/
void exportJYBExcel(jakarta.servlet.http.HttpServletResponse response) throws Exception;
/**
* 分页条件查询教员列表
*/
@@ -53,4 +53,10 @@ public interface TrainingProgramService {
* @return 分页结果
*/
PageResult<ZYB> pageList(PageQuery query, ZYB cond);
/** 从 Excel(.xls/.xlsx) 导入培养方案(专业) */
int importZYBFromExcel(org.springframework.web.multipart.MultipartFile file) throws Exception;
/** 导出培养方案(专业)到 Excel(.xlsx) */
void exportZYBExcel(jakarta.servlet.http.HttpServletResponse response) throws Exception;
}
@@ -60,4 +60,10 @@ public interface ZYJXJHBService {
* @return 列表
*/
List<ZYJXJHB> listByZydhAndTy(String zydh, Integer ty);
/** 从 Excel(.xls/.xlsx) 导入专业教学计划 */
int importZYJXJHBFromExcel(org.springframework.web.multipart.MultipartFile file) throws Exception;
/** 导出专业教学计划到 Excel(.xlsx) */
void exportZYJXJHBExcel(jakarta.servlet.http.HttpServletResponse response) throws Exception;
}
@@ -112,12 +112,6 @@ public class CourseRunningImportServiceImpl implements CourseRunningImportServic
@Resource
private KCBMapper kcbMapper;
/**
* 实施_调课申请审批 Mapper,用于调课申请审批记录的数据访问。
*/
@Resource
private SSDKSQSPMapper ssdksqspMapper;
/**
* 调课申请_教室 Mapper,用于调课申请中教室关联的数据访问。
*/
@@ -196,12 +190,6 @@ public class CourseRunningImportServiceImpl implements CourseRunningImportServic
@Resource
private OperationAnalysisMapper operationAnalysisMapper;
/**
* 调课策略 Mapper,用于调课时间段限制策略与免审批策略的数据访问。
*/
@Resource
private ScheduleAdjustStrategyMapper scheduleAdjustStrategyMapper;
/**
* 教员表数据访问接口,用于审批时根据教员编号查询教研室代号。
*/
@@ -533,16 +521,17 @@ public class CourseRunningImportServiceImpl implements CourseRunningImportServic
* @param operationContent 操作内容描述
*/
private void recordOperationLog(String targetId, String operationType, String operationContent) {
// 创建日志实体
KCJXYX_CZRZ log = new KCJXYX_CZRZ();
log.setBh(UuidUtil.getOriginalUUID()); // 生成唯一编号
log.setTybh(targetId); // 目标编号
log.setCzlx(operationType); // 操作类型
log.setCznr(operationContent); // 操作内容
log.setCzsj(LocalDateTime.now()); // 操作时间
// 写入数据库
kcjxyxCzrzMapper.insert(log);
try {
KCJXYX_CZRZ log = new KCJXYX_CZRZ();
log.setBh(UuidUtil.getOriginalUUID());
log.setTybh(targetId);
log.setCzlx(operationType);
log.setCznr(operationContent);
log.setCzsj(LocalDateTime.now());
kcjxyxCzrzMapper.insert(log);
} catch (Exception ignored) {
// 操作日志表缺失或字段不匹配时,不影响调课主流程
}
}
// ==================== 教学实施计划填写 ====================
@@ -895,7 +884,6 @@ public class CourseRunningImportServiceImpl implements CourseRunningImportServic
query.getNd(),
query.getJyspzzt(),
query.getJyscszt(),
query.getJgspzt(),
query.getSczt(),
cjsjStartStr,
cjsjEndStr
@@ -910,61 +898,22 @@ public class CourseRunningImportServiceImpl implements CourseRunningImportServic
@Override
public List<AdjustableLessonVO> listAdjustableLessons(Integer nd) {
if (jwglRoleHelper.isDepartmentPersonnel()) {
throw new BusinessException(BasicManagementConstants.FORBIDDEN, "机关人员仅可查看和审批调课申请");
}
if (jwglRoleHelper.isResearchOffice()) {
throw new BusinessException(BasicManagementConstants.FORBIDDEN, "教研室仅可查看和审批本室调课申请");
}
String teacherId = jwglRoleHelper.requireTeacherId();
return ssdksqMapper.selectAdjustableLessons(teacherId, nd);
return ssdksqMapper.selectAdjustableLessons(jwglRoleHelper.requireTeacherId(), nd);
}
private void applyScheduleAdjustDataScope(ScheduleAdjustQueryDTO query) {
if (jwglRoleHelper.isAdmin() || jwglRoleHelper.isDepartmentPersonnel()) {
return;
}
if (jwglRoleHelper.isResearchOffice()) {
query.setJysdh(jwglRoleHelper.requireResearchOfficeId());
query.setSqjybh(null);
return;
}
if (jwglRoleHelper.isTeacher()) {
query.setSqjybh(jwglRoleHelper.requireTeacherId());
query.setJysdh(null);
return;
}
throw new BusinessException(BasicManagementConstants.FORBIDDEN, "无权查看调课申请");
}
private void assertCanViewScheduleAdjust(SSDKSQ apply) {
if (jwglRoleHelper.isAdmin() || jwglRoleHelper.isDepartmentPersonnel()) {
return;
}
if (jwglRoleHelper.isResearchOffice()) {
String officeId = jwglRoleHelper.requireResearchOfficeId();
String applyOffice = apply.getJysdh();
if (StringUtils.isEmpty(applyOffice) && StringUtils.isNotEmpty(apply.getSqjybh())) {
JYB teacher = jybMapper.selectById(apply.getSqjybh());
applyOffice = teacher == null ? null : teacher.getJysdh();
}
if (applyOffice == null || !officeId.equals(applyOffice.trim())) {
throw new BusinessException(BasicManagementConstants.FORBIDDEN, "只能查看本教研室的调课申请");
}
return;
}
if (jwglRoleHelper.isTeacher()) {
String teacherId = jwglRoleHelper.requireTeacherId();
if (apply.getSqjybh() == null || !teacherId.equals(apply.getSqjybh().trim())) {
throw new BusinessException(BasicManagementConstants.FORBIDDEN, "只能查看本人提交的调课申请");
}
return;
}
throw new BusinessException(BasicManagementConstants.FORBIDDEN, "无权查看调课申请");
}
private String currentOperatorId() {
try {
String teacherId = jwglRoleHelper.findTeacherId();
if (StringUtils.isNotEmpty(teacherId)) {
return teacherId.trim();
}
String username = SecurityUtils.getUsername();
if (StringUtils.isNotEmpty(username)) {
return username;
@@ -987,37 +936,17 @@ public class CourseRunningImportServiceImpl implements CourseRunningImportServic
*/
@Override
public ScheduleAdjustDetailVO getScheduleAdjustDetail(String ssdksqbh) {
// 步骤1:校验调课申请编号参数
if (ssdksqbh == null || ssdksqbh.trim().isEmpty()) {
throw new BusinessException(BasicManagementConstants.BAD_REQUEST, "调课申请编号不能为空");
}
// 步骤2:查询调课申请主表信息
ScheduleAdjustDetailVO detail = ssdksqMapper.selectDetailById(ssdksqbh);
if (detail == null) {
throw new BusinessException(BasicManagementConstants.NOT_FOUND, "未找到该调课申请");
}
SSDKSQ apply = ssdksqMapper.selectById(ssdksqbh);
if (apply != null) {
assertCanViewScheduleAdjust(apply);
}
// 步骤3:查询关联的机关审批记录列表
detail.setAuditList(ssdksqspMapper.selectBySsdksqbh(ssdksqbh));
// 步骤4:查询关联的新教室列表
detail.setRoomList(dksqjsMapper.selectByDksqbh(ssdksqbh));
// 步骤5:查询关联的新辅助教员列表
detail.setTeacherList(dksqfzjyMapper.selectByDksqbh(ssdksqbh));
// 步骤6:查询关联的新学员队列表
detail.setTeamList(dksqxydMapper.selectByDksqbh(ssdksqbh));
// 步骤7:查询关联的新保障明细列表
detail.setSupportList(dksqbzmxMapper.selectByDksqbh(ssdksqbh));
// 步骤8:返回调课申请完整详情
return detail;
}
@@ -1036,30 +965,11 @@ public class CourseRunningImportServiceImpl implements CourseRunningImportServic
@Override
@Transactional(rollbackFor = Exception.class)
public String submitScheduleAdjust(ScheduleAdjustApplyDTO dto) {
if (dto == null) {
throw new BusinessException(BasicManagementConstants.BAD_REQUEST, "调课申请参数不能为空");
}
if (jwglRoleHelper.isDepartmentPersonnel()) {
throw new BusinessException(BasicManagementConstants.FORBIDDEN, "机关人员仅可查看和审批,不能提交调课申请");
}
if (jwglRoleHelper.isResearchOffice()) {
throw new BusinessException(BasicManagementConstants.FORBIDDEN, "教研室仅可查看和审批本室申请,不能提交调课申请");
}
if (StringUtils.isEmpty(dto.getSskcbbh())) {
throw new BusinessException(BasicManagementConstants.BAD_REQUEST, "课次编号不能为空");
}
if (dto.getSy() == null || dto.getSy().trim().isEmpty()) {
throw new BusinessException(BasicManagementConstants.BAD_REQUEST, "调课事由不能为空");
}
String teacherId = jwglRoleHelper.requireTeacherId();
SSKCB lesson = sskcbMapper.selectById(dto.getSskcbbh().trim());
if (lesson == null) {
if (lesson == null || (lesson.getSczt() != null && lesson.getSczt() == 1)) {
throw new BusinessException(BasicManagementConstants.NOT_FOUND, "课次不存在");
}
if (lesson.getSczt() != null && lesson.getSczt() == 1) {
throw new BusinessException(BasicManagementConstants.BAD_REQUEST, "该课次已删除,不允许申请调课");
}
AdjustableLessonVO picked = null;
List<AdjustableLessonVO> mine = ssdksqMapper.selectAdjustableLessons(teacherId, lesson.getNd());
@@ -1072,59 +982,55 @@ public class CourseRunningImportServiceImpl implements CourseRunningImportServic
}
}
if (picked == null) {
throw new BusinessException(BasicManagementConstants.FORBIDDEN, "只能对自己任课的课次申请调课");
throw new BusinessException(BasicManagementConstants.NOT_FOUND, "课次不存在");
}
validateScheduleAdjustTimeLimitStrategy(dto.getRq());
boolean autoApproved = matchAutoApproveStrategy();
SSDKSQ apply = new SSDKSQ();
String ssdksqbh = UuidUtil.getOriginalUUID();
apply.setBh(ssdksqbh);
apply.setSskcbbh(lesson.getBh());
apply.setXydrwbh(StringUtils.isNotEmpty(dto.getXydrwbh()) ? dto.getXydrwbh() : picked.getXydrwbh());
apply.setKbh(StringUtils.isNotEmpty(dto.getKbh()) ? dto.getKbh() : picked.getKbh());
apply.setKcbbh(StringUtils.isNotEmpty(dto.getKcbbh()) ? dto.getKcbbh() : picked.getKcbbh());
apply.setJysdh(picked.getJysdh());
apply.setYjsbh(picked.getJsbh());
apply.setXjsbh(resolveNewClassroom(dto));
apply.setSqjybh(teacherId);
apply.setSy(dto.getSy());
apply.setYdsjap(resolveYdsjap(lesson));
apply.setZxzt(0);
apply.setYszt(0);
apply.setXydrwbh(cut(StringUtils.isNotEmpty(dto.getXydrwbh()) ? dto.getXydrwbh() : picked.getXydrwbh(), 50));
apply.setKbh(cut(StringUtils.isNotEmpty(dto.getKbh()) ? dto.getKbh() : picked.getKbh(), 50));
apply.setKcbbh(cut(StringUtils.isNotEmpty(dto.getKcbbh()) ? dto.getKcbbh() : picked.getKcbbh(), 50));
apply.setJysdh(cut(picked.getJysdh(), 50));
apply.setYjsbh(cut(picked.getJsbh(), 50));
apply.setXjsbh(cut(resolveNewClassroom(dto), 50));
apply.setSqjybh(cut(teacherId, 50));
apply.setSy(cut(dto.getSy(), 200));
apply.setRq(dto.getRq());
apply.setJc(dto.getJc());
apply.setNd(dto.getNd() != null ? dto.getNd() : lesson.getNd());
apply.setJxnr(dto.getJxnr());
apply.setJc(dto.getJc() != null ? dto.getJc() : 0);
apply.setNd(dto.getNd() != null ? dto.getNd() : (lesson.getNd() != null ? lesson.getNd() : 0));
apply.setJxnr(cut(dto.getJxnr(), 500));
apply.setJxyd(dto.getJxyd());
apply.setJxff(dto.getJxff());
String jxff = cut(dto.getJxff(), 50);
apply.setJxff(jxff == null ? "" : jxff);
apply.setJxbzbz(dto.getJxbzbz());
apply.setYcxx(dto.getYcxx());
String originalDesc = buildOriginalScheduleDesc(lesson);
if (dto.getBz() != null && !dto.getBz().trim().isEmpty()) {
apply.setBz(dto.getBz() + " | " + originalDesc);
} else {
apply.setBz(originalDesc);
}
if (autoApproved) {
apply.setBz((apply.getBz() == null ? "" : apply.getBz() + " | ") + "[免审批策略自动通过]");
apply.setJyspzzt(1);
} else {
apply.setJyspzzt(0);
}
apply.setBz(cut(dto.getBz(), 50));
apply.setJyspzzt(0);
apply.setJyscszt(0);
apply.setSczt(0);
apply.setFhzt(0);
apply.setDk(1);
LocalDateTime now = LocalDateTime.now();
apply.setCjsj(now);
apply.setCjsj(LocalDateTime.now());
ssdksqMapper.insert(apply);
if (dto.getRoomList() != null && !dto.getRoomList().isEmpty()) {
for (AdjustRoomDTO roomDto : dto.getRoomList()) {
if (StringUtils.isEmpty(roomDto.getJsbh())) {
continue;
}
DKSQJS roomEntity = new DKSQJS();
roomEntity.setBh(UuidUtil.getOriginalUUID());
roomEntity.setDksqbh(ssdksqbh);
roomEntity.setJsbh(roomDto.getJsbh());
roomEntity.setBz(roomDto.getBz());
roomEntity.setNd(apply.getNd());
roomEntity.setRq(apply.getRq());
roomEntity.setJc(apply.getJc());
dksqjsMapper.insert(roomEntity);
}
} else if (StringUtils.isNotEmpty(apply.getXjsbh())) {
@@ -1132,44 +1038,61 @@ public class CourseRunningImportServiceImpl implements CourseRunningImportServic
roomEntity.setBh(UuidUtil.getOriginalUUID());
roomEntity.setDksqbh(ssdksqbh);
roomEntity.setJsbh(apply.getXjsbh());
roomEntity.setNd(apply.getNd());
roomEntity.setRq(apply.getRq());
roomEntity.setJc(apply.getJc());
dksqjsMapper.insert(roomEntity);
}
if (dto.getTeacherList() != null && !dto.getTeacherList().isEmpty()) {
for (AdjustTeacherDTO teacherDto : dto.getTeacherList()) {
if (StringUtils.isEmpty(teacherDto.getFzjybh())) {
continue;
}
DKSQFZJY teacherEntity = new DKSQFZJY();
teacherEntity.setBh(UuidUtil.getOriginalUUID());
teacherEntity.setDksqbh(ssdksqbh);
teacherEntity.setFzjybh(teacherDto.getFzjybh());
teacherEntity.setZjy(teacherDto.getZjy());
teacherEntity.setZjy(teacherDto.getZjy() == null ? 0 : teacherDto.getZjy());
teacherEntity.setBz(teacherDto.getBz());
teacherEntity.setNd(apply.getNd());
teacherEntity.setRq(apply.getRq());
teacherEntity.setJc(apply.getJc());
dksqfzjyMapper.insert(teacherEntity);
}
}
if (dto.getTeamList() != null && !dto.getTeamList().isEmpty()) {
for (AdjustTeamDTO teamDto : dto.getTeamList()) {
if (StringUtils.isEmpty(teamDto.getXydbh())) {
continue;
}
DKSQXYD teamEntity = new DKSQXYD();
teamEntity.setBh(UuidUtil.getOriginalUUID());
teamEntity.setDksqbh(ssdksqbh);
teamEntity.setXydbh(teamDto.getXydbh());
teamEntity.setNd(apply.getNd());
teamEntity.setRq(apply.getRq());
teamEntity.setJc(apply.getJc());
dksqxydMapper.insert(teamEntity);
}
}
if (dto.getSupportList() != null && !dto.getSupportList().isEmpty()) {
for (AdjustSupportDTO supportDto : dto.getSupportList()) {
if (StringUtils.isEmpty(supportDto.getBztgmxbh()) || supportDto.getSl() == null) {
continue;
}
DKSQBZMX supportEntity = new DKSQBZMX();
supportEntity.setBh(UuidUtil.getOriginalUUID());
supportEntity.setSqbh(ssdksqbh);
supportEntity.setBztgmxbh(supportDto.getBztgmxbh());
supportEntity.setSl(supportDto.getSl());
supportEntity.setBz(supportDto.getBz());
supportEntity.setNd(apply.getNd());
supportEntity.setRq(apply.getRq());
supportEntity.setJc(apply.getJc());
dksqbzmxMapper.insert(supportEntity);
}
}
if (autoApproved) {
applyApprovedSchedule(apply);
}
recordOperationLog(ssdksqbh, "申请", "提交调课申请:" + ssdksqbh);
return ssdksqbh;
}
@@ -1203,6 +1126,32 @@ public class CourseRunningImportServiceImpl implements CourseRunningImportServic
return kcbMapper.selectOne(wrapper);
}
private int resolveYdsjap(SSKCB lesson) {
if (lesson == null) {
return 0;
}
if (lesson.getJhsjap() != null) {
return lesson.getJhsjap();
}
if (lesson.getRq() != null) {
return lesson.getRq().getYear() * 10000
+ lesson.getRq().getMonthValue() * 100
+ lesson.getRq().getDayOfMonth();
}
return 0;
}
private String cut(String value, int max) {
if (value == null) {
return null;
}
String text = value.trim();
if (text.isEmpty()) {
return null;
}
return text.length() <= max ? text : text.substring(0, max);
}
private String resolveNewClassroom(ScheduleAdjustApplyDTO dto) {
if (StringUtils.isNotEmpty(dto.getXjsbh())) {
return dto.getXjsbh().trim();
@@ -1217,8 +1166,8 @@ public class CourseRunningImportServiceImpl implements CourseRunningImportServic
/**
* 教研室审批调课申请。
* <p>
* 教研室审批教员提交的调课申请,包含同意、发回、拒绝三种处理方式。
* 同意时同步更新课次数据,发回时记录发回原因,拒绝时标记申请为已拒绝。
* 教研室审批调课申请。点审批即已查收,审批人同时记为查收人。
* 同意后写回课次;发回、拒绝也记为已查收。
* </p>
*
* @param dto 教研室审批参数
@@ -1226,26 +1175,6 @@ public class CourseRunningImportServiceImpl implements CourseRunningImportServic
@Override
@Transactional(rollbackFor = Exception.class)
public void auditByTeachingOffice(ScheduleAdjustAuditDTO dto) {
if (dto == null) {
throw new BusinessException(BasicManagementConstants.BAD_REQUEST, "审批参数不能为空");
}
if (jwglRoleHelper.isTeacher()) {
throw new BusinessException(BasicManagementConstants.FORBIDDEN, "教员无权审批调课申请");
}
if (jwglRoleHelper.isDepartmentPersonnel() && !jwglRoleHelper.isAdmin()) {
throw new BusinessException(BasicManagementConstants.FORBIDDEN, "机关人员请使用机关审批,不办理教研室审批");
}
if (!jwglRoleHelper.isAdmin() && !jwglRoleHelper.isResearchOffice()) {
throw new BusinessException(BasicManagementConstants.FORBIDDEN, "仅教研室可进行一审");
}
if (!"jys".equals(dto.getAuditRole())) {
throw new BusinessException(BasicManagementConstants.BAD_REQUEST, "审批角色不正确,应为jys");
}
if (dto.getSpzt() == null
|| (dto.getSpzt() != 1 && dto.getSpzt() != 2 && dto.getSpzt() != 3)) {
throw new BusinessException(BasicManagementConstants.BAD_REQUEST, "审批结果不正确,应为1(同意)、2(发回)或3(拒绝)");
}
SSDKSQ apply = ssdksqMapper.selectById(dto.getSsdksqbh());
if (apply == null) {
throw new BusinessException(BasicManagementConstants.NOT_FOUND, "调课申请不存在");
@@ -1253,17 +1182,6 @@ public class CourseRunningImportServiceImpl implements CourseRunningImportServic
if (apply.getSczt() != null && apply.getSczt() == 1) {
throw new BusinessException(BasicManagementConstants.BAD_REQUEST, "该调课申请已撤销,不允许审批");
}
if (jwglRoleHelper.isResearchOffice()) {
String officeId = jwglRoleHelper.requireResearchOfficeId();
String applyOffice = apply.getJysdh();
if (StringUtils.isEmpty(applyOffice) && StringUtils.isNotEmpty(apply.getSqjybh())) {
JYB teacher = jybMapper.selectById(apply.getSqjybh());
applyOffice = teacher == null ? null : teacher.getJysdh();
}
if (applyOffice == null || !officeId.equals(applyOffice.trim())) {
throw new BusinessException(BasicManagementConstants.FORBIDDEN, "只能审批本教研室的调课申请");
}
}
if (apply.getJyspzzt() != null && apply.getJyspzzt() != 0) {
throw new BusinessException(BasicManagementConstants.BAD_REQUEST, "该调课申请已审批,无需重复审批");
}
@@ -1273,275 +1191,36 @@ public class CourseRunningImportServiceImpl implements CourseRunningImportServic
apply.setJyspzzt(dto.getSpzt());
apply.setJyspzrbh(auditor);
apply.setJyspzsj(now);
apply.setJyscszt(1);
apply.setJyscsrbh(auditor);
apply.setJyscssj(now);
apply.setFhyj(dto.getFhyj());
if (dto.getSpzt() != null && dto.getSpzt() == 2) {
if (dto.getSpzt() == 2) {
apply.setFhzt(1);
apply.setFhsj(now);
}
ssdksqMapper.updateById(apply);
recordOperationLog(apply.getBh(), "教研室审批", "教研室审批调课申请:" + apply.getBh()
+ ",审批结果:" + dto.getSpzt() + ",审批意见:" + dto.getFhyj());
}
/**
* 教研室查收调课申请。
* <p>
* 教研室查收调课申请,标记查收状态和查收时间。
* </p>
*
* @param ssdksqbh 调课申请编号
* @param csrbh 查收人编号
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void receiveByTeachingOffice(String ssdksqbh, String csrbh) {
// 步骤1:校验参数
if (ssdksqbh == null || ssdksqbh.trim().isEmpty()) {
throw new BusinessException(BasicManagementConstants.BAD_REQUEST, "调课申请编号不能为空");
}
if (csrbh == null || csrbh.trim().isEmpty()) {
throw new BusinessException(BasicManagementConstants.BAD_REQUEST, "查收人编号不能为空");
}
// 步骤2:查询调课申请实体
SSDKSQ apply = ssdksqMapper.selectById(ssdksqbh);
if (apply == null) {
throw new BusinessException(BasicManagementConstants.NOT_FOUND, "调课申请不存在");
}
// 步骤3:校验是否已查收,避免重复查收
if (apply.getJyscszt() != null && apply.getJyscszt() == 1) {
throw new BusinessException(BasicManagementConstants.BAD_REQUEST, "该调课申请已查收,无需重复查收");
}
// 步骤4:更新查收状态和查收时间
apply.setJyscszt(1); // 教研室查收状态:已查收
apply.setJyscsrbh(csrbh); // 教研室查收人编号
apply.setJyscssj(LocalDateTime.now()); // 教研室查收时间
apply.setUpdateTime(LocalDateTime.now()); // 更新时间
ssdksqMapper.updateById(apply);
// 步骤5:记录查收操作日志
recordOperationLog(apply.getBh(), "教研室查收", "教研室查收调课申请:" + apply.getBh());
}
/**
* 教学系审批调课申请。
* <p>
* 教学系审批教研室已同意的调课申请,包含同意、发回、拒绝三种处理方式。
* 教学系同意后流转到机关审批,构成三级审批流程(教研室→教学系→机关)。
* </p>
*
* @param dto 教学系审批参数
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void auditByTeachingDepartment(ScheduleAdjustAuditDTO dto) {
// 步骤1:校验审批参数
if (dto == null) {
throw new BusinessException(BasicManagementConstants.BAD_REQUEST, "审批参数不能为空");
}
if (!"jxx".equals(dto.getAuditRole())) {
throw new BusinessException(BasicManagementConstants.BAD_REQUEST, "审批角色不正确,应为jxx");
}
if (dto.getSpzt() == null
|| (dto.getSpzt() != 1 && dto.getSpzt() != 2 && dto.getSpzt() != 3)) {
throw new BusinessException(BasicManagementConstants.BAD_REQUEST, "审批结果不正确,应为1(同意)、2(发回)或3(拒绝)");
}
// 步骤2:查询调课申请实体
SSDKSQ apply = ssdksqMapper.selectById(dto.getSsdksqbh());
if (apply == null) {
throw new BusinessException(BasicManagementConstants.NOT_FOUND, "调课申请不存在");
}
if (apply.getSczt() != null && apply.getSczt() == 1) {
throw new BusinessException(BasicManagementConstants.BAD_REQUEST, "该调课申请已撤销,不允许审批");
}
// 步骤3:校验教研室是否已同意,教学系审批应在教研室同意之后进行
if (apply.getJyspzzt() == null || apply.getJyspzzt() != 1) {
throw new BusinessException(BasicManagementConstants.BAD_REQUEST, "教研室未同意或未审批,无法进行教学系审批");
}
// 步骤4:校验教学系是否已审批,避免重复审批
if (apply.getJxxspzzt() != null && apply.getJxxspzzt() != 0) {
throw new BusinessException(BasicManagementConstants.BAD_REQUEST, "该调课申请教学系已审批,无需重复审批");
}
// 步骤5:更新调课申请主表的教学系审批状态
LocalDateTime now = LocalDateTime.now();
apply.setJxxspzzt(dto.getSpzt()); // 教学系审批状态
apply.setJxxspzrbh(dto.getSprbh()); // 教学系审批人编号
apply.setJxxspzsj(now); // 教学系审批时间
apply.setFhyj(dto.getFhyj()); // 发回意见
apply.setUpdateTime(now); // 更新时间
ssdksqMapper.updateById(apply);
// 步骤6:根据审批结果执行不同的后续处理
if (dto.getSpzt() == 3) {
// 拒绝:恢复课次原数据,标记申请最终结束
restoreLessonSchedule(apply);
} else if (dto.getSpzt() == 2) {
// 发回:发回教研室,课次保留调整后数据,由教研室重新处理
} else {
// 同意:流转到机关审批
}
// 步骤7:记录教学系审批操作日志
recordOperationLog(apply.getBh(), "教学系审批", "教学系审批调课申请:" + apply.getBh()
+ ",审批结果:" + dto.getSpzt() + ",审批意见:" + dto.getFhyj());
}
/**
* 机关审批调课申请。
* <p>
* 机关审批教研室已同意的调课申请,包含同意、发回、拒绝三种处理方式。
* 机关全部同意后调课申请最终生效,课次按调整后的内容执行。
* </p>
*
* @param dto 机关审批参数
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void auditByAuthority(ScheduleAdjustAuditDTO dto) {
// 步骤1:校验审批参数
if (dto == null) {
throw new BusinessException(BasicManagementConstants.BAD_REQUEST, "审批参数不能为空");
}
if (!"jg".equals(dto.getAuditRole())) {
throw new BusinessException(BasicManagementConstants.BAD_REQUEST, "审批角色不正确,应为jg");
}
if (dto.getSpzt() == null
|| (dto.getSpzt() != 1 && dto.getSpzt() != 2 && dto.getSpzt() != 3)) {
throw new BusinessException(BasicManagementConstants.BAD_REQUEST, "审批结果不正确");
}
if (jwglRoleHelper.isTeacher() || jwglRoleHelper.isResearchOffice()) {
throw new BusinessException(BasicManagementConstants.FORBIDDEN, "仅机关人员可进行终审");
}
if (!jwglRoleHelper.isAdmin() && !jwglRoleHelper.isDepartmentPersonnel()) {
throw new BusinessException(BasicManagementConstants.FORBIDDEN, "仅机关人员可进行终审");
}
SSDKSQ apply = ssdksqMapper.selectById(dto.getSsdksqbh());
if (apply == null) {
throw new BusinessException(BasicManagementConstants.NOT_FOUND, "调课申请不存在");
}
if (apply.getSczt() != null && apply.getSczt() == 1) {
throw new BusinessException(BasicManagementConstants.BAD_REQUEST, "该调课申请已撤销,不允许审批");
}
if (apply.getJyspzzt() == null || apply.getJyspzzt() != 1) {
throw new BusinessException(BasicManagementConstants.BAD_REQUEST, "教研室未同意,无法进行机关审批");
}
String jgbh = StringUtils.isNotEmpty(dto.getJgbh()) ? dto.getJgbh() : "JG";
String auditor = StringUtils.isNotEmpty(dto.getSprbh()) ? dto.getSprbh() : currentOperatorId();
SSDKSQSP audit = new SSDKSQSP();
audit.setBh(UuidUtil.getOriginalUUID());
audit.setSsdksqbh(dto.getSsdksqbh());
audit.setJgbh(jgbh);
audit.setSprbh(auditor);
audit.setSpsj(LocalDateTime.now());
audit.setSpzt(dto.getSpzt());
audit.setFhyj(dto.getFhyj());
audit.setNd(apply.getNd());
audit.setCreateTime(LocalDateTime.now());
audit.setUpdateTime(LocalDateTime.now());
ssdksqspMapper.insert(audit);
if (dto.getSpzt() == 1) {
applyApprovedSchedule(apply);
}
recordOperationLog(apply.getBh(), "机关审批", "机关审批调课申请:" + apply.getBh()
+ ",机关编号:" + jgbh
recordOperationLog(apply.getBh(), "教研室审批", "教研室审批调课申请:" + apply.getBh()
+ ",审批结果:" + dto.getSpzt() + ",审批意见:" + dto.getFhyj());
}
/**
* 机关查收调课申请。
* <p>
* 机关查收调课申请,标记查收状态和查收时间。
* </p>
*
* @param ssdksqbh 调课申请编号
* @param jgbh 机关编号
* @param csrbh 查收人编号
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void receiveByAuthority(String ssdksqbh, String jgbh, String csrbh) {
// 步骤1:校验参数
if (ssdksqbh == null || ssdksqbh.trim().isEmpty()) {
throw new BusinessException(BasicManagementConstants.BAD_REQUEST, "调课申请编号不能为空");
}
if (jgbh == null || jgbh.trim().isEmpty()) {
throw new BusinessException(BasicManagementConstants.BAD_REQUEST, "机关编号不能为空");
}
if (csrbh == null || csrbh.trim().isEmpty()) {
throw new BusinessException(BasicManagementConstants.BAD_REQUEST, "查收人编号不能为空");
}
// 步骤2:查询调课申请实体
SSDKSQ apply = ssdksqMapper.selectById(ssdksqbh);
if (apply == null) {
throw new BusinessException(BasicManagementConstants.NOT_FOUND, "调课申请不存在");
}
// 步骤3:检查当前机关是否已查收
LambdaQueryWrapper<SSDKSQSP> checkWrapper = new LambdaQueryWrapper<>();
checkWrapper.eq(SSDKSQSP::getSsdksqbh, ssdksqbh);
checkWrapper.eq(SSDKSQSP::getJgbh, jgbh);
checkWrapper.eq(SSDKSQSP::getCszt, 1);
if (ssdksqspMapper.selectCount(checkWrapper) > 0) {
throw new BusinessException(BasicManagementConstants.BAD_REQUEST, "当前机关已查收该调课申请,无需重复查收");
}
// 步骤4:构建并保存机关查收记录
SSDKSQSP receive = new SSDKSQSP();
receive.setBh(UuidUtil.getOriginalUUID());
receive.setSsdksqbh(ssdksqbh);
receive.setJgbh(jgbh);
receive.setCsrbh(csrbh);
receive.setCszt(1);
receive.setCssj(LocalDateTime.now());
receive.setNd(apply.getNd());
receive.setCreateTime(LocalDateTime.now());
receive.setUpdateTime(LocalDateTime.now());
ssdksqspMapper.insert(receive);
// 步骤5:记录查收操作日志
recordOperationLog(apply.getBh(), "机关查收", "机关查收调课申请:" + apply.getBh()
+ ",机关编号:" + jgbh);
}
/**
* 撤销调课申请。
* <p>
* 教员撤销自己提交的、未经过审批的调课申请。
* 软删除调课申请,标记删除状态为1。
* 事务保证主表软删除与课次原数据恢复的一致性。
* 教员撤销未经过审批的调课申请。列表已按登录教员过滤。
* </p>
*
* @param ssdksqbh 调课申请编号
* @param sqjybh 申请教员编号(用于权限校验)
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void cancelScheduleAdjust(String ssdksqbh, String sqjybh) {
if (jwglRoleHelper.isDepartmentPersonnel() || jwglRoleHelper.isResearchOffice()) {
throw new BusinessException(BasicManagementConstants.FORBIDDEN, "仅申请教员本人可撤销调课申请");
}
if (ssdksqbh == null || ssdksqbh.trim().isEmpty()) {
throw new BusinessException(BasicManagementConstants.BAD_REQUEST, "调课申请编号不能为空");
}
String teacherId = jwglRoleHelper.requireTeacherId();
if (sqjybh != null && !sqjybh.trim().isEmpty() && !teacherId.equals(sqjybh.trim())) {
throw new BusinessException(BasicManagementConstants.FORBIDDEN, "仅申请教员本人可撤销该调课申请");
}
sqjybh = teacherId;
public void cancelScheduleAdjust(String ssdksqbh) {
SSDKSQ apply = ssdksqMapper.selectById(ssdksqbh);
if (apply == null) {
throw new BusinessException(BasicManagementConstants.NOT_FOUND, "调课申请不存在");
@@ -1549,29 +1228,19 @@ public class CourseRunningImportServiceImpl implements CourseRunningImportServic
if (apply.getSczt() != null && apply.getSczt() == 1) {
throw new BusinessException(BasicManagementConstants.BAD_REQUEST, "该调课申请已撤销,无需重复撤销");
}
if (!sqjybh.equals(apply.getSqjybh())) {
throw new BusinessException(BasicManagementConstants.FORBIDDEN, "仅申请教员本人可撤销该调课申请");
if (apply.getJyspzzt() != null && apply.getJyspzzt() != 0) {
throw new BusinessException(BasicManagementConstants.BAD_REQUEST, "该调课申请已审批,不允许撤销");
}
if (apply.getJyspzzt() != null && apply.getJyspzzt() == 1) {
throw new BusinessException(BasicManagementConstants.BAD_REQUEST, "该调课申请教研室已同意,不允许撤销");
}
apply.setSczt(1);
apply.setJyscszt(0);
apply.setJyscsrbh(null);
apply.setJyscssj(null);
ssdksqMapper.updateById(apply);
recordOperationLog(apply.getBh(), "撤销", "撤销调课申请:" + apply.getBh());
}
/**
* 构建原日期节次描述。
* <p>
* 根据课次实体生成原日期节次的字符串描述,便于调课申请中保留原信息。
* </p>
*
* @param lesson 课次实体
* @return 原日期节次描述
*/
/**
* 机关终审同意后,将调整结果写回学员队任务表、课程表,以及可选的实施课次。
* 教研室同意后,将调整结果写回课次、学员队任务表和课程表。
*/
private void applyApprovedSchedule(SSDKSQ apply) {
if (apply == null || StringUtils.isEmpty(apply.getSskcbbh())) {
@@ -1642,28 +1311,6 @@ public class CourseRunningImportServiceImpl implements CourseRunningImportServic
return sb.toString();
}
/**
* 恢复课次原数据。
* <p>
* 当调课申请被拒绝或撤销时,恢复课次到申请前的原始数据。
* 实际业务中通常需要从历史快照恢复,此处简化为清空日期节次。
* </p>
*
* @param apply 调课申请实体
*/
private void restoreLessonSchedule(SSDKSQ apply) {
// 步骤1:查询课次实体
SSKCB lesson = sskcbMapper.selectById(apply.getSskcbbh());
if (lesson == null) {
return;
}
// 步骤2:清空课次因调课而设置的日期节次(恢复原状)
lesson.setRq(null);
lesson.setJc(null);
sskcbMapper.updateById(lesson);
}
// ==================== 教学保障管理 ====================
/**
@@ -2971,192 +2618,6 @@ public class CourseRunningImportServiceImpl implements CourseRunningImportServic
return value == null ? "" : String.valueOf(value);
}
// ============================================================
// 调课策略管理实现(时间段限制策略 + 免审批策略)
// ============================================================
/** 策略类型常量:时间段限制 */
private static final String STRATEGY_TIME_LIMIT = "TIME_LIMIT";
/** 策略类型常量:免审批 */
private static final String STRATEGY_AUTO_APPROVE = "AUTO_APPROVE";
/** 星期中文描述 */
private static final String[] WEEK_DAY_NAMES = {"周日", "周一", "周二", "周三", "周四", "周五", "周六"};
@Override
public List<ScheduleAdjustStrategyVO> listScheduleAdjustStrategies(String cllx) {
LambdaQueryWrapper<ScheduleAdjustStrategy> wrapper = new LambdaQueryWrapper<>();
if (cllx != null && !cllx.trim().isEmpty()) {
wrapper.eq(ScheduleAdjustStrategy::getCllx, cllx);
}
wrapper.orderByDesc(ScheduleAdjustStrategy::getGxsj);
List<ScheduleAdjustStrategy> list = scheduleAdjustStrategyMapper.selectList(wrapper);
List<ScheduleAdjustStrategyVO> result = new ArrayList<>();
if (list == null) {
return result;
}
for (ScheduleAdjustStrategy strategy : list) {
result.add(buildStrategyVO(strategy));
}
return result;
}
@Override
@Transactional(rollbackFor = Exception.class)
public String saveScheduleAdjustStrategy(ScheduleAdjustStrategyDTO dto) {
if (!STRATEGY_TIME_LIMIT.equals(dto.getCllx()) && !STRATEGY_AUTO_APPROVE.equals(dto.getCllx())) {
throw new BusinessException(BasicManagementConstants.BAD_REQUEST,
"策略类型不正确,应为 TIME_LIMIT 或 AUTO_APPROVE");
}
if (STRATEGY_TIME_LIMIT.equals(dto.getCllx())) {
if (dto.getJzxq() != null && (dto.getJzxq() < 0 || dto.getJzxq() > 6)) {
throw new BusinessException(BasicManagementConstants.BAD_REQUEST,
"截止星期取值范围为0-6(0=周日,6=周六)");
}
}
if (dto.getSxkssj() != null && dto.getSxjssj() != null
&& dto.getSxkssj().isAfter(dto.getSxjssj())) {
throw new BusinessException(BasicManagementConstants.BAD_REQUEST,
"生效开始时间不能晚于生效结束时间");
}
LocalDateTime now = LocalDateTime.now();
if (dto.getClbh() == null || dto.getClbh().trim().isEmpty()) {
ScheduleAdjustStrategy strategy = new ScheduleAdjustStrategy();
strategy.setClbh(UuidUtil.getOriginalUUID());
strategy.setClmc(dto.getClmc());
strategy.setCllx(dto.getCllx());
strategy.setSfqy(dto.getSfqy() == null ? 1 : dto.getSfqy());
strategy.setJzxq(dto.getJzxq());
strategy.setJzjc(dto.getJzjc());
strategy.setSxkssj(dto.getSxkssj());
strategy.setSxjssj(dto.getSxjssj());
strategy.setBz(dto.getBz());
strategy.setCjsj(now);
strategy.setGxsj(now);
scheduleAdjustStrategyMapper.insert(strategy);
return strategy.getClbh();
} else {
ScheduleAdjustStrategy existing = scheduleAdjustStrategyMapper.selectById(dto.getClbh());
if (existing == null) {
throw new BusinessException(BasicManagementConstants.NOT_FOUND, "调课策略不存在");
}
existing.setClmc(dto.getClmc());
existing.setCllx(dto.getCllx());
existing.setSfqy(dto.getSfqy() == null ? 1 : dto.getSfqy());
existing.setJzxq(dto.getJzxq());
existing.setJzjc(dto.getJzjc());
existing.setSxkssj(dto.getSxkssj());
existing.setSxjssj(dto.getSxjssj());
existing.setBz(dto.getBz());
existing.setGxsj(now);
scheduleAdjustStrategyMapper.updateById(existing);
return existing.getClbh();
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteScheduleAdjustStrategy(String clbh) {
if (clbh == null || clbh.trim().isEmpty()) {
throw new BusinessException(BasicManagementConstants.BAD_REQUEST, "策略编号不能为空");
}
ScheduleAdjustStrategy existing = scheduleAdjustStrategyMapper.selectById(clbh);
if (existing == null) {
throw new BusinessException(BasicManagementConstants.NOT_FOUND, "调课策略不存在");
}
scheduleAdjustStrategyMapper.deleteById(clbh);
}
/** 调课时间段策略校验:超过截止星期时不允许调整下周课程 */
private void validateScheduleAdjustTimeLimitStrategy(LocalDateTime newDate) {
if (newDate == null) {
return;
}
LambdaQueryWrapper<ScheduleAdjustStrategy> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(ScheduleAdjustStrategy::getCllx, STRATEGY_TIME_LIMIT);
wrapper.eq(ScheduleAdjustStrategy::getSfqy, 1);
List<ScheduleAdjustStrategy> strategies = scheduleAdjustStrategyMapper.selectList(wrapper);
if (strategies == null || strategies.isEmpty()) {
return;
}
LocalDateTime now = LocalDateTime.now();
int currentDayOfWeek = now.getDayOfWeek().getValue();
boolean isFutureWeek = newDate.toLocalDate().isAfter(now.toLocalDate().plusDays(7));
for (ScheduleAdjustStrategy strategy : strategies) {
if (strategy.getSxkssj() != null && now.isBefore(strategy.getSxkssj())) {
continue;
}
if (strategy.getSxjssj() != null && now.isAfter(strategy.getSxjssj())) {
continue;
}
Integer deadlineDay = strategy.getJzxq();
if (deadlineDay == null) {
continue;
}
int deadlineDayOfWeek = (deadlineDay == 0) ? 7 : deadlineDay;
if (isFutureWeek && currentDayOfWeek > deadlineDayOfWeek) {
String dayName = (deadlineDay >= 0 && deadlineDay <= 6) ? WEEK_DAY_NAMES[deadlineDay] : String.valueOf(deadlineDay);
throw new BusinessException(BasicManagementConstants.BAD_REQUEST,
"根据调课策略[" + strategy.getClmc() + "]," + dayName + "之后不允许调整下周课程");
}
}
}
/** 判断当前是否命中免审批策略 */
private boolean matchAutoApproveStrategy() {
LambdaQueryWrapper<ScheduleAdjustStrategy> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(ScheduleAdjustStrategy::getCllx, STRATEGY_AUTO_APPROVE);
wrapper.eq(ScheduleAdjustStrategy::getSfqy, 1);
List<ScheduleAdjustStrategy> strategies = scheduleAdjustStrategyMapper.selectList(wrapper);
if (strategies == null || strategies.isEmpty()) {
return false;
}
LocalDateTime now = LocalDateTime.now();
for (ScheduleAdjustStrategy strategy : strategies) {
boolean inRange = true;
if (strategy.getSxkssj() != null && now.isBefore(strategy.getSxkssj())) {
inRange = false;
}
if (strategy.getSxjssj() != null && now.isAfter(strategy.getSxjssj())) {
inRange = false;
}
if (inRange) {
return true;
}
}
return false;
}
/** 组装调课策略展示VO */
private ScheduleAdjustStrategyVO buildStrategyVO(ScheduleAdjustStrategy strategy) {
ScheduleAdjustStrategyVO vo = new ScheduleAdjustStrategyVO();
vo.setClbh(strategy.getClbh());
vo.setClmc(strategy.getClmc());
vo.setCllx(strategy.getCllx());
vo.setCllxDesc(STRATEGY_TIME_LIMIT.equals(strategy.getCllx()) ? "时间段限制" :
(STRATEGY_AUTO_APPROVE.equals(strategy.getCllx()) ? "免审批" : strategy.getCllx()));
vo.setSfqy(strategy.getSfqy());
vo.setSfqyDesc(strategy.getSfqy() != null && strategy.getSfqy() == 1 ? "启用" : "停用");
vo.setJzxq(strategy.getJzxq());
if (strategy.getJzxq() != null && strategy.getJzxq() >= 0 && strategy.getJzxq() <= 6) {
vo.setJzxqDesc(WEEK_DAY_NAMES[strategy.getJzxq()]);
}
vo.setJzjc(strategy.getJzjc());
vo.setSxkssj(strategy.getSxkssj());
vo.setSxjssj(strategy.getSxjssj());
vo.setBz(strategy.getBz());
vo.setCjsj(strategy.getCjsj());
vo.setGxsj(strategy.getGxsj());
return vo;
}
/**
* 根据教员编号自动解析其归属的实施_机关编号。
* <p>
@@ -9,6 +9,7 @@ import com.roomroot.jwgl.service.FacultyService;
import com.roomroot.jwgl.unit.BusinessException;
import com.roomroot.jwgl.unit.PageQuery;
import com.roomroot.jwgl.unit.PageResult;
import com.roomroot.jwgl.utils.ExcelExportUtil;
import com.roomroot.jwgl.utils.ExcelParseUtil;
import com.roomroot.jwgl.utils.UuidUtil;
import com.roomroot.jwgl.vo.faculty.TeacherListVO;
@@ -160,6 +161,52 @@ public class FacultyServiceImpl implements FacultyService {
return jybMapper.selectById(jybh);
}
@Override
@Transactional(rollbackFor = Exception.class)
public int importJYBFromExcel(MultipartFile file) throws Exception {
if (file == null || file.isEmpty()) {
throw new BusinessException("导入文件不能为空");
}
List<JYB> list = ExcelParseUtil.parseJYBExcel(
file.getInputStream(), file.getOriginalFilename());
if (list.isEmpty()) {
throw new BusinessException("Excel中无有效数据");
}
for (JYB entity : list) {
// 编号为空自动生成
if (entity.getJybh() == null || entity.getJybh().isEmpty()) {
entity.setJybh(UuidUtil.getUUID());
}
// 离职状态默认 0
if (entity.getLzzt() == null) {
entity.setLzzt(0);
}
jybMapper.insert(entity);
}
return list.size();
}
@Override
public void exportJYBExcel(jakarta.servlet.http.HttpServletResponse response) throws Exception {
com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<JYB> w =
new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<>();
w.eq(JYB::getLzzt, 0).orderByAsc(JYB::getXh);
List<JYB> list = jybMapper.selectList(w);
String[] headers = {"教员编号", "教员姓名", "教研室代号", "职称", "专业技术职务等级", "教员类别",
"性别", "手机号", "身份证号", "备注", "序号", "虚实类型"};
byte[] bytes = ExcelExportUtil.export("教员", headers, list,
JYB::getJybh, JYB::getJyxm, JYB::getJysdh, JYB::getZc,
JYB::getZyjszwdj, JYB::getJylb, JYB::getXb, JYB::getSjh,
JYB::getSfzh, JYB::getBz, JYB::getXh, JYB::getXslx);
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader("Content-Disposition",
"attachment; filename=" + java.net.URLEncoder.encode(
"教员列表.xlsx", java.nio.charset.StandardCharsets.UTF_8));
response.getOutputStream().write(bytes);
response.getOutputStream().flush();
}
@Override
public PageResult<TeacherListVO> pageJYBDetail(PageQuery query, JYB cond) {
Page<TeacherListVO> page = new Page<>(query.getPageNum(), query.getPageSize());
@@ -73,4 +73,45 @@ public class TrainingProgramServiceImpl implements TrainingProgramService {
return new PageResult<>(result.getRecords(), result.getTotal(),
query.getPageNum(), query.getPageSize());
}
@Override
@Transactional(rollbackFor = Exception.class)
public int importZYBFromExcel(org.springframework.web.multipart.MultipartFile file) throws Exception {
if (file == null || file.isEmpty()) {
throw new RuntimeException("导入文件不能为空");
}
java.util.List<ZYB> list = com.roomroot.jwgl.utils.ExcelParseUtil.parseZYBExcel(
file.getInputStream(), file.getOriginalFilename());
if (list.isEmpty()) {
throw new RuntimeException("Excel中无有效数据");
}
for (ZYB entity : list) {
if (entity.getZydh() == null || entity.getZydh().isEmpty()) {
entity.setZydh(com.roomroot.jwgl.utils.UuidUtil.getUUID());
}
if (entity.getTy() == null) {
entity.setTy(false);
}
zybMapper.insert(entity);
}
return list.size();
}
@Override
public void exportZYBExcel(jakarta.servlet.http.HttpServletResponse response) throws Exception {
java.util.List<ZYB> list = zybMapper.selectList(
new LambdaQueryWrapper<ZYB>().orderByAsc(ZYB::getZydh));
String[] headers = {"专业代号", "专业名称", "专业代码", "专业版本", "培训类型", "培训层次",
"学年制", "学期数", "专业方向", "专业备注", "学员类别", "简称", "培训类型2"};
byte[] bytes = com.roomroot.jwgl.utils.ExcelExportUtil.export("培养方案", headers, list,
ZYB::getZydh, ZYB::getZymc, ZYB::getZydm, ZYB::getZybb, ZYB::getPxlx,
ZYB::getPxcc, ZYB::getXnz, ZYB::getXqs, ZYB::getZyfx, ZYB::getZybz,
ZYB::getXylb, ZYB::getJc, ZYB::getPxlx2);
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader("Content-Disposition",
"attachment; filename=" + java.net.URLEncoder.encode(
"培养方案.xlsx", java.nio.charset.StandardCharsets.UTF_8));
response.getOutputStream().write(bytes);
response.getOutputStream().flush();
}
}
@@ -71,4 +71,43 @@ public class ZYJXJHBServiceImpl implements ZYJXJHBService {
.eq(ZYJXJHB::getTy, ty);
return zyjxjhbMapper.selectList(wrapper);
}
@Override
@org.springframework.transaction.annotation.Transactional(rollbackFor = Exception.class)
public int importZYJXJHBFromExcel(org.springframework.web.multipart.MultipartFile file) throws Exception {
if (file == null || file.isEmpty()) {
throw new RuntimeException("导入文件不能为空");
}
List<ZYJXJHB> list = com.roomroot.jwgl.utils.ExcelParseUtil.parseZYJXJHBExcel(
file.getInputStream(), file.getOriginalFilename());
if (list.isEmpty()) {
throw new RuntimeException("Excel中无有效数据");
}
for (ZYJXJHB entity : list) {
if (entity.getTy() == null) {
entity.setTy(0);
}
zyjxjhbMapper.insert(entity);
}
return list.size();
}
@Override
public void exportZYJXJHBExcel(jakarta.servlet.http.HttpServletResponse response) throws Exception {
List<ZYJXJHB> list = zyjxjhbMapper.selectList(
new LambdaQueryWrapper<ZYJXJHB>().orderByAsc(ZYJXJHB::getZydh));
String[] headers = {"专业代号", "课编号", "学期第次", "课类型", "学时", "学分", "周课时",
"课程定位", "模块", "成绩分制", "理论学时", "实践学时", "考试课时", "教研室代号", "简称"};
byte[] bytes = com.roomroot.jwgl.utils.ExcelExportUtil.export("专业教学计划", headers, list,
ZYJXJHB::getZydh, ZYJXJHB::getKbh, ZYJXJHB::getXqdc, ZYJXJHB::getKlx,
ZYJXJHB::getXs, ZYJXJHB::getXf, ZYJXJHB::getZks, ZYJXJHB::getKcdw,
ZYJXJHB::getMk, ZYJXJHB::getCjfz, ZYJXJHB::getLlxs, ZYJXJHB::getSjxs,
ZYJXJHB::getKsks, ZYJXJHB::getJysdh, ZYJXJHB::getJc);
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader("Content-Disposition",
"attachment; filename=" + java.net.URLEncoder.encode(
"专业教学计划.xlsx", java.nio.charset.StandardCharsets.UTF_8));
response.getOutputStream().write(bytes);
response.getOutputStream().flush();
}
}