package com.ruoyi.web.controller.front; import cn.hutool.core.date.DateUtil; import cn.hutool.core.date.LocalDateTimeUtil; import cn.hutool.core.lang.Dict; import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; import com.google.common.collect.Lists; import com.ruoyi.common.core.content.VistorContextHolder; import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.domain.AjaxResult2; import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.enums.ExamType; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.dz.domain.DzControl; import com.ruoyi.dz.domain.DzSubject; import com.ruoyi.dz.service.IDzControlService; import com.ruoyi.dz.service.IDzSubjectService; import com.ruoyi.ie.domain.AEnrollUniversity; import com.ruoyi.ie.domain.AMarjorPlan; import com.ruoyi.ie.service.IAEnrollUniversityService; import com.ruoyi.ie.service.IAMarjorPlanService; import com.ruoyi.learn.domain.*; import com.ruoyi.learn.service.ILearnDirectedKnowledgeService; import com.ruoyi.learn.service.ILearnPlanService; import com.ruoyi.learn.service.ILearnPlanStudyService; import com.ruoyi.sy.service.ISyMajorService; import com.ruoyi.system.service.ISysUserService; import com.ruoyi.web.service.LearnStatService; import com.ruoyi.web.service.LearnTeacherService; import com.ruoyi.web.service.StudentService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.time.DateUtils; import org.springframework.web.bind.annotation.*; import javax.validation.ValidationException; import java.text.ParseException; import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.stream.Collectors; @RestController @RequestMapping("/front/student") @Api(tags = "前台-学习-学生") public class FrontStudentController extends BaseController { private final IDzControlService dzControlService; private final IAEnrollUniversityService universityService; private final ISyMajorService syMajorService; private final ISysUserService sysUserService; private final ILearnPlanService learnPlanService; private final ILearnPlanStudyService learnPlanStudyService; private final IAMarjorPlanService marjorPlanService; private final ILearnDirectedKnowledgeService learnDirectedKnowledgeService; private final StudentService studentService; private final IDzSubjectService dzSubjectService; private final LearnTeacherService learnTeacherService; private final LearnStatService learnStatService; public FrontStudentController(IDzControlService dzControlService, IAEnrollUniversityService universityService, ISyMajorService syMajorService, ISysUserService sysUserService, ILearnPlanService learnPlanService, ILearnPlanStudyService learnPlanStudyService, IAMarjorPlanService marjorPlanService, ILearnDirectedKnowledgeService learnDirectedKnowledgeService, StudentService studentService, IDzSubjectService dzSubjectService, LearnTeacherService learnTeacherService, LearnStatService learnStatService) { this.dzControlService = dzControlService; this.universityService = universityService; this.syMajorService = syMajorService; this.sysUserService = sysUserService; this.learnPlanService = learnPlanService; this.learnPlanStudyService = learnPlanStudyService; this.marjorPlanService = marjorPlanService; this.learnDirectedKnowledgeService = learnDirectedKnowledgeService; this.studentService = studentService; this.dzSubjectService = dzSubjectService; this.learnTeacherService = learnTeacherService; this.learnStatService = learnStatService; } @ApiOperation("02 全部科目") @GetMapping(value = "subject") public AjaxResult2> getSubject(@ApiParam("定向") @RequestParam(defaultValue = "false") boolean directed) { SysUser sysUser = SecurityUtils.getLoginUser().getUser(); DzSubject sCond = new DzSubject(); sCond.setLocations(sysUser.getLocation()); sCond.setExamTypes(sysUser.getExamType().name()); List list = dzSubjectService.selectDzSubjectList(sCond); return AjaxResult2.success(list); } @ApiOperation("试卷作业统计") @GetMapping("paperStats") public AjaxResult paperStats() { return AjaxResult.success(studentService.selectStatsForStudent(SecurityUtils.getUserId())); } @ApiOperation("试卷作业列表") @GetMapping("papers") public TableDataInfo papers(@ApiParam("status=1未做3正做4完成") Integer status) { startPage(); List list = studentService.selectLearnPaperForStudent(SecurityUtils.getUserId(), status); return getDataTable(list); } @ApiOperation("01 计划院校列表") @GetMapping(value = "university") public AjaxResult getUniversity() { DzControl dzControl = dzControlService.selectDzControl(VistorContextHolder.getContext()); AEnrollUniversity cond = new AEnrollUniversity(); cond.setYear(dzControl.getPlanYear()); return AjaxResult.success(universityService.selectAEnrollUniversityList(cond).stream().map( t -> JSONObject.of("universityId", t.getUniversityId(), "universityName", t.getUniversityName()) ).collect(Collectors.toList())); } @ApiOperation("02 计划院校专业及上级") @GetMapping(value = "university/major") public AjaxResult getUniversityMajor(@ApiParam("院校ID") Long universityId) { return AjaxResult.success(syMajorService.selectPlanMajorList(VistorContextHolder.getContext(), universityId)); } @ApiOperation("30 计划院校专业信息") @GetMapping("university/plan") public AjaxResult getUniversityPlan(@ApiParam("专业") Long planId) { AMarjorPlan mp = marjorPlanService.selectAMarjorPlanById(planId); LearnDirectedKnowledge cond = new LearnDirectedKnowledge(); String groupName = StringUtils.trimToEmpty(mp.getMajorGroup()); List result = null; if(StringUtils.isNotBlank(mp.getMajorName())) { cond.setDirectKey(mp.getYear() + "_" + mp.getUniversityId() + "_" + groupName + "_" + mp.getMajorName()); // 三级键 result = learnDirectedKnowledgeService.selectLearnDirectedKnowledgeList(cond); } if(CollectionUtils.isEmpty(result)) { cond.setDirectKey(mp.getYear() + "_" + mp.getUniversityId() + "_" + groupName); // 二级键 result = learnDirectedKnowledgeService.selectLearnDirectedKnowledgeList(cond); } if(CollectionUtils.isEmpty(result) && StringUtils.isNotBlank(groupName)) { cond.setDirectKey(mp.getYear() + "_" + mp.getUniversityId().toString()); // 一级键 result = learnDirectedKnowledgeService.selectLearnDirectedKnowledgeList(cond); } return CollectionUtils.isNotEmpty(result) ? AjaxResult.success(result.get(0)) : AjaxResult.error("无计划"); } @ApiOperation("03 查询学生定向院校") @GetMapping(value = "simulated/info") public AjaxResult getSimulateInfo() { JSONObject result = new JSONObject(); SysUser user = SecurityUtils.getLoginUser().getUser(); if(ExamType.OHS.name().equals(user.getUserType())) { result.put("subjects", Lists.newArrayList("职业技能", "语数外")); } else { result.put("subjects", Lists.newArrayList("职业技能")); } SysUser sysUser = sysUserService.selectUserById(SecurityUtils.getUserId()); result.put("evalCount", sysUser.getEvalCount()); return AjaxResult.success(result); } @ApiOperation("03 查询学生定向院校") @GetMapping(value = "directed/school") public AjaxResult getDirectionSchools() { SysUser user = sysUserService.selectUserById(SecurityUtils.getLoginUser().getUserId()); return AjaxResult.success(JSONArray.parse(user.getDirectedStudy())); } @ApiOperation("04 保存学生定向院校") @PostMapping(value = "directed/school") public AjaxResult saveStudySchool(@RequestBody JSONArray directionStudy) { SysUser user = new SysUser(); user.setUserId(SecurityUtils.getLoginUser().getUserId()); if(!directionStudy.isEmpty()) { JSONObject directed = directionStudy.getJSONObject(0); Long planId = directed.getLongValue("majorId"); Long universityId = directed.getLongValue("universityId"); directed.put("notice", learnTeacherService.updateDirected(user.getUserId(), universityId, planId)); } user.setDirectedStudy(directionStudy.toJSONString()); return sysUserService.updateUserProfile(user) > 0 ? AjaxResult.success("更新成功") : AjaxResult.success("无更新"); } @ApiOperation("10 查询学习计划") @GetMapping("plan") public AjaxResult getPlan() { return AjaxResult.success(learnPlanService.getCurrLearnPlan()); } @ApiOperation("11 保存学习计划") @PostMapping("plan") public AjaxResult savePlan(@RequestBody LearnPlan plan) { LearnPlan curr = learnPlanService.getCurrLearnPlan(); Date today = DateUtils.truncate(new Date(), Calendar.DATE); if(null != curr) { if(curr.getStatus().equals(1)) { if(DateUtils.isSameDay(curr.getBeginTime(), today)) { // 当天的更新计划 curr.setVideoTime(plan.getVideoTime()); curr.setQuestionCnt(plan.getQuestionCnt()); } else { curr.setStatus(0); } curr.setStudentId(null); curr.setBeginTime(null); curr.setStats(null); plan.setFirstTime(curr.getFirstTime()); learnPlanService.updateLearnPlan(curr); } if(curr.getStatus().equals(1)) { return AjaxResult.success(); } } else { plan.setFirstTime(today); } plan.setStudentId(SecurityUtils.getLoginUser().getUserId()); plan.setBeginTime(today); plan.setStatus(1); learnPlanService.insertLearnPlan(plan); return AjaxResult.success(); } @ApiOperation("10 查询学习计划统计") @GetMapping("plan/stats") public AjaxResult getPlanStats(@ApiParam String reportMonth) { LearnPlan curr = learnPlanService.getCurrLearnPlan(); if(null == curr) { throw new RuntimeException("未配置学习计划"); } // 统计每天的学习情况, 再汇总 LearnPlanStudy cond = new LearnPlanStudy(); cond.setStudentId(SecurityUtils.getLoginUser().getUserId()); try { cond.setReportDate(DateUtils.parseDate(reportMonth, "yyyy-MM-dd")); } catch (ParseException e) { throw new ValidationException("日期格式错误"); } List studyList = learnPlanStudyService.selectPlanStudyStats(cond); Integer doneDay = 0; Long videoTimes = 0L; Long questionCnt = 0L; List monthStudyList = Lists.newArrayList(); Date firstDate = null; JSONObject today = null; for(LearnPlanStudy study : studyList) { JSONObject planStudy = toStudyStats(study); if(DateUtils.isSameDay(cond.getReportDate(), study.getReportDate())) { today = planStudy; } boolean videoCompleted; if(null != study.getVideoCount()) { videoCompleted = study.getVideoCount() >= study.getVideoPlan(); } else { videoCompleted = study.getVideoPlan().equals(0); } if(null != study.getVideoTime()) { videoTimes += study.getVideoTime(); } boolean questionCompleted; if(null != study.getQuestionCount()) { questionCnt += study.getQuestionCount(); questionCompleted = study.getQuestionCount() >= study.getQuestionPlan(); } else { questionCompleted = study.getQuestionPlan().equals(0); } if(videoCompleted && questionCompleted) { doneDay++; } if(null == firstDate) { firstDate = study.getReportDate(); } monthStudyList.add(Dict.create().set("date", DateUtil.format(study.getReportDate(), "yyyy-MM-dd")).set("data", planStudy)); } Integer preDay = 0; // 同月的排队计划开始之前的 历史月不好计算,待定 TODO MF Date month = DateUtils.truncate(cond.getReportDate(), Calendar.MONTH); if(DateUtils.isSameDay(month, DateUtils.truncate(curr.getFirstTime(), Calendar.MONTH))) { Calendar cal = Calendar.getInstance(); cal.setTime(curr.getFirstTime()); preDay = cal.get(Calendar.DAY_OF_MONTH) - 1; } JSONObject stats = new JSONObject(); stats.put("firstDay", DateUtil.format(curr.getFirstTime(), "yyyy-MM-dd")); stats.put("preDay", preDay); stats.put("doneDay", doneDay); stats.put("undoneDay", LocalDateTimeUtil.of(DateUtils.addDays(DateUtils.addMonths(month, 1), -1)).getDayOfMonth() - doneDay - preDay); stats.put("videoTimes", videoTimes); stats.put("questionCnt", questionCnt); stats.put("studyList", monthStudyList); stats.put("today", today); return AjaxResult.success(stats); } private JSONObject toStudyStats(LearnPlanStudy todayStudy) { JSONObject study = new JSONObject(); study.put("questionPlan", todayStudy.getQuestionPlan()); study.put("videoPlan", todayStudy.getVideoPlan()); study.put("questionCnt", todayStudy.getQuestionCount()); study.put("videoTime", todayStudy.getVideoCount()); study.put("videoTimes", todayStudy.getVideoTime()); study.put("rightRate", Math.round((float)(todayStudy.getRightCount() * 100 / todayStudy.getQuestionCount()))); return study; } @ApiOperation("50 记录-知识点统计") @GetMapping("record/knowledge") public TableDataInfo getRecordKnowledge() { List list = learnStatService.getRecordKnowledge(SecurityUtils.getUserId()); return getDataTable(list); } @ApiOperation("51 记录-模拟卷") @GetMapping("record/simulated") public AjaxResult getRecordSimulated() { JSONObject data = JSONObject.of("name", "考试", "date", "2025-09-26 15:46", "total", 300, "score", 80, "rate", 82); List list = Lists.newArrayList(data); return AjaxResult.success(list); } @ApiOperation("52 记录-模拟卷结果") @GetMapping("record/simulated/{recordId}") public AjaxResult getSimulatedDetail(@ApiParam("记录ID") @PathVariable("recordId") Long recordId) { return AjaxResult.success(); } @ApiOperation("53 记录-测试卷") @GetMapping("record/test") public TableDataInfo getRecordTest() { JSONObject data = JSONObject.of("name", "考试", "date", "2025-09-26 15:46", "total", 300, "score", 80, "rate", 82); List list = Lists.newArrayList(data); return getDataTable(list); } @ApiOperation("54 记录-测试卷结果") @GetMapping("record/test/{recordId}") public AjaxResult getTestDetail(@ApiParam("记录ID") @PathVariable("recordId") Long recordId) { return AjaxResult.success(); } @ApiOperation("55 记录-计划刷题") @GetMapping("record/planStudy") public AjaxResult getRecordPlanStudy(@ApiParam Integer year, @ApiParam @RequestParam(required = false) Long month) { return AjaxResult.success(learnStatService.getRecordPlanStudy(SecurityUtils.getUserId(), year, month)); } @ApiOperation("56 记录-视频学习") @GetMapping("record/video") public AjaxResult getRecordVideo() { return AjaxResult.success(learnStatService.getRecordVideo(SecurityUtils.getUserId())); } }