package com.xjrsoft.module.schedule.controller; import cn.dev33.satoken.annotation.SaCheckPermission; import cn.dev33.satoken.stp.StpUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import com.alibaba.excel.support.ExcelTypeEnum; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.google.gson.JsonArray; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.xjrsoft.common.annotation.XjrLog; import com.xjrsoft.common.enums.DeleteMark; import com.xjrsoft.common.enums.EnabledMark; import com.xjrsoft.common.model.result.RT; import com.xjrsoft.module.base.entity.BaseSemester; import com.xjrsoft.module.base.service.IBaseSemesterService; import com.xjrsoft.module.courseTable.entity.ClassTime; import com.xjrsoft.module.courseTable.entity.CourseTable; import com.xjrsoft.module.courseTable.service.IClassTimeService; import com.xjrsoft.module.courseTable.service.ICourseTableService; import com.xjrsoft.module.schedule.dto.*; import com.xjrsoft.module.schedule.entity.CourseReceiveMsg; import com.xjrsoft.module.schedule.service.ICourseReceiveMsgService; import com.xjrsoft.module.schedule.service.IWfCourseAdjustService; import com.xjrsoft.module.schedule.util.ScheduleUtil; import com.xjrsoft.module.schedule.vo.ClassOptionVo; import com.xjrsoft.module.schedule.vo.CourseListVo; import com.xjrsoft.module.schedule.vo.CourseNamesVo; import com.xjrsoft.module.schedule.vo.CourseTableVo; import com.xjrsoft.module.schedule.vo.CurrentWeekVo; import com.xjrsoft.module.schedule.vo.ScheduleWeekVo; import com.xjrsoft.module.student.entity.BaseStudentSchoolRoll; import com.xjrsoft.module.student.service.IBaseStudentSchoolRollService; import com.xjrsoft.module.teacher.entity.BaseTeacher; import com.xjrsoft.module.teacher.entity.XjrUser; import com.xjrsoft.module.teacher.service.IBaseTeacherService; import com.xjrsoft.module.teacher.service.ITeacherbaseManagerService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.AllArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.time.*; import java.time.format.DateTimeFormatter; import java.time.temporal.TemporalAdjusters; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.stream.Collectors; /** * @title: 课表 * @Author dzx * @Date: 2023-12-27 * @Version 1.0 */ @RestController @RequestMapping("/schedule" + "/schedule") @Api(value = "/schedule" + "/schedule", tags = "课表代码") @AllArgsConstructor public class ScheduleController { private final ICourseReceiveMsgService courseReceiveMsgService; // private final IJianyueDataService jianyueDataService; private final ICourseTableService courseTableService; private final IBaseStudentSchoolRollService baseStudentSchoolRollService; private final IBaseTeacherService baseTeacherService; private final ITeacherbaseManagerService teacherService; private final IBaseSemesterService semesterService; private final IWfCourseAdjustService courseAdjustService; private final IClassTimeService classTimeService; @GetMapping(value = "/receive-msg") @ApiOperation(value = "接收消息") // @SaCheckPermission("schedule:receivemsg") @XjrLog(value = "接收消息", saveResponseData = true) public RT receiveMsg(@RequestParam String schoolId, @RequestParam String eduYearSerialNo, @RequestParam String startDate, @RequestParam String endDate) throws Exception { Date date = new Date(); CourseReceiveMsg courseReceiveMsg = new CourseReceiveMsg(); courseReceiveMsg.setCreateDate(date); courseReceiveMsg.setSchoolId(schoolId); courseReceiveMsg.setEduYearSerialNo(eduYearSerialNo); courseReceiveMsg.setStartDate(startDate); courseReceiveMsg.setEndDate(endDate); courseReceiveMsg.setDeleteMark(DeleteMark.NODELETE.getCode()); courseReceiveMsg.setEnabledMark(EnabledMark.ENABLED.getCode()); courseReceiveMsgService.save(courseReceiveMsg); courseReceiveMsgService.noticeOverseer(eduYearSerialNo, date); return RT.ok(courseReceiveMsg); } @GetMapping(value = "/course-table") @ApiOperation(value = "课表接口(PC端)") @SaCheckPermission("schedule:coursetable") @XjrLog(value = "课表接口(PC端)", saveRequestData = false) public RT courseInfo(CourseTableDto dto) { if (dto.getSemesterId() == null) { BaseSemester semester = semesterService.getCurrentSemester(); if (semester != null) { dto.setSemesterId(semester.getId()); } } CourseTableVo list = courseTableService.getList(dto); return RT.ok(list); } @GetMapping(value = "/course-table-day") @ApiOperation(value = "今日课表接口(手机端)") @SaCheckPermission("schedule:coursetableday") @XjrLog(value = "今日课表接口(手机端)", saveResponseData = true) public RT courseInfoDay(CourseTableDto dto) { LocalDateTime now = LocalDateTime.now(); DayOfWeek dayOfWeek = now.getDayOfWeek(); dto.setWeekDay(dayOfWeek.getValue()); dto.setToDay(now); if (ObjectUtil.isNotNull(dto.getStudentId())) { List schoolRolls = baseStudentSchoolRollService.list( new QueryWrapper().lambda().eq(BaseStudentSchoolRoll::getUserId, dto.getStudentId()) ); if (schoolRolls != null && !schoolRolls.isEmpty()) { dto.setCourseType("class"); dto.setClassId(schoolRolls.get(0).getClassId()); } } else { // 查询登录者身份 long loginIdAsLong = StpUtil.getLoginIdAsLong(); List schoolRolls = baseStudentSchoolRollService.list( new QueryWrapper().lambda().eq(BaseStudentSchoolRoll::getUserId, loginIdAsLong) ); if (schoolRolls != null && !schoolRolls.isEmpty()) { dto.setCourseType("class"); dto.setClassId(schoolRolls.get(0).getClassId()); } List teachers = baseTeacherService.list(new QueryWrapper().lambda().eq(BaseTeacher::getUserId, loginIdAsLong)); if (teachers != null && !teachers.isEmpty()) { dto.setCourseType("teacher"); dto.setTeacherId(loginIdAsLong); } } CourseTableVo list = courseTableService.getList(dto); return RT.ok(list); } @GetMapping(value = "/current-week") @ApiOperation(value = "获取当前周次") @SaCheckPermission("schedule:currentweek") @XjrLog(value = "获取当前周次", saveResponseData = true) public RT currentWeek(CourseTableDto dto) { CurrentWeekVo currentWeek = courseTableService.getCurrentWeek(dto); if(currentWeek != null){ return RT.ok(currentWeek.getWeek()); } return RT.ok(0); } @GetMapping(value = "/adjust-list") @ApiOperation(value = "可以调课的课程") @SaCheckPermission("schedule:adjustlist") @XjrLog(value = "可以调课的课程") public RT> adjustList(CourseTableAdjustDto dto) { if (dto.getAdjustDate() == null || dto.getTeacherId() == null) { return RT.error("请传入调整日期和教师id"); } List list = courseTableService.getAdjustList(dto.getTeacherId().toString(), dto.getAdjustDate(), dto.getClassId(), dto.getAdjustType()); if (list.isEmpty()) { return RT.error("暂无可调课程"); } return RT.ok(); } @GetMapping(value = "/adjust-list1") @ApiOperation(value = "可以调课的课程") @SaCheckPermission("schedule:adjustlist") @XjrLog(value = "可以调课的课程") public RT> adjustList1(CourseTableAdjustDto1 dto) { if (dto.getAdjustDate() == null || dto.getTeacherId() == null) { return RT.error("请传入调整日期和教师id"); } List list = courseTableService.getAdjustList1(dto.getClassId(), dto.getTeacherId().toString(), dto.getAdjustDate(),dto.getTimeNumber(),dto.getApplicantTeacherId().toString(), dto.getExchangeDate(), dto.getAdjustType()); if (list.isEmpty()) { return RT.error("暂无可调课程"); } return RT.ok(); } @GetMapping(value = "/pre-check") @ApiOperation(value = "预检查") @SaCheckPermission("schedule:precheck") @XjrLog(value = "预检查", saveResponseData = true) public RT preCheck(CourseTablePreCheckDto dto) throws Exception { if (dto.getPreCheckType() != null) { if (dto.getPreCheckType() == 1) { for (int i = 0; i < dto.getCourseIds().size(); i++) { Long courseId = dto.getCourseIds().get(i); Long swapCourseId = dto.getSwapCourseIds().get(i); CourseTable courseTable = courseTableService.getById(courseId); CourseTable swapCourseTable = courseTableService.getById(swapCourseId); JsonObject preCheck = getExtendPreCheck(dto, courseTable, swapCourseTable); if (preCheck.get("code").getAsInt() != 0) { return RT.error(preCheck.get("msg").getAsString()); } } } else if (dto.getPreCheckType() == 2) { for (Long courseId : dto.getCourseIds()) { CourseTable courseTable = courseTableService.getById(courseId); JsonObject jsonObject = substitutePreTestin(dto, courseTable); if (jsonObject.get("code").getAsInt() != 0) { return RT.error(jsonObject.get("msg").getAsString()); } } } } return RT.ok("ok"); } @GetMapping(value = "/getCourseNames") @ApiOperation(value = "查询课程接口") @SaCheckPermission("schedule:getcoursenames") @XjrLog(value = "查询课程接口", saveResponseData = true) public RT getCourseNames(String id) { String[] split = id.split(","); List list = courseTableService.list( new QueryWrapper().lambda() .in(CourseTable::getId, Arrays.asList(split)) ); List classTimeList = classTimeService.list(); String result = ""; for (int i = 0; i < list.size(); i++) { if (i > 0) { result += ","; } CourseTable courseTable = list.get(i); String courseName = courseTable.getCourseName(); ClassTime classTime = classTimeList.stream().filter(u -> u.getNumber().equals(courseTable.getTimeNumber())).findAny().orElse(null); if (classTime != null) { courseName += "(" + classTime.getShortName() + ")"; } result += courseName; } return RT.ok(result); } @GetMapping(value = "/getCourseInfo") @ApiOperation(value = "根据课程id获取课程相关信息") @SaCheckPermission("schedule:getcourseinfo") @XjrLog(value = "根据课程id获取课程相关信息", saveResponseData = true) public RT getCourseInfo(String id) { String[] split = id.split(","); List list = courseTableService.list( new QueryWrapper().lambda() .in(CourseTable::getId, Arrays.asList(split)) ); CourseNamesVo resultVo = new CourseNamesVo(); Set classSets = list.stream().map(CourseTable::getClassId).collect(Collectors.toSet()); if(classSets.size() > 1){ resultVo.setStatus(0); return RT.ok(resultVo); } List classTimeList = classTimeService.list(); String courseNames = ""; String timeNumbers = ""; Set classIdSet = new HashSet<>(); Set classNameSet = new HashSet<>(); for (int i = 0; i < list.size(); i++) { if (i > 0) { courseNames += ","; timeNumbers += ","; } CourseTable courseTable = list.get(i); String courseName = courseTable.getCourseName(); ClassTime classTime = classTimeList.stream().filter(u -> u.getNumber().equals(courseTable.getTimeNumber())).findAny().orElse(null); if (classTime != null) { courseName += "(" + classTime.getShortName() + ")"; } courseNames += courseName; timeNumbers += courseTable.getTimeNumber(); classIdSet.add(courseTable.getClassId()); classNameSet.add(courseTable.getClassName()); } resultVo.setCourseNames(courseNames); resultVo.setTimeNumbers(timeNumbers); resultVo.setClassIds(classIdSet.toString().replace("[", "").replace("]", "").replace(" ", "")); resultVo.setClassNames(classNameSet.toString().replace("[", "").replace("]", "").replace(" ", "")); resultVo.setStatus(1); return RT.ok(resultVo); } @GetMapping(value = "/getCourseInfo1") @ApiOperation(value = "根据课程id获取课程相关信息") @SaCheckPermission("schedule:getcourseinfo") @XjrLog(value = "根据课程id获取课程相关信息", saveResponseData = true) public RT getCourseInfo1(String id) { String[] split = id.split(","); List list = courseTableService.list( new QueryWrapper().lambda() .in(CourseTable::getId, Arrays.asList(split)) ); CourseNamesVo resultVo = new CourseNamesVo(); Set classSets = list.stream().map(CourseTable::getClassId).collect(Collectors.toSet()); if(classSets.size() > 1){ resultVo.setStatus(0); return RT.ok(resultVo); } // 定义日期和时间的格式 DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH:mm:ss"); // 获取当前时间 LocalDateTime now = LocalDateTime.now(); // 筛选出已过期的课程(schedule_date + start_time < 当前时间) List expiredCourses = list.stream() .filter(course -> { // 解析日期和时间 LocalDate courseDate =course.getScheduleDate(); LocalTime courseTime = LocalTime.parse(course.getStartTime(), timeFormatter); // 合并成 LocalDateTime 进行比较 LocalDateTime courseDateTime = LocalDateTime.of(courseDate, courseTime); return courseDateTime.isBefore(now); }) .collect(Collectors.toList()); if(!expiredCourses.isEmpty()) { resultVo.setStatus(2); return RT.ok(resultVo); } List classTimeList = classTimeService.list(); String courseNames = ""; String timeNumbers = ""; Set classIdSet = new HashSet<>(); Set classNameSet = new HashSet<>(); for (int i = 0; i < list.size(); i++) { if (i > 0) { courseNames += ","; timeNumbers += ","; } CourseTable courseTable = list.get(i); String courseName = courseTable.getCourseName(); ClassTime classTime = classTimeList.stream().filter(u -> u.getNumber().equals(courseTable.getTimeNumber())).findAny().orElse(null); if (classTime != null) { courseName += "(" + classTime.getShortName() + ")"; } courseNames += courseName; timeNumbers += courseTable.getTimeNumber(); classIdSet.add(courseTable.getClassId()); classNameSet.add(courseTable.getClassName()); } resultVo.setCourseNames(courseNames); resultVo.setTimeNumbers(timeNumbers); resultVo.setClassIds(classIdSet.toString().replace("[", "").replace("]", "").replace(" ", "")); resultVo.setClassNames(classNameSet.toString().replace("[", "").replace("]", "").replace(" ", "")); resultVo.setStatus(1); return RT.ok(resultVo); } /** * 顶课预检查 * * @param dto * @param courseTable * @return 检查结果 */ JsonObject substitutePreTestin(CourseTablePreCheckDto dto, 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(dto.getSubTeacherId()); 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(CourseTablePreCheckDto dto, 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", dto.getSwapDate().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(); } @PostMapping("/schedule-week-export-query") @ApiOperation(value = "按周导出课表") @SaCheckPermission("schedule:scheduleweekexportquery") @XjrLog(value = "按周导出课表") public ResponseEntity scheduleWeekExportQuery(@Valid @RequestBody CourseTableDto dto) { // @GetMapping("/schedule-week-export-query") // @ApiOperation(value = "按周导出课表") // public ResponseEntity textbookClaimExportQuery(ScheduleWeekExportQueryDto dto) { ByteArrayOutputStream bot = courseTableService.scheduleWeekExportQuery(dto); return RT.fileStream(bot.toByteArray(), "scheduleWeek" + ExcelTypeEnum.XLSX.getValue()); } @GetMapping(value = "/login-url") @ApiOperation(value = "获取单点登录地址") @SaCheckPermission("schedule:loginurl") @XjrLog(value = "获取单点登录地址", saveResponseData = true) public RT getAccessToken() throws Exception { XjrUser xjrUser = teacherService.getById(StpUtil.getLoginIdAsLong()); long timeMillis = System.currentTimeMillis(); String sign = ScheduleUtil.createSign(timeMillis); JsonObject jsonObject = new JsonObject(); jsonObject.addProperty("mobileNo", xjrUser.getMobile()); String url = ScheduleUtil.apiUrl + "auth/user/token"; try { String result = ScheduleUtil.doPost(url, jsonObject.toString(), sign, timeMillis); JsonParser parser = new JsonParser(); JsonObject resultJson = parser.parse(result).getAsJsonObject(); if (resultJson.get("code").getAsInt() != 0) { return RT.error("无登录权限"); } JsonObject dataJson = resultJson.get("data").getAsJsonObject(); String loginUrl = ScheduleUtil.hostUrl + "?access_token=" + dataJson.get("access_token").getAsString(); return RT.ok(loginUrl); } catch (Exception e) { return RT.error(e.getMessage()); } } @GetMapping(value = "/week-list") @ApiOperation(value = "获取周次列表") @SaCheckPermission("schedule:weeklist") @XjrLog(value = "获取周次列表") public RT> weekList(@Valid ScheduleWeekDto dto) { BaseSemester baseSemester; if (dto.getSemesterId() != null) { baseSemester = semesterService.getById(dto.getSemesterId()); } else { baseSemester = semesterService.getCurrentSemester(); if (baseSemester == null) { return RT.ok(new ArrayList<>()); } } LocalDate startDate = LocalDate.ofInstant(baseSemester.getTeachingStart().toInstant(), ZoneId.systemDefault()); LocalDate endDate = LocalDate.ofInstant(baseSemester.getTeachingEnd().toInstant(), ZoneId.systemDefault()); List weeks = calculateSemesterWeeks(startDate, endDate); return RT.ok(weeks); // Duration between = Duration.between(startDateTime, endDateTime); // long days = between.toDays(); // int weeks = (int) Math.ceil((double) days / 7); // List result = new ArrayList<>(); // for (int i = 0; i < weeks; i++) { // LocalDateTime startDate = startDateTime.plusDays(i * 7L).withHour(0).withMinute(0).withSecond(0).withNano(0); // LocalDateTime endDate = startDate.plusDays(6).withHour(23).withMinute(59).withSecond(59).withNano(9999); // int week = i + 1; // result.add( // new ScheduleWeekVo() {{ // setWeek(week); // setWeekCn("第" + week + "周"); // setStartDate(startDate.toLocalDate()); // setEndDate(endDate.toLocalDate()); // }} // ); // } // // return RT.ok(result); } /** * 计算学期的自然周列表 * @param semesterStart 学期开始日期 * @param semesterEnd 学期结束日期 * @return 周次信息列表 */ private List calculateSemesterWeeks(LocalDate semesterStart, LocalDate semesterEnd) { List weekList = new ArrayList<>(); // 调整开始日期到本周星期一 LocalDate adjustedStart = semesterStart.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)); // 调整结束日期到本周星期日 LocalDate adjustedEnd = semesterEnd.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY)); // 计算总周数 long totalDays = java.time.temporal.ChronoUnit.DAYS.between(adjustedStart, adjustedEnd) + 1; int totalWeeks = (int) (totalDays / 7); // 生成每一周的信息 for (int i = 0; i < totalWeeks; i++) { LocalDate weekStart = adjustedStart.plusWeeks(i); LocalDate weekEnd = weekStart.plusDays(6); // 一周结束是星期日 ScheduleWeekVo weekVo = new ScheduleWeekVo(); weekVo.setWeek(i + 1); // 周次从1开始 weekVo.setWeekCn("第" + (i + 1) + "周"); weekVo.setStartDate(weekStart); weekVo.setEndDate(weekEnd); weekList.add(weekVo); } return weekList; } @GetMapping(value = "/class-list") @ApiOperation(value = "根据课表获取教师所教班级") @SaCheckPermission("schedule:classlist") @XjrLog(value = "根据课表获取教师所教班级") public RT> classList(@Valid ClassOptionDto dto) { if (dto.getUserId() == null) { dto.setUserId(StpUtil.getLoginIdAsLong()); } List result = courseTableService.getClassListByTeacherId(dto); return RT.ok(result); } @PostMapping(value = "/cancel") @ApiOperation(value = "调课顶课的作废") @SaCheckPermission("schedule:cancel") @XjrLog(value = "调课顶课的作废", saveResponseData = true) public RT cancel(@Valid @RequestBody WfCourseAdjustDto dto) { return RT.ok(courseAdjustService.cancel(dto)); } @GetMapping(value = "/is-contains-all") @ApiOperation(value = "判断登录者是否有查看所有课表的权限") @SaCheckPermission("schedule:iscontainsall") @XjrLog(value = "判断登录者是否有查看所有课表的权限", saveResponseData = true) public RT classList() { if (StpUtil.getRoleList().contains("KeBiao")) { return RT.ok(true); } return RT.ok(false); } @PostMapping("/export-query") @ApiOperation(value = "导出课表") @SaCheckPermission("schedule:exportquery") @XjrLog(value = "导出课表") public ResponseEntity exportQuery(@Valid @RequestBody CourseTableExportQueryDto dto) throws IOException { ByteArrayOutputStream bot = courseTableService.exportQuery(dto); return RT.fileStream(bot.toByteArray(), "scheduleWeek" + ExcelTypeEnum.XLSX.getValue()); } }