TextbookController.java 19 KB

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