TextbookController.java 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480
  1. package com.qxgmat.controller.api;
  2. import com.github.pagehelper.Page;
  3. import com.nuliji.tools.*;
  4. import com.nuliji.tools.exception.AuthException;
  5. import com.nuliji.tools.exception.ParameterException;
  6. import com.qxgmat.data.constants.enums.QuestionType;
  7. import com.qxgmat.data.constants.enums.ServiceKey;
  8. import com.qxgmat.data.constants.enums.TextbookSubject;
  9. import com.qxgmat.data.constants.enums.logic.TextbookLogic;
  10. import com.qxgmat.data.constants.enums.module.PaperOrigin;
  11. import com.qxgmat.data.constants.enums.module.ProductType;
  12. import com.qxgmat.data.constants.enums.module.QuestionModule;
  13. import com.qxgmat.data.constants.enums.status.DirectionStatus;
  14. import com.qxgmat.data.dao.entity.*;
  15. import com.qxgmat.data.inline.UserQuestionStat;
  16. import com.qxgmat.data.relation.entity.QuestionNoRelation;
  17. import com.qxgmat.data.relation.entity.MonthNumberRelation;
  18. import com.qxgmat.dto.extend.*;
  19. import com.qxgmat.dto.request.TextbookEnrollDto;
  20. import com.qxgmat.dto.request.TextbookSubscribeDto;
  21. import com.qxgmat.dto.response.TextbookEnrollTimeDto;
  22. import com.qxgmat.dto.response.UserTextbookGroupDto;
  23. import com.qxgmat.dto.response.UserTextbookInfoDto;
  24. import com.qxgmat.dto.response.UserTextbookPaperDto;
  25. import com.qxgmat.help.ShiroHelp;
  26. import com.qxgmat.service.UserPaperService;
  27. import com.qxgmat.service.UserQuestionService;
  28. import com.qxgmat.service.UserServiceService;
  29. import com.qxgmat.service.UsersService;
  30. import com.qxgmat.service.extend.QuestionFlowService;
  31. import com.qxgmat.service.extend.TextbookService;
  32. import com.qxgmat.service.extend.ToolsService;
  33. import com.qxgmat.service.inline.*;
  34. import io.swagger.annotations.Api;
  35. import io.swagger.annotations.ApiOperation;
  36. import org.springframework.beans.factory.annotation.Autowired;
  37. import org.springframework.validation.annotation.Validated;
  38. import org.springframework.web.bind.annotation.*;
  39. import javax.servlet.http.HttpSession;
  40. import java.text.DateFormat;
  41. import java.text.ParseException;
  42. import java.text.SimpleDateFormat;
  43. import java.util.*;
  44. import java.util.stream.Collectors;
  45. @RestController
  46. @RequestMapping("/api/textbook")
  47. @Api(tags = "机经", description = "机经接口")
  48. public class TextbookController
  49. {
  50. @Autowired
  51. private ShiroHelp shiroHelp;
  52. @Autowired
  53. private QuestionService questionService;
  54. @Autowired
  55. private QuestionNoService questionNoService;
  56. @Autowired
  57. private SettingService settingService;
  58. @Autowired
  59. private UsersService usersService;
  60. @Autowired
  61. private UserPaperService userPaperService;
  62. @Autowired
  63. private UserQuestionService userQuestionService;
  64. @Autowired
  65. private UserReportService userReportService;
  66. @Autowired
  67. private UserServiceService userServiceService;
  68. @Autowired
  69. private UserOrderRecordService userOrderRecordService;
  70. @Autowired
  71. private QuestionFlowService questionFlowService;
  72. @Autowired
  73. private TextbookPaperService textbookPaperService;
  74. @Autowired
  75. private TextbookQuestionService textbookQuestionService;
  76. @Autowired
  77. private TextbookLibraryService textbookLibraryService;
  78. @Autowired
  79. private TextbookLibraryHistoryService textbookLibraryHistoryService;
  80. @Autowired
  81. private TextbookTopicService textbookTopicService;
  82. @Autowired
  83. private TextbookService textbookService;
  84. @Autowired
  85. private ToolsService toolsService;
  86. @Autowired
  87. private UserTextbookEnrollService userTextbookEnrollService;
  88. @RequestMapping(value = "/progress", method = RequestMethod.GET)
  89. @ApiOperation(value = "机经进度", httpMethod = "GET")
  90. public Response<List<UserTextbookGroupDto>> progress(HttpSession session) {
  91. User user = (User) shiroHelp.getLoginUser();
  92. TextbookLibrary latest = textbookLibraryService.getLatest();
  93. List<UserTextbookGroupDto> p = new ArrayList<>(2);
  94. Integer latestId = latest.getId();
  95. for(TextbookLibrary library : new ArrayList<TextbookLibrary>(2){{add(latest);add(null);}}){
  96. UserTextbookGroupDto dto;
  97. List<TextbookQuestion> textbookList;
  98. if (library == null){
  99. dto = new UserTextbookGroupDto();
  100. dto.setIsLatest(0);
  101. dto.setNeedService(false);
  102. dto.setHasService(false);
  103. // 获取往期题目统计
  104. textbookList = textbookQuestionService.listByNoLibrary(latestId);
  105. }else{
  106. dto = Transform.convert(library, UserTextbookGroupDto.class);
  107. dto.setIsLatest(library.getEndDate() == null ? 1 : 0);
  108. dto.setNeedService(library.getEndDate() == null);
  109. dto.setHasService(true);
  110. // 获取第三层所有题目,并获取题目统计
  111. textbookList = textbookQuestionService.listByLibrary(library.getId());
  112. }
  113. Collection questionNoIds = Transform.getIds(textbookList, TextbookQuestion.class, "questionNoId");
  114. List<QuestionNo> questionNoList = questionNoService.select(questionNoIds);
  115. List<QuestionNoRelation> relations = questionNoService.relation(questionNoList);
  116. dto.setStat(questionNoService.statPaper(questionNoList));
  117. dto.setQuestionNumber(textbookList.size());
  118. Map<Object, UserQuestionStat> userQuestionStatMap = null;
  119. if(user != null){
  120. if (dto.getNeedService()){
  121. dto.setHasService(userServiceService.hasService(user.getId(), ServiceKey.TEXTBOOK));
  122. // 服务, 判断对应服务状态
  123. UserOrderRecord record = userOrderRecordService.getUnUseService(user.getId(), ServiceKey.TEXTBOOK);
  124. dto.setUnUseRecord(Transform.convert(record, UserServiceRecordExtendDto.class));
  125. }
  126. List<UserQuestion> userQuestionList = userQuestionService.listByQuestionNo(user.getId(), QuestionModule.TEXTBOOK, questionNoIds);
  127. userQuestionStatMap = userQuestionService.statQuestionNoMap(userQuestionList);
  128. dto.setUserStat(userQuestionService.statQuestion(userQuestionList));
  129. if (questionNoList.size() > userQuestionStatMap.size()){
  130. dto.setUserNumber(userQuestionStatMap.size());
  131. dto.setMinTimes(0);
  132. }else{
  133. int minTimes = 0;
  134. // 统计最小轮的已做题数
  135. for(UserQuestionStat stat : userQuestionStatMap.values()){
  136. if(stat.getUserNumber() < minTimes || minTimes == 0) minTimes = stat.getUserNumber();
  137. }
  138. int userNumber = 0;
  139. for(UserQuestionStat stat : userQuestionStatMap.values()){
  140. if(stat.getUserNumber() > minTimes) userNumber += 1;
  141. }
  142. dto.setMinTimes(minTimes);
  143. dto.setUserNumber(userNumber);
  144. }
  145. }
  146. List<UserTextbookGroupExtendDto> childrenDtos = new ArrayList<>(TextbookLogic.all().length);
  147. for(TextbookLogic logic : TextbookLogic.all()){
  148. UserTextbookGroupExtendDto extendDto = new UserTextbookGroupExtendDto();
  149. extendDto.setLogic(logic.key);
  150. extendDto.setTitle(logic.key.toUpperCase());
  151. List<QuestionNoRelation> childQuestionList = relations.stream().filter((q)-> logic.contain(QuestionType.ValueOf(q.getQuestion().getQuestionType()))).collect(Collectors.toList());
  152. extendDto.setQuestionNumber(childQuestionList.size());
  153. if (user != null){
  154. int minTimes = 0;
  155. int userQuestionNumber = 0;
  156. boolean flag = true;
  157. for(QuestionNoRelation questionNo : childQuestionList){
  158. UserQuestionStat stat = userQuestionStatMap.get(questionNo.getId());
  159. if (stat == null) {
  160. flag = false;
  161. break;
  162. }
  163. if (stat.getUserNumber() < minTimes || minTimes == 0) minTimes = stat.getUserNumber();
  164. }
  165. if (!flag) minTimes = 0;
  166. for(QuestionNoRelation questionNo : childQuestionList){
  167. UserQuestionStat stat = userQuestionStatMap.get(questionNo.getId());
  168. if (stat != null && stat.getUserNumber() > minTimes) userQuestionNumber += 1;
  169. }
  170. extendDto.setUserNumber(userQuestionNumber);
  171. extendDto.setMinTimes(minTimes);
  172. }
  173. childrenDtos.add(extendDto);
  174. }
  175. dto.setChildren(childrenDtos);
  176. p.add(dto);
  177. }
  178. return ResponseHelp.success(p);
  179. }
  180. @RequestMapping(value = "/info", method = RequestMethod.GET)
  181. @ApiOperation(value = "机经信息", httpMethod = "GET")
  182. public Response<UserTextbookInfoDto> info(HttpSession session) {
  183. User user = (User) shiroHelp.getLoginUser();
  184. UserTextbookInfoDto dto = new UserTextbookInfoDto();
  185. TextbookLibrary latest = textbookLibraryService.getLatest();
  186. dto.setLatest(latest);
  187. dto.setHasService(false);
  188. if (user != null){
  189. UserService userService = userServiceService.getServiceBase(user.getId(), ServiceKey.TEXTBOOK);
  190. dto.setHasService(userService != null && userService.getExpireTime().after(new Date()));
  191. UserOrderRecord record = userOrderRecordService.getUnUseService(user.getId(), ServiceKey.TEXTBOOK);
  192. dto.setUnUseRecord(Transform.convert(record, UserServiceRecordExtendDto.class));
  193. dto.setSubscribe(userService != null && userService.getIsSubscribe() > 0);
  194. dto.setStartTime(userService != null ? userService.getStartTime() : null);
  195. dto.setExpireTime(userService != null ? userService.getExpireTime() : null);
  196. }
  197. textbookService.refreshLibraryResource(user, latest);
  198. TextbookLibrary second = textbookLibraryService.getSecond();
  199. textbookService.refreshLibraryResource(user, second);
  200. dto.setSecond(second);
  201. return ResponseHelp.success(dto);
  202. }
  203. @RequestMapping(value = "/year", method = RequestMethod.GET)
  204. @ApiOperation(value = "机经年度更新信息", httpMethod = "GET")
  205. public Response<List<TextbookLibrary>> year(
  206. @RequestParam(required = false) String year,
  207. HttpSession session) {
  208. User user = (User) shiroHelp.getLoginUser();
  209. Date start;
  210. try {
  211. start = DateFormat.getDateInstance().parse(String.format("%s-01-01", year));
  212. } catch (ParseException e) {
  213. throw new ParameterException("日期格式错误");
  214. }
  215. Date end = Tools.addYear(start, 1);
  216. List<TextbookLibrary> libraryList = textbookLibraryService.listByTime(start, end);
  217. textbookService.refreshLibraryResource(user, libraryList);
  218. return ResponseHelp.success(libraryList);
  219. }
  220. @RequestMapping(value = "/history/all", method = RequestMethod.GET)
  221. @ApiOperation(value = "机经更新记录", httpMethod = "GET")
  222. public Response<List<TextbookLibraryHistory>> listHistory(
  223. @RequestParam(required = true) String subject,
  224. HttpSession session) {
  225. User user = (User) shiroHelp.getLoginUser();
  226. if (user == null){
  227. throw new AuthException("请先登录");
  228. }
  229. if (!userServiceService.hasService(user.getId(), ServiceKey.TEXTBOOK)){
  230. throw new ParameterException("没有机经查看权限");
  231. }
  232. if (TextbookSubject.ValueOf(subject) == null){
  233. throw new ParameterException("科目错误");
  234. }
  235. TextbookLibrary library = textbookLibraryService.getLatest();
  236. List<TextbookLibraryHistory> p = textbookLibraryHistoryService.allByLibraryAndSubject(library.getId(), TextbookSubject.ValueOf(subject));
  237. textbookService.refreshHistoryResource(user, p);
  238. return ResponseHelp.success(p);
  239. }
  240. @RequestMapping(value = "/topic/no", method = RequestMethod.GET)
  241. @ApiOperation(value = "获取机经详情", notes = "根据机经序号获取题目", httpMethod = "GET")
  242. public Response<TextbookTopic> topic(
  243. @RequestParam(required = true) Integer libraryId,
  244. @RequestParam(required = true) String subject,
  245. @RequestParam(required = true) Integer no
  246. ) {
  247. User user = (User) shiroHelp.getLoginUser();
  248. if (user == null) {
  249. throw new AuthException("请先登录");
  250. }
  251. if (no == null || no == 0){
  252. no = 1;
  253. }
  254. TextbookTopic textbookTopic = textbookTopicService.getByNo(libraryId, subject, no);
  255. return ResponseHelp.success(textbookTopic);
  256. }
  257. @RequestMapping(value = "/topic/list", method = RequestMethod.GET)
  258. @ApiOperation(value = "机经列表", httpMethod = "GET")
  259. public Response<PageMessage<TextbookTopic>> listTopic(
  260. @RequestParam(required = false, defaultValue = "1") int page,
  261. @RequestParam(required = false, defaultValue = "100") int size,
  262. @RequestParam(required = false) boolean latest,
  263. @RequestParam(required = true) String subject,
  264. @RequestParam(required = false) String keyword,
  265. @RequestParam(required = false) String quality,
  266. @RequestParam(required = false) Boolean isOld,
  267. @RequestParam(required = false, defaultValue = "id") String order,
  268. @RequestParam(required = false, defaultValue = "desc") String direction,
  269. HttpSession session) {
  270. TextbookLibrary library;
  271. if (latest){
  272. User user = (User) shiroHelp.getLoginUser();
  273. if (user == null){
  274. throw new AuthException("请先登录");
  275. }
  276. if (!userServiceService.hasService(user.getId(), ServiceKey.TEXTBOOK)){
  277. throw new ParameterException("没有机经查看权限");
  278. }
  279. library = textbookLibraryService.getLatest();
  280. }else{
  281. // 获取往期:倒数第二
  282. library = textbookLibraryService.getSecond();
  283. }
  284. Page<TextbookTopic> p = textbookTopicService.list(page, size, library.getId(), TextbookSubject.ValueOf(subject), keyword, quality, isOld, order, DirectionStatus.ValueOf(direction));
  285. return ResponseHelp.success(p, page, size, p.getTotal());
  286. }
  287. @RequestMapping(value = "/paper/list", method = RequestMethod.GET)
  288. @ApiOperation(value = "机经组卷列表", httpMethod = "GET")
  289. public Response<List<UserTextbookPaperDto>> listPaper(
  290. @RequestParam(required = false, defaultValue = "1") int page,
  291. @RequestParam(required = false, defaultValue = "100") int size,
  292. @RequestParam(required = true) boolean latest,
  293. @RequestParam(required = true) String logic,
  294. @RequestParam(required = false) String year,
  295. @RequestParam(required = false) Integer times,
  296. HttpSession session) {
  297. User user = (User) shiroHelp.getLoginUser();
  298. TextbookLibrary library= null;
  299. if (latest){
  300. if (user == null){
  301. throw new AuthException("请先登录");
  302. }
  303. if (!userServiceService.hasService(user.getId(), ServiceKey.TEXTBOOK)){
  304. throw new ParameterException("请先开通本期机经");
  305. }
  306. library = textbookLibraryService.getLatest();
  307. }
  308. List<TextbookPaper> p = textbookPaperService.list(page, size, library != null ? library.getId():null, user != null ? user.getId():null, TextbookLogic.ValueOf(logic), year, times);
  309. List<UserTextbookPaperDto> pr = Transform.convert(p, UserTextbookPaperDto.class);
  310. // 获取试卷统计信息
  311. Map<Integer, Integer[]> questionNoIdsMap = new HashMap<>();
  312. for(TextbookPaper paper : p){
  313. questionNoIdsMap.put(paper.getId(), paper.getQuestionNoIds());
  314. }
  315. Map statMap = questionNoService.statPaperMap(questionNoIdsMap);
  316. Transform.combine(pr, statMap, UserTextbookPaperDto.class, "id", "stat");
  317. if (user != null){
  318. // 获取做题记录
  319. Collection ids = Transform.getIds(p, TextbookPaper.class, "id");
  320. List<UserPaper> userPaperList = userPaperService.listWithOrigin(user.getId(), PaperOrigin.TEXTBOOK, ids, null);
  321. Transform.combine(pr, userPaperList, UserTextbookPaperDto.class, "id", "paper", UserPaper.class, "originId", UserPaperBaseExtendDto.class);
  322. // 绑定userPaperId,用于关联report
  323. Map userPaperMap = Transform.getMap(userPaperList, UserPaper.class, "originId", "id");
  324. Transform.combine(pr, userPaperMap, UserTextbookPaperDto.class, "id", "userPaperId");
  325. // 获取最后一次作业结果
  326. Collection paperIds = Transform.getIds(userPaperList, UserPaper.class, "id");
  327. List<UserReport> reportList = userReportService.listWithLast(paperIds);
  328. Transform.combine(pr, reportList, UserTextbookPaperDto.class, "userPaperId", "report", UserReport.class, "paperId", UserReportExtendDto.class);
  329. }
  330. return ResponseHelp.success(pr);
  331. }
  332. @RequestMapping(value = "/subscribe", method = RequestMethod.POST)
  333. @ApiOperation(value = "订阅机经", notes = "订阅机经开关", httpMethod = "POST")
  334. public Response<Boolean> subscribe(@RequestBody @Validated TextbookSubscribeDto dto) {
  335. User user = (User) shiroHelp.getLoginUser();
  336. if (user == null){
  337. throw new AuthException("请先登录");
  338. }
  339. UserService userService = userServiceService.getServiceBase(user.getId(), ServiceKey.TEXTBOOK);
  340. if (userService == null){
  341. throw new ParameterException("无订阅权限");
  342. }
  343. userServiceService.edit(UserService.builder().id(userService.getId()).isSubscribe(dto.getSubscribe() ? 1 : 0).build());
  344. return ResponseHelp.success(true);
  345. }
  346. @RequestMapping(value = "/enroll", method = RequestMethod.POST)
  347. @ApiOperation(value = "报名", notes = "报名", httpMethod = "POST")
  348. public Response<Boolean> enroll(@RequestBody @Validated TextbookEnrollDto dto) {
  349. User user = (User) shiroHelp.getLoginUser();
  350. if (user == null){
  351. throw new AuthException("请先登录");
  352. }
  353. textbookService.enroll(user.getId(), dto.getDate());
  354. return ResponseHelp.success(true);
  355. }
  356. @RequestMapping(value = "/enroll/cancel", method = RequestMethod.POST)
  357. @ApiOperation(value = "取消报名", notes = "取消报名", httpMethod = "POST")
  358. public Response<Boolean> cancelEnroll() {
  359. User user = (User) shiroHelp.getLoginUser();
  360. if (user == null){
  361. throw new AuthException("请先登录");
  362. }
  363. textbookService.unEnroll(user.getId());
  364. return ResponseHelp.success(true);
  365. }
  366. @RequestMapping(value = "/enroll/list", method = RequestMethod.GET)
  367. @ApiOperation(value = "报名记录", notes = "报名记录", httpMethod = "GET")
  368. public Response<TextbookEnrollTimeDto> enrollList(
  369. @RequestParam(required = true) String startDate,
  370. @RequestParam(required = true) String endDate,
  371. HttpSession session) {
  372. User user = (User) shiroHelp.getLoginUser();
  373. Date end;
  374. Date start;
  375. try{
  376. SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
  377. end = sdf.parse(endDate);
  378. start = sdf.parse(startDate);
  379. }catch (Exception e){
  380. throw new ParameterException("日期格式错误");
  381. }
  382. Integer useNumber = toolsService.getTextbookUseNumber();
  383. if (useNumber == null){
  384. useNumber = 0;
  385. }
  386. TextbookEnrollTimeDto dto = new TextbookEnrollTimeDto();
  387. List<MonthNumberRelation> enrollRelation = userTextbookEnrollService.groupByMonth(startDate, endDate);
  388. Map<Integer, Integer> enrollMonthMap = new HashMap<>();
  389. for(MonthNumberRelation relation : enrollRelation){
  390. int month = relation.getMonth();
  391. enrollMonthMap.put(month, relation.getNumber());
  392. }
  393. List<MonthNumberRelation> recordRelation = userOrderRecordService.groupByMonth(startDate, endDate, ProductType.SERVICE, null, ServiceKey.TEXTBOOK);
  394. Map<Integer, Integer> recordMonthMap = new HashMap<>();
  395. for(MonthNumberRelation relation : recordRelation){
  396. int month = relation.getMonth();
  397. recordMonthMap.put(month, relation.getNumber());
  398. }
  399. // 获取用户报考日期
  400. if(user != null){
  401. UserTextbookEnroll enroll = userTextbookEnrollService.getByUser(user.getId());
  402. if (enroll != null){
  403. dto.setDate(enroll.getDate());
  404. }
  405. }
  406. List<TextbookEnrollTimeExtendDto> dtos = new ArrayList<>();
  407. while(start.before(end)){
  408. int month = Tools.monthNumber(start);
  409. int enrollNumber = enrollMonthMap.getOrDefault(month, 0);
  410. int recordNumber = recordMonthMap.getOrDefault(month, 0);
  411. TextbookEnrollTimeExtendDto extendDto = new TextbookEnrollTimeExtendDto();
  412. extendDto.setMonth(start);
  413. extendDto.setEnrollNumber(enrollNumber);
  414. extendDto.setUseNumber(recordNumber + useNumber);
  415. dtos.add(extendDto);
  416. start = Tools.addMonth(start, 1);
  417. }
  418. dto.setTimes(dtos);
  419. return ResponseHelp.success(dto);
  420. }
  421. }