package com.xjrsoft.module.courseTable.service.impl; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.date.DateField; import cn.hutool.core.date.DateTime; import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.github.yulichang.wrapper.MPJLambdaWrapper; import com.google.gson.JsonArray; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.xjrsoft.common.enums.CourseAdjustTypeEnum; import com.xjrsoft.common.enums.TimeNumberEnum; import com.xjrsoft.common.enums.TimePeriodEnum; import com.xjrsoft.common.enums.WeekEnum; import com.xjrsoft.common.exception.MyException; import com.xjrsoft.config.TimetableConfig; import com.xjrsoft.module.base.entity.BaseClass; import com.xjrsoft.module.base.entity.BaseSemester; import com.xjrsoft.module.base.mapper.BaseSemesterMapper; import com.xjrsoft.module.base.service.IBaseClassService; import com.xjrsoft.module.base.service.IBaseSemesterService; import com.xjrsoft.module.courseTable.dto.ClassListDto; import com.xjrsoft.module.courseTable.dto.CourseTableParse; import com.xjrsoft.module.courseTable.entity.ClassTime; import com.xjrsoft.module.courseTable.entity.CourseTable; import com.xjrsoft.module.courseTable.mapper.ClassTimeMapper; import com.xjrsoft.module.courseTable.mapper.CourseTableMapper; import com.xjrsoft.module.courseTable.service.ICourseTableService; import com.xjrsoft.module.courseTable.vo.ClassListVo; import com.xjrsoft.module.schedule.dto.CourseTableAdjustDto; import com.xjrsoft.module.schedule.dto.CourseTableDto; import com.xjrsoft.module.schedule.entity.WfCourseAdjust; import com.xjrsoft.module.schedule.mapper.CourseTableBakMapper; import com.xjrsoft.module.schedule.util.ScheduleUtil; import com.xjrsoft.module.schedule.vo.CourseDetailVo; import com.xjrsoft.module.schedule.vo.CourseListVo; import com.xjrsoft.module.schedule.vo.CourseTableVo; import com.xjrsoft.module.teacher.entity.BaseTeacher; import com.xjrsoft.module.teacher.entity.XjrUser; import com.xjrsoft.module.teacher.service.ITeacherbaseManagerService; import lombok.AllArgsConstructor; import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.apache.poi.xwpf.usermodel.XWPFParagraph; import org.apache.poi.xwpf.usermodel.XWPFTable; import org.apache.poi.xwpf.usermodel.XWPFTableCell; import org.apache.poi.xwpf.usermodel.XWPFTableRow; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.io.IOException; import java.io.InputStream; import java.time.DayOfWeek; import java.time.Duration; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; /** *

* 课表 服务实现类 *

* * @author baomidou * @since 2023-09-02 02:19:56 */ @Service @AllArgsConstructor public class CourseTableServiceImpl extends ServiceImpl implements ICourseTableService { private final CourseTableMapper courseTableMapper; private final IBaseClassService baseClassService; private final ITeacherbaseManagerService teacherbaseManagerService; private final IBaseSemesterService baseSemesterService; private final TimetableConfig timetableConfig; private final ClassTimeMapper classTimeMapper; private final BaseSemesterMapper baseSemesterMapper; private final CourseTableBakMapper courseTableBakMapper; @Override @Transactional(rollbackFor = Exception.class) public Boolean wordImport(InputStream inputStream) throws IOException { List parses = courseTableWordParses(inputStream); String semester = null; if (parses.size() > 0) { semester = parses.get(0).getSemester(); } BaseSemester baseSemester = baseSemesterService.getOne(Wrappers.query().lambda().eq(BaseSemester::getName, semester)); if (baseSemester == null) { throw new MyException(String.format("学期【%s】不存在", semester)); } // 获取班级信息 List baseClassList = baseClassService.list(); Map baseClassMap = baseClassList.stream().collect(Collectors.toMap(BaseClass::getName, a -> a, (k1, k2) -> k1)); // 获取教师信息 MPJLambdaWrapper queryWrapper = new MPJLambdaWrapper<>(); queryWrapper .disableSubLogicDel() .innerJoin(BaseTeacher.class, BaseTeacher::getUserId, XjrUser::getId) .selectAll(XjrUser.class); List xjrUserList = teacherbaseManagerService.list(queryWrapper); Map xjrUsersMap = xjrUserList.stream().collect(Collectors.toMap(XjrUser::getName, a -> a, (k1, k2) -> k1)); // 清空所有数据 courseTableMapper.delete(Wrappers.query().lambda().eq(CourseTable::getBaseSemesterId, baseSemester.getId())); List params = new ArrayList<>(); for (CourseTableParse item : parses) { CourseTable courseTable = BeanUtil.toBean(item, CourseTable.class); courseTable.setBaseSemesterId(baseSemester.getId()); BaseClass baseClass = baseClassMap.get(item.getClassName()); if (baseClass != null) { courseTable.setClassId(baseClass.getId()); } XjrUser xjrUser = xjrUsersMap.get(item.getTeacherName()); if (xjrUser != null) { courseTable.setTeacherId(xjrUser.getId()); } if (item.getWeeksCn() != null) { courseTable.setWeeks(WeekEnum.getCode(item.getWeeksCn())); } params.add(courseTable); } return this.saveBatch(params); } @Override public List classList(ClassListDto dto) { LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(CourseTable::getClassId, dto.getClassId()) .eq(ObjectUtil.isNotEmpty(dto.getWeeks()), CourseTable::getWeeks,dto.getWeeks()); List courseTables = courseTableMapper.selectList(queryWrapper); List classListVos = BeanUtil.copyToList(courseTables, ClassListVo.class); Boolean isCurrentSummer = isCurrentSummer(); Map classTimeMap = getClassTimeMap(); // 获取节次时间 for (int i = 0; i < classListVos.size(); i++) { ClassListVo c = classListVos.get(i); String key = String.format("%d_%d", c.getTimePeriod(), c.getTimeNumber()); ClassTime ct = classTimeMap.get(key); if (ct != null) { if (isCurrentSummer) { c.setStartTime(ct.getSummerStartTime()); c.setEndTime(ct.getSummerEndTime()); } else { c.setStartTime(ct.getWinterStartTime()); c.setEndTime(ct.getWinterEndTime()); } } } return classListVos; } @Override public CourseTableVo getList(CourseTableDto dto) { List classTimes = classTimeMapper.selectList( new QueryWrapper().lambda().orderByAsc(ClassTime::getSummerStartTime) ); CourseTableVo tableVo = new CourseTableVo(); tableVo.setClassTimeList(classTimes); if(dto.getSemesterId() != null){ BaseSemester baseSemester = baseSemesterMapper.selectById(dto.getSemesterId()); tableVo.setSemesterName(baseSemester.getName()); LocalDateTime now = LocalDateTime.now(); //计算本周是第几周 LocalDateTime startDateTime = LocalDateTime.ofInstant(baseSemester.getStartDate().toInstant(), ZoneId.systemDefault()); LocalDateTime endDateTime = LocalDateTime.ofInstant(baseSemester.getEndDate().toInstant(), ZoneId.systemDefault()); Duration between = Duration.between(startDateTime, endDateTime); long days = between.toDays(); int weeks = (int) Math.ceil((double) days / 7); if(dto.getWeek() == null){ for (int i = 0; i < weeks; i ++){ LocalDateTime startDate = startDateTime.plusDays(i * 7).withHour(0).withMinute(0).withSecond(0).withNano(0); LocalDateTime endDate = startDateTime.plusDays((i + 1) * 7).withHour(23).withMinute(59).withSecond(59).withNano(9999); if(now.isAfter(startDate) && now.isBefore(endDate)){ tableVo.setWeek("第" + (i + 1) + "周"); } } }else{ LocalDateTime startDate = startDateTime.plusDays((dto.getWeek() - 1) * 7).withHour(0).withMinute(0).withSecond(0).withNano(0); LocalDateTime endDate = startDateTime.plusDays(dto.getWeek() * 7).withHour(23).withMinute(59).withSecond(59).withNano(9999); dto.setStartDate(startDate); dto.setEndDate(endDate); tableVo.setWeek("第" + dto.getWeek() + "周"); } } if(!StrUtil.isEmpty(dto.getTeacherName())){ List userList = teacherbaseManagerService.list( new QueryWrapper().lambda() .like(!StrUtil.isEmpty(dto.getTeacherName()), XjrUser::getName, dto.getTeacherName()) .like(!StrUtil.isEmpty(dto.getJobNumber()), XjrUser::getCode, dto.getJobNumber()) ); if(userList != null && !userList.isEmpty()){ XjrUser xjrUser = userList.get(0); dto.setTeacherId(xjrUser.getId()); tableVo.setTeacherName(xjrUser.getName()); } } List list = courseTableMapper.getList(dto); tableVo.setCourseList(list); tableVo.setClassHour(list.size()); if(dto.getClassId() != null){ BaseClass baseClass = baseClassService.getById(dto.getClassId()); tableVo.setClassName(baseClass.getName()); } return tableVo; } /** * 调课顶课查询 */ @Override public List getAdjustList(String teacherId, String adjustDate) { CourseTableAdjustDto dto = new CourseTableAdjustDto(); if(adjustDate != null && !"".equals(adjustDate)){ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); LocalDate localDateTime = LocalDate.parse(adjustDate, formatter); DayOfWeek dayOfWeek = localDateTime.getDayOfWeek(); dto.setWeek(dayOfWeek.getValue()); } dto.setTeacherId(Long.parseLong(teacherId)); return courseTableMapper.getAdjustList(dto); } @Override public String getPreCheck(String preCheckType, String courseId, String swapCourseId, String swapDate, String subTeacherId) { if(preCheckType != null && !"".equals(preCheckType)){ if(CourseAdjustTypeEnum.courseExchange.getCode().equals(preCheckType)){ CourseTable courseTable = courseTableMapper.selectById(courseId); CourseTable swapCourseTable = courseTableMapper.selectById(swapCourseId); try { DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); LocalDate localDateTime = LocalDate.parse(swapDate, formatter); JsonObject preCheck = getExtendPreCheck(localDateTime, courseTable, swapCourseTable); if(!preCheck.get("data").getAsBoolean() && !preCheck.get("msg").isJsonNull()){ return preCheck.get("msg").getAsString(); } } catch (Exception e) { throw new RuntimeException(e); } }else if(CourseAdjustTypeEnum.courseSubstitute.getCode().equals(preCheckType)){ CourseTable courseTable = courseTableMapper.selectById(courseId); try { JsonObject jsonObject = substitutePreTestin(subTeacherId, courseTable); if(!jsonObject.get("data").getAsBoolean() && !jsonObject.get("msg").isJsonNull()){ return jsonObject.get("msg").getAsString(); } } catch (Exception e) { throw new RuntimeException(e); } } } return null; } @Override public Boolean adjustCourse(WfCourseAdjust courseAdjust) throws Exception { if(CourseAdjustTypeEnum.courseExchange.getCode().equals(courseAdjust.getAdjustType())){ //调课,将双方课程的日期(schedule_date)、时段(time_period)、节次(time_number)、周(week)、星期几(1-7)(weeks)、星期中文(weeks_cn)对调 CourseTable courseTable = courseTableMapper.selectById(courseAdjust.getCourseId()); CourseTable swapCourseTable = courseTableMapper.selectById(courseAdjust.getExchangeCourseId()); CourseTable courseTableBak = BeanUtil.toBean(courseTable, CourseTable.class); CourseTable swapCourseTableBak = BeanUtil.toBean(swapCourseTable, CourseTable.class); courseTable.setScheduleDate(swapCourseTableBak.getScheduleDate()); courseTable.setTimePeriod(swapCourseTableBak.getTimePeriod()); courseTable.setTimeNumber(swapCourseTableBak.getTimeNumber()); courseTable.setWeek(swapCourseTableBak.getWeek()); courseTable.setWeeks(swapCourseTableBak.getWeeks()); courseTable.setWeeksCn(swapCourseTableBak.getWeeksCn()); courseTableMapper.updateById(courseTable); swapCourseTable.setScheduleDate(courseTableBak.getScheduleDate()); swapCourseTable.setTimePeriod(courseTableBak.getTimePeriod()); swapCourseTable.setTimeNumber(courseTableBak.getTimeNumber()); swapCourseTable.setWeek(courseTableBak.getWeek()); swapCourseTable.setWeeks(courseTableBak.getWeeks()); swapCourseTable.setWeeksCn(courseTableBak.getWeeksCn()); courseTableMapper.updateById(swapCourseTable); //提交调课接口 sendExchange(courseTableBak, swapCourseTableBak, courseAdjust); }else if(CourseAdjustTypeEnum.courseSubstitute.getCode().equals(courseAdjust.getAdjustType())){ CourseTable courseTable = courseTableMapper.selectById(courseAdjust.getCourseId()); courseTable.setTeacherId(courseAdjust.getExchangeTeacherId()); courseTableMapper.updateById(courseTable); //提交顶课接口 sendSubstitute(courseTable, courseAdjust); } return Boolean.TRUE; } /** * 提交顶课接口 * @param courseTable * @param courseAdjust * @throws Exception */ void sendSubstitute(CourseTable courseTable, WfCourseAdjust courseAdjust) throws Exception { String url = ScheduleUtil.apiUrl + "RescheduleApply/Extend/Substitute/Submit"; JsonObject jsonObject = new JsonObject(); jsonObject.addProperty("timetableId", courseTable.getJianyueId()); jsonObject.addProperty("isCycles", Boolean.FALSE); jsonObject.addProperty("reason", courseAdjust.getReason()); jsonObject.addProperty("teacherId", courseAdjust.getUserId()); JsonArray extendIds = new JsonArray(); extendIds.add(courseTable.getTeacherId()); jsonObject.add("extendIds", extendIds); //获取时间戳 long timestamp = System.currentTimeMillis(); //生成签名 String sign = ScheduleUtil.createSign(timestamp); String result = ScheduleUtil.doPost(url, jsonObject.toString(), sign, timestamp); System.out.println(result); } /** * 提交调课 * @param courseTable * @param swapCourseTable * @throws Exception */ void sendExchange(CourseTable courseTable, CourseTable swapCourseTable, WfCourseAdjust courseAdjust) throws Exception { String url = ScheduleUtil.apiUrl + "RescheduleApply/Extend/Submit"; JsonObject jsonObject = new JsonObject(); jsonObject.addProperty("timetableId", courseTable.getJianyueId()); jsonObject.addProperty("isCycles", Boolean.FALSE); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); jsonObject.addProperty("date", swapCourseTable.getScheduleDate().format(formatter)); jsonObject.addProperty("numberOfDay", swapCourseTable.getTimeNumber()); jsonObject.addProperty("rescheduleId", swapCourseTable.getJianyueId()); jsonObject.addProperty("reason", courseAdjust.getReason()); jsonObject.addProperty("teacherId", courseAdjust.getUserId()); //获取时间戳 long timestamp = System.currentTimeMillis(); //生成签名 String sign = ScheduleUtil.createSign(timestamp); String result = ScheduleUtil.doPost(url, jsonObject.toString(), sign, timestamp); } /** * 顶课预检查 * @param courseTable * @return 检查结果 */ JsonObject substitutePreTestin(String subTeacherId, CourseTable courseTable) throws Exception { JsonParser jsonParser = new JsonParser(); String url = ScheduleUtil.apiUrl + "RescheduleApply/Extend/Substitute/PreTesting"; JsonObject jsonObject = new JsonObject(); jsonObject.addProperty("timetableId", courseTable.getJianyueId()); jsonObject.addProperty("isCycles", Boolean.FALSE); JsonArray extendIds = new JsonArray(); extendIds.add(subTeacherId); jsonObject.add("extendIds", extendIds); //获取时间戳 long timestamp = System.currentTimeMillis(); //生成签名 String sign = ScheduleUtil.createSign(timestamp); String result = ScheduleUtil.doPost(url, jsonObject.toString(), sign, timestamp); if(StrUtil.isEmpty(result)){ return null; } return jsonParser.parse(result).getAsJsonObject(); } /** * 调课预检查 * @param courseTable 需要调整的课程 * @param swapCourseTable 对调的课程 * @return 检查结果 */ JsonObject getExtendPreCheck(LocalDate swapDate, CourseTable courseTable, CourseTable swapCourseTable) throws Exception { JsonParser jsonParser = new JsonParser(); String url = ScheduleUtil.apiUrl + "RescheduleApply/Extend/PreTesting"; JsonObject jsonObject = new JsonObject(); jsonObject.addProperty("timetableId", courseTable.getJianyueId()); jsonObject.addProperty("isCycles", Boolean.FALSE); // jsonObject.addProperty("startDate", "2024-01-01"); // jsonObject.addProperty("endDate", "2024-01-31"); // jsonObject.addProperty("dayOfweek", 5); jsonObject.addProperty("numberOfday", swapCourseTable.getTimeNumber()); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); jsonObject.addProperty("date", swapDate.format(formatter)); jsonObject.addProperty("reschduleId", courseTable.getJianyueId()); //获取时间戳 long timestamp = System.currentTimeMillis(); //生成签名 String sign = ScheduleUtil.createSign(timestamp); String result = ScheduleUtil.doPost(url, jsonObject.toString(), sign, timestamp); if(StrUtil.isEmpty(result)){ return null; } return jsonParser.parse(result).getAsJsonObject(); } /** * 获取节次 * * @return */ private Map getClassTimeMap() { List classTimes = classTimeMapper.selectList(null); Map result = new HashMap<>(); for (ClassTime item : classTimes) { String key = String.format("%d_%d", item.getTimePeriod(), item.getNumber()); result.put(key, item); } return result; } /** * 当前时间是否在夏季 * * @return */ private Boolean isCurrentSummer() { DateTime now = DateUtil.date(); DateTime summerStart = DateUtil.parse(String.format("%d-%s", now.year(), timetableConfig.getSummerStart())); DateTime summerEnd = DateUtil.parse(String.format("%d-%s", now.year(), timetableConfig.getSummerEnd())); DateTime winterStart = DateUtil.parse(String.format("%d-%s", now.year(), timetableConfig.getWinterStart())); DateTime winterEnd = DateUtil.parse(String.format("%d-%s", now.year(), timetableConfig.getWinterEnd())); // 如果开始时间大于结束时间,开始时间增加1年 if (DateUtil.compare(summerStart, summerEnd) > 0) { summerEnd = DateUtil.offset(summerEnd, DateField.DAY_OF_YEAR, 1); } if (DateUtil.compare(winterStart, winterEnd) > 0) { winterEnd = DateUtil.offset(winterEnd, DateField.DAY_OF_YEAR, 1); } if (DateUtil.compare(summerStart, now) > 0 && DateUtil.compare(summerEnd, now) < 0) { return true; } return false; } /** * 解析word课表 * * @param inputStream * @return * @throws IOException */ private List courseTableWordParses(InputStream inputStream) throws IOException { XWPFDocument doc = new XWPFDocument(inputStream); List paras = doc.getParagraphs(); String semester = null; List cNames = new ArrayList<>(); //获取标题 for (int i = 0; i < paras.size(); i++) { String txt = paras.get(i).getText(); if (i == 0) { semester = txt; continue; } txt = txt.replaceAll("总课程表", "").replace("\n", "").trim(); if (!txt.equals("") && !txt.equals(semester)) { cNames.add(txt); } } List result = new ArrayList<>(); //获取文档中所有的表格 List tables = doc.getTables(); int tNum = 0; for (XWPFTable table : tables) { int rNum = 0; String timePeriod = null; List weeks = new ArrayList<>(); List rows = table.getRows(); for (XWPFTableRow row : rows) { //获取行对应的单元格 List cells = row.getTableCells(); String timeNumber = null; for (int i = 0; i < cells.size(); i++) { String cellText = cells.get(i).getText(); if (cellText.equals("") || rNum < 1) continue; if (rNum == 1) { weeks.add(cellText); continue; } if (i == 0) { timePeriod = cellText; continue; } if (i == 1) { timeNumber = cellText; continue; } List cParagraph = cells.get(i).getParagraphs(); CourseTableParse item = new CourseTableParse(); item.setSemester(semester); item.setTimePeriod(TimePeriodEnum.getCode(timePeriod)); item.setTimeNumber(TimeNumberEnum.getCode(timeNumber)); String week = weeks.get(Math.max(i - 2, 0)); item.setWeeksCn(week); item.setClassName(cNames.get(tNum)); for (int j = 0; j < cParagraph.size(); j++) { cellText = cParagraph.get(j).getText().trim(); switch (j) { case 0: item.setCourseName(cellText); break; case 1: item.setTeacherName(cellText); break; case 2: item.setSiteName(cellText); break; } } result.add(item); } rNum++; } tNum++; } inputStream.close(); return result; } }