package com.qxgmat.controller.api; import com.github.pagehelper.Page; import com.nuliji.tools.*; import com.nuliji.tools.exception.AuthException; import com.nuliji.tools.exception.ParameterException; import com.qxgmat.data.constants.enums.QuestionType; import com.qxgmat.data.constants.enums.ServiceKey; import com.qxgmat.data.constants.enums.TextbookSubject; import com.qxgmat.data.constants.enums.logic.TextbookLogic; import com.qxgmat.data.constants.enums.module.PaperOrigin; import com.qxgmat.data.constants.enums.module.ProductType; import com.qxgmat.data.constants.enums.module.QuestionModule; import com.qxgmat.data.constants.enums.status.DirectionStatus; import com.qxgmat.data.dao.entity.*; import com.qxgmat.data.inline.UserQuestionStat; import com.qxgmat.data.relation.entity.QuestionNoRelation; import com.qxgmat.data.relation.entity.MonthNumberRelation; import com.qxgmat.dto.extend.*; import com.qxgmat.dto.request.TextbookEnrollDto; import com.qxgmat.dto.request.TextbookSubscribeDto; import com.qxgmat.dto.response.TextbookEnrollTimeDto; import com.qxgmat.dto.response.UserTextbookGroupDto; import com.qxgmat.dto.response.UserTextbookInfoDto; import com.qxgmat.dto.response.UserTextbookPaperDto; import com.qxgmat.help.ShiroHelp; import com.qxgmat.service.UserPaperService; import com.qxgmat.service.UserQuestionService; import com.qxgmat.service.UserServiceService; import com.qxgmat.service.UsersService; import com.qxgmat.service.extend.QuestionFlowService; import com.qxgmat.service.extend.TextbookService; import com.qxgmat.service.extend.ToolsService; import com.qxgmat.service.inline.*; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpSession; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.*; import java.util.stream.Collectors; @RestController @RequestMapping("/api/textbook") @Api(tags = "机经", description = "机经接口") public class TextbookController { @Autowired private ShiroHelp shiroHelp; @Autowired private QuestionService questionService; @Autowired private QuestionNoService questionNoService; @Autowired private SettingService settingService; @Autowired private UsersService usersService; @Autowired private UserPaperService userPaperService; @Autowired private UserQuestionService userQuestionService; @Autowired private UserReportService userReportService; @Autowired private UserServiceService userServiceService; @Autowired private UserOrderRecordService userOrderRecordService; @Autowired private QuestionFlowService questionFlowService; @Autowired private TextbookPaperService textbookPaperService; @Autowired private TextbookQuestionService textbookQuestionService; @Autowired private TextbookLibraryService textbookLibraryService; @Autowired private TextbookLibraryHistoryService textbookLibraryHistoryService; @Autowired private TextbookTopicService textbookTopicService; @Autowired private TextbookService textbookService; @Autowired private ToolsService toolsService; @Autowired private UserTextbookEnrollService userTextbookEnrollService; @RequestMapping(value = "/progress", method = RequestMethod.GET) @ApiOperation(value = "机经进度", httpMethod = "GET") public Response> progress(HttpSession session) { User user = (User) shiroHelp.getLoginUser(); TextbookLibrary latest = textbookLibraryService.getLatest(); List p = new ArrayList<>(2); Integer latestId = latest.getId(); for(TextbookLibrary library : new ArrayList(2){{add(latest);add(null);}}){ UserTextbookGroupDto dto; List textbookList; if (library == null){ dto = new UserTextbookGroupDto(); dto.setIsLatest(0); dto.setNeedService(false); dto.setHasService(false); // 获取往期题目统计 textbookList = textbookQuestionService.listByNoLibrary(latestId); }else{ dto = Transform.convert(library, UserTextbookGroupDto.class); dto.setIsLatest(library.getEndDate() == null ? 1 : 0); dto.setNeedService(library.getEndDate() == null); dto.setHasService(true); // 获取第三层所有题目,并获取题目统计 textbookList = textbookQuestionService.listByLibrary(library.getId()); } Collection questionNoIds = Transform.getIds(textbookList, TextbookQuestion.class, "questionNoId"); List questionNoList = questionNoService.select(questionNoIds); List relations = questionNoService.relation(questionNoList); dto.setStat(questionNoService.statPaper(questionNoList)); dto.setQuestionNumber(textbookList.size()); Map userQuestionStatMap = null; if(user != null){ if (dto.getNeedService()){ dto.setHasService(userServiceService.hasService(user.getId(), ServiceKey.TEXTBOOK)); // 服务, 判断对应服务状态 UserOrderRecord record = userOrderRecordService.getUnUseService(user.getId(), ServiceKey.TEXTBOOK); dto.setUnUseRecord(Transform.convert(record, UserServiceRecordExtendDto.class)); } List userQuestionList = userQuestionService.listByQuestionNo(user.getId(), QuestionModule.TEXTBOOK, questionNoIds); userQuestionStatMap = userQuestionService.statQuestionNoMap(userQuestionList); dto.setUserStat(userQuestionService.statQuestion(userQuestionList)); if (questionNoList.size() > userQuestionStatMap.size()){ dto.setUserNumber(userQuestionStatMap.size()); dto.setMinTimes(0); }else{ int minTimes = 0; // 统计最小轮的已做题数 for(UserQuestionStat stat : userQuestionStatMap.values()){ if(stat.getUserNumber() < minTimes || minTimes == 0) minTimes = stat.getUserNumber(); } int userNumber = 0; for(UserQuestionStat stat : userQuestionStatMap.values()){ if(stat.getUserNumber() > minTimes) userNumber += 1; } dto.setMinTimes(minTimes); dto.setUserNumber(userNumber); } } List childrenDtos = new ArrayList<>(TextbookLogic.all().length); for(TextbookLogic logic : TextbookLogic.all()){ UserTextbookGroupExtendDto extendDto = new UserTextbookGroupExtendDto(); extendDto.setLogic(logic.key); extendDto.setTitle(logic.key.toUpperCase()); List childQuestionList = relations.stream().filter((q)-> logic.contain(QuestionType.ValueOf(q.getQuestion().getQuestionType()))).collect(Collectors.toList()); extendDto.setQuestionNumber(childQuestionList.size()); if (user != null){ int minTimes = 0; int userQuestionNumber = 0; boolean flag = true; for(QuestionNoRelation questionNo : childQuestionList){ UserQuestionStat stat = userQuestionStatMap.get(questionNo.getId()); if (stat == null) { flag = false; break; } if (stat.getUserNumber() < minTimes || minTimes == 0) minTimes = stat.getUserNumber(); } if (!flag) minTimes = 0; for(QuestionNoRelation questionNo : childQuestionList){ UserQuestionStat stat = userQuestionStatMap.get(questionNo.getId()); if (stat != null && stat.getUserNumber() > minTimes) userQuestionNumber += 1; } extendDto.setUserNumber(userQuestionNumber); extendDto.setMinTimes(minTimes); } childrenDtos.add(extendDto); } dto.setChildren(childrenDtos); p.add(dto); } return ResponseHelp.success(p); } @RequestMapping(value = "/info", method = RequestMethod.GET) @ApiOperation(value = "机经信息", httpMethod = "GET") public Response info(HttpSession session) { User user = (User) shiroHelp.getLoginUser(); UserTextbookInfoDto dto = new UserTextbookInfoDto(); TextbookLibrary latest = textbookLibraryService.getLatest(); dto.setLatest(latest); dto.setHasService(false); if (user != null){ UserService userService = userServiceService.getServiceBase(user.getId(), ServiceKey.TEXTBOOK); dto.setHasService(userService != null && userService.getExpireTime().after(new Date())); UserOrderRecord record = userOrderRecordService.getUnUseService(user.getId(), ServiceKey.TEXTBOOK); dto.setUnUseRecord(Transform.convert(record, UserServiceRecordExtendDto.class)); dto.setSubscribe(userService != null && userService.getIsSubscribe() > 0); dto.setStartTime(userService != null ? userService.getStartTime() : null); dto.setExpireTime(userService != null ? userService.getExpireTime() : null); } textbookService.refreshLibraryResource(user, latest); TextbookLibrary second = textbookLibraryService.getSecond(); textbookService.refreshLibraryResource(user, second); dto.setSecond(second); return ResponseHelp.success(dto); } @RequestMapping(value = "/year", method = RequestMethod.GET) @ApiOperation(value = "机经年度更新信息", httpMethod = "GET") public Response> year( @RequestParam(required = false) String year, HttpSession session) { User user = (User) shiroHelp.getLoginUser(); Date start; try { start = DateFormat.getDateInstance().parse(String.format("%s-01-01", year)); } catch (ParseException e) { throw new ParameterException("日期格式错误"); } Date end = Tools.addYear(start, 1); List libraryList = textbookLibraryService.listByTime(start, end); textbookService.refreshLibraryResource(user, libraryList); return ResponseHelp.success(libraryList); } @RequestMapping(value = "/history/all", method = RequestMethod.GET) @ApiOperation(value = "机经更新记录", httpMethod = "GET") public Response> listHistory( @RequestParam(required = true) String subject, HttpSession session) { User user = (User) shiroHelp.getLoginUser(); if (user == null){ throw new AuthException("请先登录"); } if (!userServiceService.hasService(user.getId(), ServiceKey.TEXTBOOK)){ throw new ParameterException("没有机经查看权限"); } if (TextbookSubject.ValueOf(subject) == null){ throw new ParameterException("科目错误"); } TextbookLibrary library = textbookLibraryService.getLatest(); List p = textbookLibraryHistoryService.allByLibraryAndSubject(library.getId(), TextbookSubject.ValueOf(subject)); textbookService.refreshHistoryResource(user, p); return ResponseHelp.success(p); } @RequestMapping(value = "/topic/no", method = RequestMethod.GET) @ApiOperation(value = "获取机经详情", notes = "根据机经序号获取题目", httpMethod = "GET") public Response topic( @RequestParam(required = true) Integer libraryId, @RequestParam(required = true) String subject, @RequestParam(required = true) Integer no ) { User user = (User) shiroHelp.getLoginUser(); if (user == null) { throw new AuthException("请先登录"); } if (no == null || no == 0){ no = 1; } TextbookTopic textbookTopic = textbookTopicService.getByNo(libraryId, subject, no); return ResponseHelp.success(textbookTopic); } @RequestMapping(value = "/topic/list", method = RequestMethod.GET) @ApiOperation(value = "机经列表", httpMethod = "GET") public Response> listTopic( @RequestParam(required = false, defaultValue = "1") int page, @RequestParam(required = false, defaultValue = "100") int size, @RequestParam(required = false) boolean latest, @RequestParam(required = true) String subject, @RequestParam(required = false) String keyword, @RequestParam(required = false) String quality, @RequestParam(required = false) Boolean isOld, @RequestParam(required = false, defaultValue = "id") String order, @RequestParam(required = false, defaultValue = "desc") String direction, HttpSession session) { TextbookLibrary library; if (latest){ User user = (User) shiroHelp.getLoginUser(); if (user == null){ throw new AuthException("请先登录"); } if (!userServiceService.hasService(user.getId(), ServiceKey.TEXTBOOK)){ throw new ParameterException("没有机经查看权限"); } library = textbookLibraryService.getLatest(); }else{ // 获取往期:倒数第二 library = textbookLibraryService.getSecond(); } Page p = textbookTopicService.list(page, size, library.getId(), TextbookSubject.ValueOf(subject), keyword, quality, isOld, order, DirectionStatus.ValueOf(direction)); return ResponseHelp.success(p, page, size, p.getTotal()); } @RequestMapping(value = "/paper/list", method = RequestMethod.GET) @ApiOperation(value = "机经组卷列表", httpMethod = "GET") public Response> listPaper( @RequestParam(required = false, defaultValue = "1") int page, @RequestParam(required = false, defaultValue = "100") int size, @RequestParam(required = true) boolean latest, @RequestParam(required = true) String logic, @RequestParam(required = false) String year, @RequestParam(required = false) Integer times, HttpSession session) { User user = (User) shiroHelp.getLoginUser(); TextbookLibrary library= null; if (latest){ if (user == null){ throw new AuthException("请先登录"); } if (!userServiceService.hasService(user.getId(), ServiceKey.TEXTBOOK)){ throw new ParameterException("请先开通本期机经"); } library = textbookLibraryService.getLatest(); } List p = textbookPaperService.list(page, size, library != null ? library.getId():null, user != null ? user.getId():null, TextbookLogic.ValueOf(logic), year, times); List pr = Transform.convert(p, UserTextbookPaperDto.class); // 获取试卷统计信息 Map questionNoIdsMap = new HashMap<>(); for(TextbookPaper paper : p){ questionNoIdsMap.put(paper.getId(), paper.getQuestionNoIds()); } Map statMap = questionNoService.statPaperMap(questionNoIdsMap); Transform.combine(pr, statMap, UserTextbookPaperDto.class, "id", "stat"); if (user != null){ // 获取做题记录 Collection ids = Transform.getIds(p, TextbookPaper.class, "id"); List userPaperList = userPaperService.listWithOrigin(user.getId(), PaperOrigin.TEXTBOOK, ids, null); Transform.combine(pr, userPaperList, UserTextbookPaperDto.class, "id", "paper", UserPaper.class, "originId", UserPaperBaseExtendDto.class); // 绑定userPaperId,用于关联report Map userPaperMap = Transform.getMap(userPaperList, UserPaper.class, "originId", "id"); Transform.combine(pr, userPaperMap, UserTextbookPaperDto.class, "id", "userPaperId"); // 获取最后一次作业结果 Collection paperIds = Transform.getIds(userPaperList, UserPaper.class, "id"); List reportList = userReportService.listWithLast(paperIds); Transform.combine(pr, reportList, UserTextbookPaperDto.class, "userPaperId", "report", UserReport.class, "paperId", UserReportExtendDto.class); } return ResponseHelp.success(pr); } @RequestMapping(value = "/subscribe", method = RequestMethod.POST) @ApiOperation(value = "订阅机经", notes = "订阅机经开关", httpMethod = "POST") public Response subscribe(@RequestBody @Validated TextbookSubscribeDto dto) { User user = (User) shiroHelp.getLoginUser(); if (user == null){ throw new AuthException("请先登录"); } UserService userService = userServiceService.getServiceBase(user.getId(), ServiceKey.TEXTBOOK); if (userService == null){ throw new ParameterException("无订阅权限"); } userServiceService.edit(UserService.builder().id(userService.getId()).isSubscribe(dto.getSubscribe() ? 1 : 0).build()); return ResponseHelp.success(true); } @RequestMapping(value = "/enroll", method = RequestMethod.POST) @ApiOperation(value = "报名", notes = "报名", httpMethod = "POST") public Response enroll(@RequestBody @Validated TextbookEnrollDto dto) { User user = (User) shiroHelp.getLoginUser(); if (user == null){ throw new AuthException("请先登录"); } textbookService.enroll(user.getId(), dto.getDate()); return ResponseHelp.success(true); } @RequestMapping(value = "/enroll/cancel", method = RequestMethod.POST) @ApiOperation(value = "取消报名", notes = "取消报名", httpMethod = "POST") public Response cancelEnroll() { User user = (User) shiroHelp.getLoginUser(); if (user == null){ throw new AuthException("请先登录"); } textbookService.unEnroll(user.getId()); return ResponseHelp.success(true); } @RequestMapping(value = "/enroll/list", method = RequestMethod.GET) @ApiOperation(value = "报名记录", notes = "报名记录", httpMethod = "GET") public Response enrollList( @RequestParam(required = true) String startDate, @RequestParam(required = true) String endDate, HttpSession session) { User user = (User) shiroHelp.getLoginUser(); Date end; Date start; try{ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); end = sdf.parse(endDate); start = sdf.parse(startDate); }catch (Exception e){ throw new ParameterException("日期格式错误"); } Integer useNumber = toolsService.getTextbookUseNumber(); if (useNumber == null){ useNumber = 0; } TextbookEnrollTimeDto dto = new TextbookEnrollTimeDto(); List enrollRelation = userTextbookEnrollService.groupByMonth(startDate, endDate); Map enrollMonthMap = new HashMap<>(); for(MonthNumberRelation relation : enrollRelation){ int month = relation.getMonth(); enrollMonthMap.put(month, relation.getNumber()); } List recordRelation = userOrderRecordService.groupByMonth(startDate, endDate, ProductType.SERVICE, null, ServiceKey.TEXTBOOK); Map recordMonthMap = new HashMap<>(); for(MonthNumberRelation relation : recordRelation){ int month = relation.getMonth(); recordMonthMap.put(month, relation.getNumber()); } // 获取用户报考日期 if(user != null){ UserTextbookEnroll enroll = userTextbookEnrollService.getByUser(user.getId()); if (enroll != null){ dto.setDate(enroll.getDate()); } } List dtos = new ArrayList<>(); while(start.before(end)){ int month = Tools.monthNumber(start); int enrollNumber = enrollMonthMap.getOrDefault(month, 0); int recordNumber = recordMonthMap.getOrDefault(month, 0); TextbookEnrollTimeExtendDto extendDto = new TextbookEnrollTimeExtendDto(); extendDto.setMonth(start); extendDto.setEnrollNumber(enrollNumber); extendDto.setUseNumber(recordNumber + useNumber); dtos.add(extendDto); start = Tools.addMonth(start, 1); } dto.setTimes(dtos); return ResponseHelp.success(dto); } }