kongzy
2024-06-26 daf7acb4f107a427e4a83ba1eb26e5e6012cbdaf
update
已修改52个文件
已添加16个文件
已删除2个文件
1735 ■■■■■ 文件已修改
.gitignore 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-admin/src/main/java/com/gkhy/exam/admin/app/AppExerciseAnswerController.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-admin/src/main/java/com/gkhy/exam/admin/app/AppPaperStudentController.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-admin/src/main/java/com/gkhy/exam/admin/app/AppPhaseStudentController.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-admin/src/main/java/com/gkhy/exam/admin/app/AppQuestionBankController.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-admin/src/main/java/com/gkhy/exam/admin/app/AppQuestionController.java 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-admin/src/main/java/com/gkhy/exam/admin/app/AppResourceController.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-admin/src/main/java/com/gkhy/exam/admin/app/AppStudentAnswerController.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-admin/src/main/java/com/gkhy/exam/admin/app/AppStudentStudyController.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-admin/src/main/java/com/gkhy/exam/admin/system/SysCarouselController.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-admin/src/main/java/com/gkhy/exam/admin/system/SysCategoryController.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-admin/src/main/java/com/gkhy/exam/admin/system/SysCommonController.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-admin/src/main/java/com/gkhy/exam/admin/system/SysCompanyController.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-admin/src/main/java/com/gkhy/exam/admin/system/SysDictDataController.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-admin/src/main/java/com/gkhy/exam/admin/system/SysDictTypeController.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-admin/src/main/java/com/gkhy/exam/admin/system/SysNoticeController.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-admin/src/main/java/com/gkhy/exam/admin/system/SysProfileController.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-admin/src/main/java/com/gkhy/exam/admin/system/SysUserController.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-admin/src/main/java/com/gkhy/exam/admin/web/ExCompanyPeriodController.java 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-admin/src/main/java/com/gkhy/exam/admin/web/ExCourseChapterController.java 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-admin/src/main/java/com/gkhy/exam/admin/web/ExCourseChapterPeriodController.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-admin/src/main/java/com/gkhy/exam/admin/web/ExCourseController.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-admin/src/main/java/com/gkhy/exam/admin/web/ExCoursePhaseController.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-admin/src/main/java/com/gkhy/exam/admin/web/ExExamPaperController.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-admin/src/main/java/com/gkhy/exam/admin/web/ExExamRecordController.java 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-admin/src/main/java/com/gkhy/exam/admin/web/ExPaperQuestionController.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-admin/src/main/java/com/gkhy/exam/admin/web/ExPaperStudentController.java 24 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-admin/src/main/java/com/gkhy/exam/admin/web/ExPhaseStudentController.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-admin/src/main/java/com/gkhy/exam/admin/web/ExQuestionBankController.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-admin/src/main/java/com/gkhy/exam/admin/web/ExQuestionController.java 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-admin/src/main/java/com/gkhy/exam/admin/web/ExResourceController.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-admin/src/main/java/com/gkhy/exam/admin/web/ExStatisticController.java 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-admin/src/main/java/com/gkhy/exam/admin/web/ExStudentAnswerController.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-admin/src/main/java/com/gkhy/exam/admin/web/ExStudentController.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-admin/src/main/java/com/gkhy/exam/admin/web/ExStudentStudyController.java 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-common/pom.xml 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-common/src/main/java/com/gkhy/exam/common/config/FilePathConfig.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-common/src/main/java/com/gkhy/exam/common/config/ThreadPoolConfig.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-common/src/main/java/com/gkhy/exam/common/enums/PhaseLevelEnum.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-common/src/main/java/com/gkhy/exam/common/utils/M3u8Utils.java 165 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-common/src/main/java/com/gkhy/exam/common/utils/MinioUtils.java 41 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-system/src/main/java/com/gkhy/exam/system/domain/ExExamRecord.java 97 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-system/src/main/java/com/gkhy/exam/system/domain/ExQuestion.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-system/src/main/java/com/gkhy/exam/system/domain/ExResource.java 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-system/src/main/java/com/gkhy/exam/system/domain/vo/CompanyPaperStudentVO.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-system/src/main/java/com/gkhy/exam/system/domain/vo/CompanyPhaseStudentVO.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-system/src/main/java/com/gkhy/exam/system/domain/vo/CompanyPhaseVO.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-system/src/main/java/com/gkhy/exam/system/domain/vo/CompanyStatisticVO.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-system/src/main/java/com/gkhy/exam/system/mapper/ExExamRecordMapper.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-system/src/main/java/com/gkhy/exam/system/mapper/SysCompanyMapper.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-system/src/main/java/com/gkhy/exam/system/service/ExExamRecordService.java 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-system/src/main/java/com/gkhy/exam/system/service/ExPaperStudentService.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-system/src/main/java/com/gkhy/exam/system/service/ExStatisticService.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-system/src/main/java/com/gkhy/exam/system/service/SysCommonService.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-system/src/main/java/com/gkhy/exam/system/service/impl/ExCourseServiceImpl.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-system/src/main/java/com/gkhy/exam/system/service/impl/ExExamPaperServiceImpl.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-system/src/main/java/com/gkhy/exam/system/service/impl/ExExamRecordServiceImpl.java 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-system/src/main/java/com/gkhy/exam/system/service/impl/ExPaperStudentServiceImpl.java 51 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-system/src/main/java/com/gkhy/exam/system/service/impl/ExQuestionBankServiceImpl.java 46 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-system/src/main/java/com/gkhy/exam/system/service/impl/ExQuestionServiceImpl.java 49 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-system/src/main/java/com/gkhy/exam/system/service/impl/ExResourceServiceImpl.java 53 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-system/src/main/java/com/gkhy/exam/system/service/impl/ExStatisticServiceImpl.java 108 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-system/src/main/java/com/gkhy/exam/system/service/impl/ExStudentServiceImpl.java 32 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-system/src/main/java/com/gkhy/exam/system/service/impl/SysCommonServiceImpl.java 113 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-system/src/main/resources/mapper/system/ExExamPaperMapper.xml 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-system/src/main/resources/mapper/system/ExExamRecordMapper.xml 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-system/src/main/resources/mapper/system/ExPaperStudentMapper.xml 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-system/src/main/resources/mapper/system/SysCompanyMapper.xml 102 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-system/src/test/java/com/gkhy/exam/system/MybatisPlusGenerator.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
pom.xml 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.gitignore
@@ -32,4 +32,5 @@
### VS Code ###
.vscode/
logs/
images/
images/
upload/
exam-admin/src/main/java/com/gkhy/exam/admin/app/AppExerciseAnswerController.java
@@ -7,6 +7,7 @@
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@@ -28,6 +29,7 @@
    @Autowired
    private ExExerciseAnswerService exerciseAnswerService;
    @PreAuthorize("hasAnyAuthority('train:exam:student')")
    @ApiOperation(value = "新增答题")
    @PostMapping
    public CommonResult add(@Validated @RequestBody ExExerciseAnswer exerciseAnswer){
exam-admin/src/main/java/com/gkhy/exam/admin/app/AppPaperStudentController.java
@@ -9,6 +9,7 @@
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
/**
@@ -26,6 +27,7 @@
    @Autowired
    private ExPaperStudentService paperStudentService;
    @PreAuthorize("hasAnyAuthority('train:exam:student')")
    @ApiOperation(value = "分页获取学员的试卷列表(分页)")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "pageNum", dataType = "int", required = false, value = "当前页,默认1"),
@@ -55,6 +57,7 @@
//    }
    @PreAuthorize("hasAnyAuthority('train:exam:student')")
    @ApiOperation(value = "结束考试")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "body", name = "paperId", dataType = "long", required = true, value = "试卷id"),
exam-admin/src/main/java/com/gkhy/exam/admin/app/AppPhaseStudentController.java
@@ -9,6 +9,7 @@
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@@ -29,6 +30,7 @@
    @Autowired
    private ExPhaseStudentService phaseStudentService;
    @PreAuthorize("hasAnyAuthority('train:exam:student')")
    @ApiOperation(value = "分页获取学员的批次列表(分页)")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "pageNum", dataType = "int", required = false, value = "当前页,默认1"),
@@ -39,6 +41,7 @@
        return CommonResult.success(phaseStudentService.selectPhaseStudentListForStudent(phaseStudent));
    }
    @PreAuthorize("hasAnyAuthority('train:exam:student')")
    @ApiOperation(value = "根据id查询学员批次信息")
    @GetMapping(value = { "/getPhaseStudentById" })
    public CommonResult getPhaseStudentById(@RequestParam(value = "phaseStudentId", required = true) Long phaseStudentId)
exam-admin/src/main/java/com/gkhy/exam/admin/app/AppQuestionBankController.java
@@ -1,6 +1,7 @@
package com.gkhy.exam.admin.app;
import com.gkhy.exam.common.annotation.RepeatSubmit;
import com.gkhy.exam.common.api.CommonResult;
import com.gkhy.exam.system.domain.ExQuestionBank;
import com.gkhy.exam.system.service.ExQuestionBankService;
@@ -9,6 +10,7 @@
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
/**
@@ -26,6 +28,7 @@
    @Autowired
    private ExQuestionBankService questionBankService;
    @PreAuthorize("hasAnyAuthority('train:exam:student')")
    @ApiOperation(value = "题库列表(分页)")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "pageNum", dataType = "int", required = false, value = "当前页,默认1"),
@@ -36,6 +39,7 @@
        return CommonResult.success(questionBankService.selectQuestionBankListForStudent(questionBank));
    }
    @PreAuthorize("hasAnyAuthority('train:exam:student')")
    @ApiOperation(value = "根据id获取题库信息")
    @GetMapping(value = { "/{bankId}" })
    public CommonResult getQuestionBankInfo(@PathVariable(value = "bankId", required = true) Long bankId)
@@ -43,6 +47,8 @@
        return CommonResult.success(questionBankService.selectQuestionBankByIdForStudent(bankId));
    }
    @RepeatSubmit
    @PreAuthorize("hasAnyAuthority('train:exam:student')")
    @ApiOperation(value = "清除刷题记录")
    @GetMapping(value = { "/clearExerciseRecord" })
    public CommonResult clearExerciseRecord(@RequestParam(value = "bankId", required = true) Long bankId)
exam-admin/src/main/java/com/gkhy/exam/admin/app/AppQuestionController.java
@@ -8,6 +8,7 @@
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@@ -30,7 +31,7 @@
    @Autowired
    private ExQuestionService questionService;
    @PreAuthorize("hasAnyAuthority('train:exam:student')")
    @ApiOperation(value = "刷题获取题目ID列表")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "bankId", dataType = "long", required = false, value = "题库id"),
@@ -42,7 +43,7 @@
        return CommonResult.success(questionService.getExerciseQuestionList(bankId,exerciseType));
    }
    @PreAuthorize("hasAnyAuthority('train:exam:student')")
    @ApiOperation(value = "刷题根据题目ID获取题目详情")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "questionId", dataType = "long", required = true, value = "题目id")
@@ -53,6 +54,7 @@
        return CommonResult.success(questionService.getExerciseQuestionById(questionId));
    }
    @PreAuthorize("hasAnyAuthority('train:exam:student')")
    @ApiOperation(value = "刷题根据题目ID列表批量获取题目详情")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "questionIds", dataType = "list", required = true, value = "题目id列表")
@@ -64,6 +66,7 @@
    }
    @PreAuthorize("hasAnyAuthority('train:exam:student')")
    @ApiOperation(value = "刷题获取错题题目ID列表")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "bankId", dataType = "long", required = false, value = "题库id")
@@ -75,6 +78,7 @@
    }
    @PreAuthorize("hasAnyAuthority('train:exam:student')")
    @ApiOperation(value = "考试获取题目ID列表(考试完成返回错对,未完成则不返回)")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "bankId", dataType = "long", required = false, value = "考卷id"),
@@ -86,6 +90,7 @@
        return CommonResult.success(questionService.getPaperQuestionList(paperId,viewType));
    }
    @PreAuthorize("hasAnyAuthority('train:exam:student')")
    @ApiOperation(value = "考试根据题目ID获取题目详情(考试完成返回答案,未完成则不返回)")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "paperId", dataType = "long", required = true, value = "试卷id"),
@@ -97,6 +102,7 @@
        return CommonResult.success(questionService.getPaperQuestionById(paperId,questionId));
    }
    @PreAuthorize("hasAnyAuthority('train:exam:student')")
    @ApiOperation(value = "考试根据题目ID列表批量获取题目详情")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "paperId", dataType = "long", required = true, value = "试卷id"),
exam-admin/src/main/java/com/gkhy/exam/admin/app/AppResourceController.java
@@ -6,6 +6,7 @@
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
/**
@@ -23,6 +24,7 @@
    @Autowired
    private ExResourceService resourceService;
    @PreAuthorize("hasAnyAuthority('train:exam:student')")
    @ApiOperation(value = "根据课时id获取资源信息")
    @GetMapping(value = { "/getResourceByPeriod" })
    public CommonResult getResourceByPeriod(@RequestParam(value = "periodId", required = true) Long periodId)
exam-admin/src/main/java/com/gkhy/exam/admin/app/AppStudentAnswerController.java
@@ -7,6 +7,7 @@
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@@ -28,6 +29,7 @@
    @Autowired
    private ExStudentAnswerService studentAnswerService;
    @PreAuthorize("hasAnyAuthority('train:exam:student')")
    @ApiOperation(value = "新增答题")
    @PostMapping
    public CommonResult add(@Validated @RequestBody ExStudentAnswer studentAnswer){
exam-admin/src/main/java/com/gkhy/exam/admin/app/AppStudentStudyController.java
@@ -9,6 +9,7 @@
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@@ -27,12 +28,14 @@
    @Autowired
    private ExStudentStudyService studentStudyService;
    @PreAuthorize("hasAnyAuthority('train:exam:student')")
    @ApiOperation(value = "新增学习记录")
    @PostMapping
    public CommonResult add(@Validated @RequestBody ExStudentStudy studentStudy){
        return CommonResult.success(studentStudyService.insertStudentStudy(studentStudy));
    }
    @PreAuthorize("hasAnyAuthority('train:exam:student')")
    @ApiOperation(value = "上报学习进度")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "body", name = "id", dataType = "long", required = true, value = "学习记录id"),
exam-admin/src/main/java/com/gkhy/exam/admin/system/SysCarouselController.java
@@ -2,6 +2,7 @@
import com.gkhy.exam.common.annotation.Log;
import com.gkhy.exam.common.annotation.RepeatSubmit;
import com.gkhy.exam.common.api.CommonResult;
import com.gkhy.exam.common.enums.BusinessType;
import com.gkhy.exam.system.domain.SysCarousel;
@@ -47,6 +48,7 @@
        return CommonResult.success(carouselService.selectCarouselById(carouselId));
    }
    @RepeatSubmit
    @PreAuthorize("hasAnyAuthority('train:exam:system')")
    @Log(title = "轮播图管理", businessType = BusinessType.INSERT)
    @ApiOperation(value = "新增轮播图")
@@ -55,6 +57,7 @@
        return CommonResult.success(carouselService.insertCarousel(carousel));
    }
    @RepeatSubmit
    @PreAuthorize("hasAnyAuthority('train:exam:system')")
    @Log(title = "轮播图管理", businessType = BusinessType.UPDATE)
    @ApiOperation(value = "编辑轮播图")
@@ -63,6 +66,7 @@
        return CommonResult.success(carouselService.updateCarousel(carousel));
    }
    @RepeatSubmit
    @PreAuthorize("hasAnyAuthority('train:exam:system')")
    @Log(title = "轮播图管理", businessType = BusinessType.DELETE)
    @ApiOperation(value = "删除轮播图")
exam-admin/src/main/java/com/gkhy/exam/admin/system/SysCategoryController.java
@@ -2,6 +2,7 @@
import com.gkhy.exam.common.annotation.Log;
import com.gkhy.exam.common.annotation.RepeatSubmit;
import com.gkhy.exam.common.api.CommonResult;
import com.gkhy.exam.common.enums.BusinessType;
import com.gkhy.exam.system.domain.SysCategory;
@@ -39,6 +40,7 @@
        return CommonResult.success(categoryService.selectCategoryById(categoryId));
    }
    @RepeatSubmit
    @Log(title = "课程分类管理", businessType = BusinessType.INSERT)
    @ApiOperation(value = "新增课程分类")
    @PostMapping
@@ -46,6 +48,7 @@
        return CommonResult.success(categoryService.insertCategory(category));
    }
    @RepeatSubmit
    @Log(title = "课程分类管理", businessType = BusinessType.UPDATE)
    @ApiOperation(value = "编辑课程分类")
    @PutMapping
@@ -53,6 +56,7 @@
        return CommonResult.success(categoryService.updateCategory(category));
    }
    @RepeatSubmit
    @Log(title = "课程分类管理", businessType = BusinessType.UPDATE)
    @ApiOperation(value = "删除课程分类")
    @DeleteMapping(value = { "/{categoryId}" })
exam-admin/src/main/java/com/gkhy/exam/admin/system/SysCommonController.java
@@ -1,5 +1,6 @@
package com.gkhy.exam.admin.system;
import com.gkhy.exam.common.annotation.RepeatSubmit;
import com.gkhy.exam.common.api.CommonResult;
import com.gkhy.exam.system.domain.vo.UploadObjectVO;
import com.gkhy.exam.system.service.SysCommonService;
@@ -16,6 +17,7 @@
    @Autowired
    private SysCommonService commonService;
    @RepeatSubmit
    @ApiOperation(value = "上传图片/文件")
    @PostMapping("/uploadFile")
    public CommonResult<UploadObjectVO> uploadFile(MultipartFile file){
@@ -30,4 +32,16 @@
    }
    /**
     * 整个文件上传
     * 上传视频文件转m3u8
     *@param file 文件
     *@return  String: 路径
     */
    @PostMapping("/uploadVideo")
    public CommonResult uploadVideo(@RequestPart("file") MultipartFile file) throws Exception { ;
        return CommonResult.success(commonService.uploadVideo2M3u8(file));
    }
}
exam-admin/src/main/java/com/gkhy/exam/admin/system/SysCompanyController.java
@@ -2,6 +2,7 @@
import com.gkhy.exam.common.annotation.Log;
import com.gkhy.exam.common.annotation.RepeatSubmit;
import com.gkhy.exam.common.api.CommonResult;
import com.gkhy.exam.common.enums.BusinessType;
import com.gkhy.exam.system.domain.SysCompany;
@@ -49,6 +50,7 @@
        return CommonResult.success(companyService.selectCompanyById(companyId));
    }
    @RepeatSubmit
    @PreAuthorize("hasAnyAuthority('train:exam:system')")
    @Log(title = "企业管理", businessType = BusinessType.INSERT)
    @ApiOperation(value = "新增企业")
@@ -57,6 +59,7 @@
        return CommonResult.success(companyService.insertCompany(company));
    }
    @RepeatSubmit
    @PreAuthorize("hasAnyAuthority('train:exam:system')")
    @Log(title = "企业管理", businessType = BusinessType.UPDATE)
    @ApiOperation(value = "编辑企业")
@@ -65,6 +68,7 @@
        return CommonResult.success(companyService.updateCompany(company));
    }
    @RepeatSubmit
    @PreAuthorize("hasAnyAuthority('train:exam:system')")
    @Log(title = "企业管理", businessType = BusinessType.UPDATE)
    @ApiOperation(value = "删除企业")
@@ -73,6 +77,7 @@
        return CommonResult.success(companyService.deleteCompanyById(companyId));
    }
    @RepeatSubmit
    @PreAuthorize("hasAnyAuthority('train:exam:system')")
    @Log(title = "企业管理", businessType = BusinessType.INSERT)
    @ApiOperation(value = "企业分配课时")
exam-admin/src/main/java/com/gkhy/exam/admin/system/SysDictDataController.java
@@ -1,6 +1,7 @@
package com.gkhy.exam.admin.system;
import com.gkhy.exam.common.annotation.Log;
import com.gkhy.exam.common.annotation.RepeatSubmit;
import com.gkhy.exam.common.api.CommonResult;
import com.gkhy.exam.common.domain.entity.SysDictData;
import com.gkhy.exam.common.enums.BusinessType;
@@ -42,6 +43,7 @@
    }
    @RepeatSubmit
    @PreAuthorize("hasAnyAuthority('train:exam:system')")
    @Log(title = "字典数据", businessType = BusinessType.INSERT)
    @ApiOperation(value = "新增字典数据")
@@ -50,6 +52,7 @@
        return CommonResult.success(dictDataServic.insertDictData(dictData));
    }
    @RepeatSubmit
    @PreAuthorize("hasAnyAuthority('train:exam:system')")
    @Log(title = "字典数据", businessType = BusinessType.UPDATE)
    @ApiOperation(value = "编辑字典数据")
@@ -58,6 +61,7 @@
        return CommonResult.success(dictDataServic.updateDictData(dictData));
    }
    @RepeatSubmit
    @PreAuthorize("hasAnyAuthority('train:exam:system')")
    @Log(title = "字典类型", businessType = BusinessType.DELETE)
    @ApiOperation(value = "删除字典数据")
exam-admin/src/main/java/com/gkhy/exam/admin/system/SysDictTypeController.java
@@ -1,6 +1,7 @@
package com.gkhy.exam.admin.system;
import com.gkhy.exam.common.annotation.Log;
import com.gkhy.exam.common.annotation.RepeatSubmit;
import com.gkhy.exam.common.api.CommonResult;
import com.gkhy.exam.common.domain.entity.SysDictType;
import com.gkhy.exam.common.enums.BusinessType;
@@ -33,6 +34,7 @@
        return CommonResult.success(dictTypeService.selectDictTypeById(dictId));
    }
    @RepeatSubmit
    @PreAuthorize("hasAnyAuthority('train:exam:system')")
    @Log(title = "字典类型", businessType = BusinessType.INSERT)
    @ApiOperation(value = "新增字典类型")
@@ -41,6 +43,7 @@
        return CommonResult.success(dictTypeService.insertDictType(dictType));
    }
    @RepeatSubmit
    @PreAuthorize("hasAnyAuthority('train:exam:system')")
    @Log(title = "字典类型", businessType = BusinessType.UPDATE)
    @ApiOperation(value = "编辑字典类型")
@@ -49,6 +52,7 @@
        return CommonResult.success(dictTypeService.updateDictType(dictType));
    }
    @RepeatSubmit
    @PreAuthorize("hasAnyAuthority('train:exam:system')")
    @Log(title = "字典类型", businessType = BusinessType.DELETE)
    @ApiOperation(value = "删除字典类型")
@@ -58,6 +62,7 @@
        return CommonResult.success();
    }
    @RepeatSubmit
    @Log(title = "字典类型", businessType = BusinessType.CLEAN)
    @ApiOperation(value = "刷新缓存")
    @DeleteMapping("/refreshCache")
exam-admin/src/main/java/com/gkhy/exam/admin/system/SysNoticeController.java
@@ -1,6 +1,7 @@
package com.gkhy.exam.admin.system;
import com.gkhy.exam.common.annotation.Log;
import com.gkhy.exam.common.annotation.RepeatSubmit;
import com.gkhy.exam.common.api.CommonResult;
import com.gkhy.exam.common.enums.BusinessType;
import com.gkhy.exam.system.domain.SysNotice;
@@ -34,6 +35,7 @@
    }
    @RepeatSubmit
    @Log(title = "通知公告", businessType = BusinessType.INSERT)
    @ApiOperation(value = "新增通知公告")
    @PostMapping
@@ -42,6 +44,7 @@
        return CommonResult.success(noticeService.insertNotice(notice));
    }
    @RepeatSubmit
    @Log(title = "通知公告", businessType = BusinessType.UPDATE)
    @ApiOperation(value = "修改通知公告")
    @PutMapping
@@ -50,6 +53,7 @@
        return CommonResult.success(noticeService.updateNotice(notice));
    }
    @RepeatSubmit
    @Log(title = "通知公告", businessType = BusinessType.DELETE)
    @ApiOperation(value = "删除通知公告")
    @DeleteMapping("/{noticeIds}")
exam-admin/src/main/java/com/gkhy/exam/admin/system/SysProfileController.java
@@ -2,6 +2,7 @@
import cn.hutool.core.codec.Base64;
import com.gkhy.exam.common.annotation.Log;
import com.gkhy.exam.common.annotation.RepeatSubmit;
import com.gkhy.exam.common.api.CommonResult;
import com.gkhy.exam.common.domain.entity.SysUser;
import com.gkhy.exam.common.enums.BusinessType;
@@ -33,6 +34,7 @@
        return CommonResult.success(user);
    }
    @RepeatSubmit
    @Log(title = "个人信息", businessType = BusinessType.UPDATE)
    @PutMapping
    public CommonResult updateProfile(@RequestBody SysUser user)
@@ -54,6 +56,7 @@
        throw new ApiException("修改个人信息异常,请联系管理员");
    }
    @RepeatSubmit
    @Log(title = "个人信息", businessType = BusinessType.UPDATE)
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "body", name = "oldPassword", dataType = "String", required = true, value = "旧密码"),
exam-admin/src/main/java/com/gkhy/exam/admin/system/SysUserController.java
@@ -1,6 +1,7 @@
package com.gkhy.exam.admin.system;
import com.gkhy.exam.common.annotation.Log;
import com.gkhy.exam.common.annotation.RepeatSubmit;
import com.gkhy.exam.common.api.CommonResult;
import com.gkhy.exam.common.domain.entity.SysUser;
import com.gkhy.exam.common.enums.BusinessType;
@@ -41,6 +42,7 @@
    }
    @RepeatSubmit
    @Log(title = "用户管理", businessType = BusinessType.INSERT)
    @ApiOperation(value = "新增用户")
    @PostMapping
@@ -49,6 +51,7 @@
    }
    @RepeatSubmit
    @Log(title = "用户管理", businessType = BusinessType.UPDATE)
    @ApiOperation(value = "编辑用户")
    @PutMapping
@@ -57,6 +60,7 @@
    }
    @RepeatSubmit
    @Log(title = "用户管理", businessType = BusinessType.DELETE)
    @ApiOperation(value = "删除用户")
    @PutMapping("/{userId}")
@@ -65,6 +69,7 @@
    }
    @RepeatSubmit
    @Log(title = "用户管理", businessType = BusinessType.UPDATE)
    @ApiOperation(value = "重置密码")
    @PutMapping(value = "/resetPwd")
@@ -73,6 +78,7 @@
        return CommonResult.success();
    }
    @RepeatSubmit
    @Log(title = "用户管理", businessType = BusinessType.UPDATE)
    @ApiOperation(value = "修改用户状态")
    @PutMapping(value = "/changeStatus")
exam-admin/src/main/java/com/gkhy/exam/admin/web/ExCompanyPeriodController.java
@@ -2,6 +2,7 @@
import com.gkhy.exam.common.annotation.Log;
import com.gkhy.exam.common.annotation.RepeatSubmit;
import com.gkhy.exam.common.api.CommonResult;
import com.gkhy.exam.common.enums.BusinessType;
import com.gkhy.exam.system.domain.ExCompanyPeriod;
@@ -39,25 +40,11 @@
    }
    @RepeatSubmit
    @Log(title = "企业课时变更记录管理", businessType = BusinessType.UPDATE)
    @ApiOperation(value = "删除企业课时变更记录")
    @DeleteMapping(value = { "/{periodId}" })
    public CommonResult delete(@PathVariable(value = "periodId", required = true) Long periodId){
        return CommonResult.success(companyPeriodService.deleteCompanyPeriodById(periodId));
    }
    /**
     * <p>
     * 题库表 前端控制器
     * </p>
     *
     * @author kzy
     * @since 2024-06-18 10:09:52
     */
    @RestController
    @RequestMapping("/system/ex-question-bank")
    public static class ExQuestionBankController {
    }
}
exam-admin/src/main/java/com/gkhy/exam/admin/web/ExCourseChapterController.java
@@ -2,6 +2,7 @@
import com.gkhy.exam.common.annotation.Log;
import com.gkhy.exam.common.annotation.RepeatSubmit;
import com.gkhy.exam.common.api.CommonResult;
import com.gkhy.exam.common.enums.BusinessType;
import com.gkhy.exam.system.domain.ExCourseChapter;
@@ -47,7 +48,7 @@
        return CommonResult.success(courseChapterService.selectChapterById(chapterId));
    }
    @RepeatSubmit
    @Log(title = "课程章节管理", businessType = BusinessType.INSERT)
    @ApiOperation(value = "新增章节")
    @PostMapping
@@ -55,6 +56,7 @@
        return CommonResult.success(courseChapterService.insertChapter(courseChapter));
    }
    @RepeatSubmit
    @Log(title = "课程章节管理", businessType = BusinessType.UPDATE)
    @ApiOperation(value = "编辑章节")
    @PutMapping
@@ -62,6 +64,7 @@
        return CommonResult.success(courseChapterService.updateChapter(courseChapter));
    }
    @RepeatSubmit
    @Log(title = "课程章节管理", businessType = BusinessType.UPDATE)
    @ApiOperation(value = "删除章节")
    @DeleteMapping(value = { "/{chapterId}" })
exam-admin/src/main/java/com/gkhy/exam/admin/web/ExCourseChapterPeriodController.java
@@ -2,6 +2,7 @@
import com.gkhy.exam.common.annotation.Log;
import com.gkhy.exam.common.annotation.RepeatSubmit;
import com.gkhy.exam.common.api.CommonResult;
import com.gkhy.exam.common.enums.BusinessType;
import com.gkhy.exam.system.domain.ExCourseChapterPeriod;
@@ -46,6 +47,7 @@
        return CommonResult.success(courseChapterPeriodService.selectPeriodById(periodId));
    }
    @RepeatSubmit
    @Log(title = "课时管理", businessType = BusinessType.INSERT)
    @ApiOperation(value = "新增课时")
    @PostMapping
@@ -53,6 +55,7 @@
        return CommonResult.success(courseChapterPeriodService.insertPeriod(chapterPeriod));
    }
    @RepeatSubmit
    @Log(title = "课时管理", businessType = BusinessType.UPDATE)
    @ApiOperation(value = "编辑课时")
    @PutMapping
@@ -60,6 +63,7 @@
        return CommonResult.success(courseChapterPeriodService.updatePeriod(chapterPeriod));
    }
    @RepeatSubmit
    @Log(title = "课时管理", businessType = BusinessType.UPDATE)
    @ApiOperation(value = "删除课时")
    @DeleteMapping(value = { "/{periodId}" })
exam-admin/src/main/java/com/gkhy/exam/admin/web/ExCourseController.java
@@ -2,6 +2,7 @@
import com.gkhy.exam.common.annotation.Log;
import com.gkhy.exam.common.annotation.RepeatSubmit;
import com.gkhy.exam.common.api.CommonResult;
import com.gkhy.exam.common.enums.BusinessType;
import com.gkhy.exam.system.domain.ExCourse;
@@ -50,6 +51,7 @@
        return CommonResult.success(courseService.selectApproveCourseList(course));
    }
    @RepeatSubmit
    @ApiOperation(value = "课程审批")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "body", name = "id", dataType = "long", required = true, value = "课程id"),
@@ -68,6 +70,7 @@
        return CommonResult.success(courseService.selectCourseById(courseId));
    }
    @RepeatSubmit
    @Log(title = "课程管理", businessType = BusinessType.INSERT)
    @ApiOperation(value = "新增课程")
    @PostMapping
@@ -75,6 +78,7 @@
        return CommonResult.success(courseService.insertCourse(course));
    }
    @RepeatSubmit
    @Log(title = "课程管理", businessType = BusinessType.UPDATE)
    @ApiOperation(value = "编辑课程")
    @PutMapping
@@ -82,6 +86,7 @@
        return CommonResult.success(courseService.updateCourse(course));
    }
    @RepeatSubmit
    @Log(title = "课程管理", businessType = BusinessType.UPDATE)
    @ApiOperation(value = "删除课程")
    @DeleteMapping(value = { "/{courseId}" })
exam-admin/src/main/java/com/gkhy/exam/admin/web/ExCoursePhaseController.java
@@ -2,6 +2,7 @@
import com.gkhy.exam.common.annotation.Log;
import com.gkhy.exam.common.annotation.RepeatSubmit;
import com.gkhy.exam.common.api.CommonResult;
import com.gkhy.exam.common.enums.BusinessType;
import com.gkhy.exam.system.domain.ExCoursePhase;
@@ -47,6 +48,7 @@
        return CommonResult.success(coursePhaseService.selectCoursePhaseById(phaseId));
    }
    @RepeatSubmit
    @Log(title = "批次管理", businessType = BusinessType.INSERT)
    @ApiOperation(value = "新增批次")
    @PostMapping
@@ -54,6 +56,7 @@
        return CommonResult.success(coursePhaseService.insertCoursePhase(coursePhase));
    }
    @RepeatSubmit
    @Log(title = "批次管理", businessType = BusinessType.UPDATE)
    @ApiOperation(value = "编辑批次")
    @PutMapping
@@ -61,6 +64,7 @@
        return CommonResult.success(coursePhaseService.updateCoursePhase(coursePhase));
    }
    @RepeatSubmit
    @Log(title = "批次管理", businessType = BusinessType.UPDATE)
    @ApiOperation(value = "删除批次")
    @DeleteMapping(value = { "/{phaseId}" })
exam-admin/src/main/java/com/gkhy/exam/admin/web/ExExamPaperController.java
@@ -2,6 +2,7 @@
import com.gkhy.exam.common.annotation.Log;
import com.gkhy.exam.common.annotation.RepeatSubmit;
import com.gkhy.exam.common.api.CommonResult;
import com.gkhy.exam.common.enums.BusinessType;
import com.gkhy.exam.system.domain.ExExamPaper;
@@ -46,6 +47,7 @@
        return CommonResult.success(examPaperService.selectExamPaperById(paperId));
    }
    @RepeatSubmit
    @Log(title = "试卷管理", businessType = BusinessType.INSERT)
    @ApiOperation(value = "新增试卷")
    @PostMapping
@@ -53,6 +55,7 @@
        return CommonResult.success(examPaperService.insertExamPaper(examPaper));
    }
    @RepeatSubmit
    @Log(title = "试卷管理", businessType = BusinessType.UPDATE)
    @ApiOperation(value = "编辑试卷")
    @PutMapping
@@ -60,6 +63,7 @@
        return CommonResult.success(examPaperService.updateExamPaper(examPaper));
    }
    @RepeatSubmit
    @Log(title = "试卷管理", businessType = BusinessType.UPDATE)
    @ApiOperation(value = "删除试卷")
    @DeleteMapping(value = { "/{paperId}" })
@@ -74,6 +78,7 @@
        return CommonResult.success(examPaperService.checkNameUnique(examPaper));
    }
    @RepeatSubmit
    @Log(title = "试卷管理", businessType = BusinessType.UPDATE)
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "body", name = "id", dataType = "long", required = false, value = "试卷id"),
exam-admin/src/main/java/com/gkhy/exam/admin/web/ExExamRecordController.java
对比新文件
@@ -0,0 +1,73 @@
package com.gkhy.exam.admin.web;
import com.gkhy.exam.common.annotation.Log;
import com.gkhy.exam.common.annotation.RepeatSubmit;
import com.gkhy.exam.common.api.CommonResult;
import com.gkhy.exam.common.enums.BusinessType;
import com.gkhy.exam.system.domain.ExExamRecord;
import com.gkhy.exam.system.service.ExExamRecordService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
/**
 * <p>
 * 线下教育登记表 前端控制器
 * </p>
 *
 * @author kzy
 * @since 2024-06-24 16:16:33
 */
@Api(tags = "线下教育登记前端控制器")
@RestController
@RequestMapping("/exam-record")
public class ExExamRecordController {
    @Autowired
    private ExExamRecordService examRecordService;
    @ApiOperation(value = "登记列表(分页)")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "pageNum", dataType = "int", required = false, value = "当前页,默认1"),
            @ApiImplicitParam(paramType = "query", name = "pageSize", dataType = "int", required = false, value = "每页数目,默认10")
    })
    @GetMapping("/list")
    public CommonResult list(ExExamRecord examRecord){
        return CommonResult.success(examRecordService.selectExamRecordList(examRecord));
    }
    @ApiOperation(value = "根据id获取登记信息")
    @GetMapping(value = { "/{recordId}" })
    public CommonResult getExamRecordInfo(@PathVariable(value = "recordId", required = true) Long recordId)
    {
        return CommonResult.success(examRecordService.selectExamRecordById(recordId));
    }
    @RepeatSubmit
    @Log(title = "线下教育登记管理", businessType = BusinessType.INSERT)
    @ApiOperation(value = "新增登记")
    @PostMapping
    public CommonResult add(@Validated @RequestBody ExExamRecord examRecord){
        return CommonResult.success(examRecordService.insertExamRecord(examRecord));
    }
    @RepeatSubmit
    @Log(title = "线下教育登记管理", businessType = BusinessType.UPDATE)
    @ApiOperation(value = "编辑登记")
    @PutMapping
    public CommonResult edit(@Validated @RequestBody ExExamRecord examRecord){
        return CommonResult.success(examRecordService.updateExamRecord(examRecord));
    }
    @RepeatSubmit
    @Log(title = "线下教育登记管理", businessType = BusinessType.DELETE)
    @ApiOperation(value = "删除登记")
    @DeleteMapping(value = { "/{recordId}" })
    public CommonResult delete(@PathVariable(value = "recordId", required = true) Long recordId){
        return CommonResult.success(examRecordService.deleteExamRecordById(recordId));
    }
}
exam-admin/src/main/java/com/gkhy/exam/admin/web/ExPaperQuestionController.java
文件已删除
exam-admin/src/main/java/com/gkhy/exam/admin/web/ExPaperStudentController.java
@@ -2,6 +2,7 @@
import com.gkhy.exam.common.annotation.Log;
import com.gkhy.exam.common.annotation.RepeatSubmit;
import com.gkhy.exam.common.api.CommonResult;
import com.gkhy.exam.common.enums.BusinessType;
import com.gkhy.exam.system.domain.ExPaperStudent;
@@ -16,6 +17,7 @@
import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
 * <p>
@@ -35,13 +37,15 @@
    @ApiOperation(value = "考卷下的学员列表(分页)")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "pageNum", dataType = "int", required = false, value = "当前页,默认1"),
            @ApiImplicitParam(paramType = "query", name = "pageSize", dataType = "int", required = false, value = "每页数目,默认10")
            @ApiImplicitParam(paramType = "query", name = "pageSize", dataType = "int", required = false, value = "每页数目,默认10"),
            @ApiImplicitParam(paramType = "query", name = "paperId", dataType = "long", required = true, value = "考卷id")
    })
    @GetMapping("/list")
    public CommonResult list(ExPaperStudent paperStudent){
        return CommonResult.success(paperStudentService.selectPaperStudentList(paperStudent));
    }
    @RepeatSubmit
    @Log(title = "试卷与学员关系管理", businessType = BusinessType.INSERT)
    @ApiOperation(value = "新增学员")
    @PostMapping
@@ -49,21 +53,29 @@
        return CommonResult.success(paperStudentService.addPaperStudent(paperStudent));
    }
    @Log(title = "试卷与学员关系管理", businessType = BusinessType.UPDATE)
    @RepeatSubmit
    @Log(title = "试卷与学员关系管理", businessType = BusinessType.INSERT)
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "body", name = "phaseIds", dataType = "array", required = false, value = "批次id列表"),
            @ApiImplicitParam(paramType = "query", name = "studentIds", dataType = "array", required = false, value = "学员id列表(批次id和学员id列表只能传一个)"),
            @ApiImplicitParam(paramType = "query", name = "paperId", dataType = "long", required = true, value = "考卷id")
    })
    @ApiOperation(value = "批量新增学员")
    @PostMapping("/batchAdd")
    public CommonResult batchAdd(@Validated @RequestBody List<ExPaperStudent> paperStudents){
        return CommonResult.success(paperStudentService.batchAddPaperStudent(paperStudents));
    public CommonResult batchAdd(@RequestBody Map<String,Object> paperStudentMap){
        return CommonResult.success(paperStudentService.batchAddPaperStudent(paperStudentMap));
    }
    @Log(title = "试卷与学员关系管理", businessType = BusinessType.UPDATE)
    @RepeatSubmit
    @Log(title = "试卷与学员关系管理", businessType = BusinessType.DELETE)
    @ApiOperation(value = "删除学员")
    @DeleteMapping(value = { "/{phaseStudentId}" })
    public CommonResult delete(@PathVariable(value = "phaseStudentId", required = true) Long paperStudentId){
        return CommonResult.success(paperStudentService.deletePaperStudent(paperStudentId));
    }
    @Log(title = "试卷与学员关系管理", businessType = BusinessType.UPDATE)
    @RepeatSubmit
    @Log(title = "试卷与学员关系管理", businessType = BusinessType.DELETE)
    @ApiOperation(value = "批量删除学员")
    @DeleteMapping(value = { "/batchDelete" })
    public CommonResult batchDelete( List<Long> paperStudentIds){
exam-admin/src/main/java/com/gkhy/exam/admin/web/ExPhaseStudentController.java
@@ -2,6 +2,7 @@
import com.gkhy.exam.common.annotation.Log;
import com.gkhy.exam.common.annotation.RepeatSubmit;
import com.gkhy.exam.common.api.CommonResult;
import com.gkhy.exam.common.enums.BusinessType;
import com.gkhy.exam.system.domain.ExPhaseStudent;
@@ -43,6 +44,7 @@
        return CommonResult.success(phaseStudentService.selectPhaseStudentList(phaseStudent));
    }
    @RepeatSubmit
    @Log(title = "批次与学员关系管理", businessType = BusinessType.INSERT)
    @ApiOperation(value = "新增学员")
    @PostMapping
@@ -50,6 +52,7 @@
        return CommonResult.success(phaseStudentService.addPhaseStudent(phaseStudent));
    }
    @RepeatSubmit
    @Log(title = "批次与学员关系管理", businessType = BusinessType.UPDATE)
    @ApiOperation(value = "批量新增学员")
    @PostMapping("/batchAdd")
@@ -57,6 +60,7 @@
        return CommonResult.success(phaseStudentService.batchAddPhaseStudent(phaseStudents));
    }
    @RepeatSubmit
    @Log(title = "批次与学员关系管理", businessType = BusinessType.UPDATE)
    @ApiOperation(value = "删除学员")
    @DeleteMapping(value = { "/{phaseStudentId}" })
@@ -64,6 +68,7 @@
        return CommonResult.success(phaseStudentService.deletePhaseStudent(phaseStudentId));
    }
    @RepeatSubmit
    @Log(title = "批次与学员关系管理", businessType = BusinessType.UPDATE)
    @ApiOperation(value = "批量删除学员")
    @DeleteMapping(value = { "/batchDelete" })
exam-admin/src/main/java/com/gkhy/exam/admin/web/ExQuestionBankController.java
@@ -2,6 +2,7 @@
import com.gkhy.exam.common.annotation.Log;
import com.gkhy.exam.common.annotation.RepeatSubmit;
import com.gkhy.exam.common.api.CommonResult;
import com.gkhy.exam.common.enums.BusinessType;
import com.gkhy.exam.system.domain.ExQuestionBank;
@@ -46,6 +47,7 @@
        return CommonResult.success(questionBankService.selectQuestionBankById(bankId));
    }
    @RepeatSubmit
    @Log(title = "题库管理", businessType = BusinessType.INSERT)
    @ApiOperation(value = "新增题库")
    @PostMapping
@@ -53,6 +55,7 @@
        return CommonResult.success(questionBankService.insertQuestionBank(questionBank));
    }
    @RepeatSubmit
    @Log(title = "题库管理", businessType = BusinessType.UPDATE)
    @ApiOperation(value = "编辑题库")
    @PutMapping
@@ -60,6 +63,7 @@
        return CommonResult.success(questionBankService.updateQuestionBank(questionBank));
    }
    @RepeatSubmit
    @Log(title = "题库管理", businessType = BusinessType.UPDATE)
    @ApiOperation(value = "删除题库")
    @DeleteMapping(value = { "/{bankId}" })
exam-admin/src/main/java/com/gkhy/exam/admin/web/ExQuestionController.java
@@ -2,6 +2,7 @@
import com.gkhy.exam.common.annotation.Log;
import com.gkhy.exam.common.annotation.RepeatSubmit;
import com.gkhy.exam.common.api.CommonResult;
import com.gkhy.exam.common.enums.BusinessType;
import com.gkhy.exam.system.domain.ExQuestion;
@@ -32,7 +33,8 @@
    @ApiOperation(value = "题目列表(分页)")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "pageNum", dataType = "int", required = false, value = "当前页,默认1"),
            @ApiImplicitParam(paramType = "query", name = "pageSize", dataType = "int", required = false, value = "每页数目,默认10")
            @ApiImplicitParam(paramType = "query", name = "pageSize", dataType = "int", required = false, value = "每页数目,默认10"),
            @ApiImplicitParam(paramType = "query", name = "bankId", dataType = "long", required = true, value = "题库id")
    })
    @GetMapping("/list")
    public CommonResult list(ExQuestion question){
@@ -47,6 +49,7 @@
        return CommonResult.success(questionService.selectQuestionById(questionId));
    }
    @RepeatSubmit
    @Log(title = "题目管理", businessType = BusinessType.INSERT)
    @ApiOperation(value = "新增题目")
    @PostMapping
@@ -54,6 +57,7 @@
        return CommonResult.success(questionService.insertQuestion(question));
    }
    @RepeatSubmit
    @Log(title = "题目管理", businessType = BusinessType.UPDATE)
    @ApiOperation(value = "编辑题目")
    @PutMapping
@@ -61,6 +65,7 @@
        return CommonResult.success(questionService.updateQuestion(question));
    }
    @RepeatSubmit
    @Log(title = "题目管理", businessType = BusinessType.DELETE)
    @ApiOperation(value = "删除题目")
    @DeleteMapping(value = { "/{questionId}" })
exam-admin/src/main/java/com/gkhy/exam/admin/web/ExResourceController.java
@@ -2,6 +2,7 @@
import com.gkhy.exam.common.annotation.Log;
import com.gkhy.exam.common.annotation.RepeatSubmit;
import com.gkhy.exam.common.api.CommonResult;
import com.gkhy.exam.common.enums.BusinessType;
import com.gkhy.exam.system.domain.ExResource;
@@ -46,20 +47,23 @@
        return CommonResult.success(resourceService.selectResourceById(resourceId));
    }
    @RepeatSubmit
    @Log(title = "资源管理", businessType = BusinessType.INSERT)
    @ApiOperation(value = "新增资源")
    @PostMapping
    public CommonResult add(@Validated @RequestBody ExResource resource){
    public CommonResult add(@Validated @ModelAttribute  ExResource resource){
        return CommonResult.success(resourceService.insertResource(resource));
    }
    @RepeatSubmit
    @Log(title = "资源管理", businessType = BusinessType.UPDATE)
    @ApiOperation(value = "编辑资源")
    @PutMapping
    public CommonResult edit(@Validated @RequestBody ExResource resource){
    public CommonResult edit(@Validated  @ModelAttribute ExResource resource){
        return CommonResult.success(resourceService.updateResource(resource));
    }
    @RepeatSubmit
    @Log(title = "资源管理", businessType = BusinessType.UPDATE)
    @ApiOperation(value = "删除资源")
    @DeleteMapping(value = { "/{resourceId}" })
exam-admin/src/main/java/com/gkhy/exam/admin/web/ExStatisticController.java
对比新文件
@@ -0,0 +1,48 @@
package com.gkhy.exam.admin.web;
import com.gkhy.exam.common.api.CommonResult;
import com.gkhy.exam.system.service.ExStatisticService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
/**
 * <p>
 * 统计前端控制器
 * </p>
 *
 * @author kzy
 * @since 2024-06-06 13:53:17
 */
@Api(tags = "统计记录前端控制器")
@RestController
@RequestMapping("/statistic")
public class ExStatisticController {
    @Autowired
    private ExStatisticService statisticService;
    @ApiOperation(value = "企业数据统计")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "pageNum", dataType = "int", required = false, value = "当前页,默认1"),
            @ApiImplicitParam(paramType = "query", name = "pageSize", dataType = "int", required = false, value = "每页数目,默认10"),
            @ApiImplicitParam(paramType = "query", name = "startTime", dataType = "string", required = false, value = "开始时间(格式:xxxx-xx-xx 00:00:00)"),
            @ApiImplicitParam(paramType = "query", name = "endTime", dataType = "string", required = false, value = "结束时间(格式:xxxx-xx-xx 00:00:00)"),
            @ApiImplicitParam(paramType = "query", name = "companyId", dataType = "long", required = false, value = "企业id"),
            @ApiImplicitParam(paramType = "query", name = "type", dataType = "int", required = true, value = "1线上教育  2线下教育,默认1")
    })
    @GetMapping("/companyStatistic")
    public CommonResult companyStatistic(@RequestParam(required = false) Date startTime, @RequestParam(required = false) Date endTime, @RequestParam(required = false) Long companyId, @RequestParam(required = true,value = "1") Integer type) {
        return CommonResult.success(statisticService.companyStatic(companyId, startTime, endTime,type));
    }
}
exam-admin/src/main/java/com/gkhy/exam/admin/web/ExStudentAnswerController.java
文件已删除
exam-admin/src/main/java/com/gkhy/exam/admin/web/ExStudentController.java
@@ -2,6 +2,7 @@
import com.gkhy.exam.common.annotation.Log;
import com.gkhy.exam.common.annotation.RepeatSubmit;
import com.gkhy.exam.common.api.CommonResult;
import com.gkhy.exam.common.enums.BusinessType;
import com.gkhy.exam.system.domain.ExStudent;
@@ -11,7 +12,6 @@
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@@ -48,6 +48,7 @@
        return CommonResult.success(studentService.selectStudentById(studentId));
    }
    @RepeatSubmit
    @Log(title = "学员管理", businessType = BusinessType.INSERT)
    @ApiOperation(value = "新增学员")
    @PostMapping
@@ -55,6 +56,7 @@
        return CommonResult.success(studentService.insertStudent(student));
    }
    @RepeatSubmit
    @Log(title = "学员管理", businessType = BusinessType.UPDATE)
    @ApiOperation(value = "编辑学员")
    @PutMapping
@@ -62,13 +64,15 @@
        return CommonResult.success(studentService.updateStudent(student));
    }
    @Log(title = "学员管理", businessType = BusinessType.UPDATE)
    @RepeatSubmit
    @Log(title = "学员管理", businessType = BusinessType.DELETE)
    @ApiOperation(value = "删除学员")
    @DeleteMapping(value = { "/{studentId}" })
    public CommonResult delete(@PathVariable(value = "studentId", required = true) Long studentId){
        return CommonResult.success(studentService.deleteStudentById(studentId));
    }
    @RepeatSubmit
    @Log(title = "学员管理", businessType = BusinessType.UPDATE)
    @ApiOperation(value = "重置密码")
    @PutMapping(value = "/resetPwd")
exam-admin/src/main/java/com/gkhy/exam/admin/web/ExStudentStudyController.java
@@ -2,6 +2,7 @@
import com.gkhy.exam.common.annotation.Log;
import com.gkhy.exam.common.annotation.RepeatSubmit;
import com.gkhy.exam.common.api.CommonResult;
import com.gkhy.exam.common.enums.BusinessType;
import com.gkhy.exam.system.service.ExStudentStudyService;
@@ -20,7 +21,7 @@
 * @author kzy
 * @since 2024-06-06 13:53:17
 */
@Api(tags = "学员学习记录前端控制器")
@Api(tags = "学员课程学习记录前端控制器")
@RestController
@RequestMapping("/student-study")
public class ExStudentStudyController {
@@ -37,6 +38,8 @@
        return CommonResult.success(studentStudyService.selectStudyByPhaseAndStundentId(phaseId,studentId));
    }
    @RepeatSubmit
    @Log(title = "课程学习记录管理", businessType = BusinessType.DELETE)
    @ApiOperation(value = "删除学习记录")
    @DeleteMapping(value = { "/{studyId}" })
exam-common/pom.xml
@@ -115,6 +115,10 @@
            <groupId>eu.bitwalker</groupId>
            <artifactId>UserAgentUtils</artifactId>
        </dependency>
        <dependency>
            <groupId>net.bramp.ffmpeg</groupId>
            <artifactId>ffmpeg</artifactId>
        </dependency>
    </dependencies>
</project>
exam-common/src/main/java/com/gkhy/exam/common/config/FilePathConfig.java
对比新文件
@@ -0,0 +1,31 @@
package com.gkhy.exam.common.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
 * @Author wsl
 * @Version 1.0
 */
@Data
@Component
@ConfigurationProperties(prefix = "m3u8.convertor")
public class FilePathConfig {
    /**
    * 文件上传临时路径 (本地文件转换不需要)
    */
    private String tempPath = "upload/tmp/";
    /**
     * m3u8文件转换后,储存的根路径
     */
    private String basePath = "upload/m3u8/";
    /**
     * m3u8文件转换后,储存的根路径
     */
    private String bigPath = "upload/big/";
    private String proxy = "m3u8/";
}
exam-common/src/main/java/com/gkhy/exam/common/config/ThreadPoolConfig.java
@@ -13,13 +13,13 @@
@Configuration
public class ThreadPoolConfig {
    //核心线程池大小
    private int corePoolSize=50;
    private int corePoolSize=10;
    //最大可创建的线程数
    private int maxPoolSize=200;
    private int maxPoolSize=500;
    //队列最大长度
    private int queueCapacity=1000;
    //线程池维护非线程允许的空闲时间
    private int keepAliveSeconds=300;
    private int keepAliveSeconds=30;
    @Bean(name = "threadPoolTaskExecutor")
    public ThreadPoolTaskExecutor threadPoolTaskExecutor(){
@@ -30,6 +30,7 @@
        executor.setKeepAliveSeconds(keepAliveSeconds);
        // 线程池对拒绝任务(无线程可用)的处理策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;
    }
exam-common/src/main/java/com/gkhy/exam/common/enums/PhaseLevelEnum.java
对比新文件
@@ -0,0 +1,32 @@
package com.gkhy.exam.common.enums;
/**
 * 批次等级
 *
 */
public enum PhaseLevelEnum
{
    COMPANY(1, "公司级"),
    DEPART(2, "部门级"),
    WORkSHOP(3, "车间级"),
    OTHER(4, "其他");
    private final Integer code;
    private final String info;
    PhaseLevelEnum(Integer code, String info)
    {
        this.code = code;
        this.info = info;
    }
    public Integer getCode()
    {
        return code;
    }
    public String getInfo()
    {
        return info;
    }
}
exam-common/src/main/java/com/gkhy/exam/common/utils/M3u8Utils.java
对比新文件
@@ -0,0 +1,165 @@
package com.gkhy.exam.common.utils;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import com.gkhy.exam.common.config.FilePathConfig;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import net.bramp.ffmpeg.FFmpeg;
import net.bramp.ffmpeg.FFmpegExecutor;
import net.bramp.ffmpeg.FFprobe;
import net.bramp.ffmpeg.builder.FFmpegBuilder;
import net.bramp.ffmpeg.probe.FFmpegProbeResult;
import net.bramp.ffmpeg.probe.FFmpegStream;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.io.File;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
/**
 * @Author sirwsl
 * @Version 1.0
 */
@Slf4j
@Component
public class M3u8Utils {
    @Resource
    private FFmpeg ffmpeg;
    @Resource
    private FFprobe ffprobe;
    @Resource
    private FilePathConfig filePath;
    /**
     * 视频文件转 m3u8
     * 支持: .mp4 | .flv | .avi | .mov | .wmv | .wav
     * @param file 视频文件
     * @return 路径
     */
    public String mediaFileToM3u8(MultipartFile file){
        if (file.isEmpty()) {
            throw new RuntimeException("未发现文件");
        }
        log.info("开始解析视频");
        long start = System.currentTimeMillis();
        //临时目录创建
        String path = new File(System.getProperty("user.dir")).getAbsolutePath();
        String tempFilePath = path+ filePath.getTempPath();
        if (!FileUtil.exist(tempFilePath)) {
            FileUtil.mkdir(tempFilePath);
        }
        String filePathName = tempFilePath + file.getOriginalFilename();
        File dest = new File(filePathName);
        try {
            file.transferTo(dest);
        }catch (Exception e){
            log.error("视频转m3u8格式存在异常,异常原因e:{}",e.getMessage());
        }
        long end = System.currentTimeMillis();
        log.info("临时文件上传成功......耗时:{} ms", end - start);
        String m3u8FilePath = localFileToM3u8(filePathName);
        log.info("视频转换已完成 !");
        return m3u8FilePath;
    }
    /**
     * 本地媒体资源转换
     * @param filePathName : 文件路径
     * @return :
     */
    @SneakyThrows
    public String localFileToM3u8(String filePathName) {
        long startTime = System.currentTimeMillis();
        final FFmpegProbeResult probe = ffprobe.probe(filePathName);
        final List<FFmpegStream> streams = probe.getStreams().stream().filter(fFmpegStream -> fFmpegStream.codec_type != null).collect(Collectors.toList());
        final Optional<FFmpegStream> audioStream = streams.stream().filter(fFmpegStream -> FFmpegStream.CodecType.AUDIO.equals(fFmpegStream.codec_type)).findFirst();
        final Optional<FFmpegStream> videoStream = streams.stream().filter(fFmpegStream -> FFmpegStream.CodecType.VIDEO.equals(fFmpegStream.codec_type)).findFirst();
        if (!audioStream.isPresent()) {
            log.error("未发现音频流");
        }
        if (!videoStream.isPresent()) {
            log.error("未发现视频流");
        }
        //m3u8文件 存储路径
        String filePath = generateFilePath(this.filePath.getBasePath());
        if (!FileUtil.exist(filePath)) {
            FileUtil.mkdir(filePath);
        }
        String mainName = getFileMainName(filePathName);
        String m3u8FileName = filePath + mainName + ".m3u8";
        //下面这一串参数别乱动,经过调优的,1G视频大概需要10秒左右,如果是大佬随意改
        //"-vsync", "2", "-c:v", "copy", "-c:a", "copy", "-tune", "fastdecode", "-hls_wrap", "0", "-hls_time", "10", "-hls_list_size", "0", "-threads", "12"
        FFmpegBuilder builder = new FFmpegBuilder()
                .setInput(filePathName)
                .overrideOutputFiles(true)
                .addOutput(m3u8FileName)//输出文件
                .setFormat(probe.getFormat().format_name) //"mp4"
                .setAudioBitRate(audioStream.map(fFmpegStream -> fFmpegStream.bit_rate).orElse(0L))
                .setAudioChannels(1)
                .setAudioCodec("aac")        // using the aac codec
                .setAudioSampleRate(audioStream.get().sample_rate)
                .setAudioBitRate(audioStream.get().bit_rate)
                .setStrict(FFmpegBuilder.Strict.STRICT)
                .setFormat("hls")
                .setPreset("ultrafast")
                .addExtraArgs("-vsync", "2", "-c:v", "copy", "-c:a", "copy", "-tune", "fastdecode", "-hls_wrap", "0", "-hls_time", "10", "-hls_list_size", "0", "-threads", "12")
                .done();
        FFmpegExecutor executor = new FFmpegExecutor(ffmpeg, ffprobe);
        // Run a one-pass encode
        executor.createJob(builder).run();
        File dest = new File(filePathName);
        if (dest.isFile() && dest.exists()) {
            dest.delete();
            System.gc();
            log.warn("临时文件 {}已删除", dest.getName());
        }
        long endTime = System.currentTimeMillis();
        log.info("文件:{} 转换完成!共耗时{} ms", dest.getName(), (endTime - startTime));
        return m3u8FileName;
    }
    public static String generateFilePath(String basePath){
        String temp = basePath;
        if(StringUtils.isNotBlank(basePath)){
            if(basePath.endsWith("/")){
                temp = basePath.substring(0,basePath.lastIndexOf("/"));
            }
        }
        return temp+"/"+generateDateDir()+"/";
    }
    /**
     *@Description 根据当前时间,生成下级存储目录
     *@Return
     */
    public static String generateDateDir(){
        LocalDateTime now = LocalDateTime.now();
        return DateUtil.format(now, "yyyyMMdd/HH/mm/ss");
    }
    /**
     *@Description 根据文件全路径,获取文件主名称
     *@param fullPath 文件全路径(包含文件名)
     *@Return
     */
    public static String getFileMainName(String fullPath){
        String fileName = FileUtil.getName(fullPath);
        return fileName.substring(0,fileName.lastIndexOf("."));
    }
}
exam-common/src/main/java/com/gkhy/exam/common/utils/MinioUtils.java
@@ -6,6 +6,7 @@
import com.gkhy.exam.common.config.MinioConfig;
import io.minio.*;
import io.minio.http.Method;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.FastByteArrayOutputStream;
@@ -13,9 +14,11 @@
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.util.Date;
@Component
@Slf4j
public class MinioUtils {
    @Autowired
    private MinioClient minioClient;
@@ -27,15 +30,27 @@
     * @return boolean
     */
    public Boolean bucketExists(String bucketName) {
        Boolean found;
        Boolean found=false;
        try {
            found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
        } catch (Exception e) {
            e.printStackTrace();
            return false;
            log.error("minio校验bucket失败:{}",e.getMessage());
        }
        return found;
    }
    /**
     * 文件上传 上传完成后请关闭文件流
     *
     * @param fileName 带后缀的文件名 检验日期yyyyMMdd加16位随机码
     * @param stream   文件流 要上传文件的流
     */
    public void fileUploader( String fileName, InputStream stream) throws Exception {
        PutObjectArgs objectArgs = PutObjectArgs.builder().bucket(minioConfig.getBucketName()).object(fileName).stream(stream,-1,-1).contentType("application/octet-stream").build();
        // 使用putObject上传一个文件到文件分类
        minioClient.putObject(objectArgs);
    }
    /**
     * 文件上传
@@ -43,7 +58,7 @@
     * @param file 文件
     * @return Boolean
     */
    public String upload(MultipartFile file) {
    public String uploadFile(MultipartFile file) {
        String originalFilename = file.getOriginalFilename();
        if (StringUtils.isBlank(originalFilename)){
            throw new RuntimeException();
@@ -56,7 +71,7 @@
            //文件名称相同会覆盖
            minioClient.putObject(objectArgs);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("minio上传文件失败:{}",e.getMessage());
            return null;
        }
        return objectName;
@@ -110,4 +125,20 @@
            e.printStackTrace();
        }
    }
    /**
     * 删除文件
     * @param fileName
     * @return
     */
    public boolean removeFile(String fileName){
        try {
            RemoveObjectArgs removeObjectArgs = RemoveObjectArgs.builder().bucket(minioConfig.getBucketName())
                    .object(fileName).build();
            minioClient.removeObject(removeObjectArgs);
            return true;
        }catch (Exception e){
            return false;
        }
    }
}
exam-system/src/main/java/com/gkhy/exam/system/domain/ExExamRecord.java
对比新文件
@@ -0,0 +1,97 @@
package com.gkhy.exam.system.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
 * <p>
 * 线下教育登记表
 * </p>
 *
 * @author kzy
 * @since 2024-06-24 16:16:33
 */
@Getter
@Setter
@TableName("ex_exam_record")
@ApiModel(value = "ExExamRecord对象", description = "线下教育登记表")
public class ExExamRecord implements Serializable {
    private static final long serialVersionUID = 1L;
    @ApiModelProperty("主键")
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;
    @ApiModelProperty("公司id")
    @TableField("company_id")
    private Long companyId;
    @ApiModelProperty("学员id")
    @TableField("student_id")
    private Long studentId;
    @ApiModelProperty("计划名称")
    @TableField("plan_name")
    private String planName;
    @ApiModelProperty("课程名称")
    @TableField("course_name")
    private String courseName;
    @ApiModelProperty("培训等级")
    @TableField("level")
    private String level;
    @ApiModelProperty("要求课时(分)")
    @TableField("period")
    private Integer period;
    @ApiModelProperty("实际课时(分)")
    @TableField("actual_period")
    private Integer actualPeriod;
    @ApiModelProperty("考试成绩")
    @TableField("score")
    private Integer score;
    @ApiModelProperty("是否合格,0不合格 1合格 默认0")
    @TableField("passed")
    private Integer passed;
    @ApiModelProperty("创建时间")
    @TableField("create_time")
    private LocalDateTime createTime;
    @ApiModelProperty("创建人")
    @TableField("create_by")
    private String createBy;
    @ApiModelProperty("更新时间")
    @TableField("update_time")
    private LocalDateTime updateTime;
    @ApiModelProperty("更新人")
    @TableField("update_by")
    private String updateBy;
    @ApiModelProperty("备注")
    @TableField("remark")
    private String remark;
    @ApiModelProperty("公司名称")
    @TableField(exist = false)
    private String companyName;
}
exam-system/src/main/java/com/gkhy/exam/system/domain/ExQuestion.java
@@ -48,6 +48,7 @@
    @TableField("bank_id")
    private Long bankId;
    @NotNull(message = "公司id不能为空")
    @ApiModelProperty("公司id")
    @TableField("company_id")
    private Long companyId;
exam-system/src/main/java/com/gkhy/exam/system/domain/ExResource.java
@@ -13,7 +13,6 @@
import org.springframework.web.multipart.MultipartFile;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.time.LocalDateTime;
@@ -54,7 +53,6 @@
    @TableField("name")
    private String name;
    @NotEmpty(message = "公司id不能为空")
    @ApiModelProperty(value = "提交公司id",required = true)
    @TableField("company_id")
    private Long companyId;
@@ -63,7 +61,7 @@
    @TableField("privatize")
    private Integer privatize;
    @NotBlank(message = "资源种类不能为空")
    @NotNull(message = "资源种类不能为空")
    @ApiModelProperty(value = "资源种类(1:视频2:音频;3:文档)",required = true)
    @TableField("resource_type")
    private Integer resourceType;
exam-system/src/main/java/com/gkhy/exam/system/domain/vo/CompanyPaperStudentVO.java
对比新文件
@@ -0,0 +1,18 @@
package com.gkhy.exam.system.domain.vo;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
@Getter
@Setter
@Accessors(chain = true)
public class CompanyPaperStudentVO {
    @ApiModelProperty("公司id")
    private Long companyId;
    @ApiModelProperty("考试人员数量")
    private Integer paperStudentCount;
    @ApiModelProperty("合格人员数量")
    private Integer passStudentCount;
}
exam-system/src/main/java/com/gkhy/exam/system/domain/vo/CompanyPhaseStudentVO.java
对比新文件
@@ -0,0 +1,18 @@
package com.gkhy.exam.system.domain.vo;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
@Getter
@Setter
@Accessors(chain = true)
public class CompanyPhaseStudentVO {
    @ApiModelProperty("公司id")
    private Long companyId;
    @ApiModelProperty("批次人员数量")
    private Integer phaseStudentCount;
    @ApiModelProperty("批次等级")
    private Integer level;
}
exam-system/src/main/java/com/gkhy/exam/system/domain/vo/CompanyPhaseVO.java
对比新文件
@@ -0,0 +1,18 @@
package com.gkhy.exam.system.domain.vo;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
@Getter
@Setter
@Accessors(chain = true)
public class CompanyPhaseVO {
    @ApiModelProperty("公司id")
    private Long companyId;
    @ApiModelProperty("批次数量")
    private Integer phaseCount;
    @ApiModelProperty("批次等级")
    private Integer level;
}
exam-system/src/main/java/com/gkhy/exam/system/domain/vo/CompanyStatisticVO.java
对比新文件
@@ -0,0 +1,39 @@
package com.gkhy.exam.system.domain.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
@Getter
@Setter
@Accessors(chain = true)
@ApiModel(value = "CompanyStatisticVO对象", description = "公司数据统计对象")
public class CompanyStatisticVO {
    @ApiModelProperty("公司id")
    private Long companyId;
    @ApiModelProperty("公司名称")
    private String companyName;
    @ApiModelProperty("批次数量")
    private Integer phaseCount;
    @ApiModelProperty("批次人员数量")
    private Integer phaseStudentCount;
    @ApiModelProperty("三级批次数量")
    private Integer level3PhaseCount;
    @ApiModelProperty("三级人员数量")
    private Integer level3StudentCount;
    @ApiModelProperty("二级批次数量")
    private Integer level2PhaseCount;
    @ApiModelProperty("二级人员数量")
    private Integer level2StudentCount;
    @ApiModelProperty("一级批次数量")
    private Integer level1PhaseCount;
    @ApiModelProperty("一级人员数量")
    private Integer level1StudentCount;
    @ApiModelProperty("考试人员数量")
    private Integer paperStudentCount;
    @ApiModelProperty("合格人员数量")
    private Integer passStudentCount;
}
exam-system/src/main/java/com/gkhy/exam/system/mapper/ExExamRecordMapper.java
对比新文件
@@ -0,0 +1,32 @@
package com.gkhy.exam.system.mapper;
import com.gkhy.exam.system.domain.ExExamRecord;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
 * <p>
 * 线下教育登记表 Mapper 接口
 * </p>
 *
 * @author kzy
 * @since 2024-06-24 16:16:33
 */
@Mapper
public interface ExExamRecordMapper extends BaseMapper<ExExamRecord> {
    /**
     * 分页获取登记记录列表
     * @param examRecord
     * @return
     */
    List<ExExamRecord> selectExamRecordList(ExExamRecord examRecord);
    /**
     * 根据id获取登记记录详情
     * @param recordId
     * @return
     */
    ExExamRecord selectExamRecordById(Long recordId);
}
exam-system/src/main/java/com/gkhy/exam/system/mapper/SysCompanyMapper.java
@@ -2,7 +2,11 @@
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.gkhy.exam.system.domain.SysCompany;
import com.gkhy.exam.system.domain.vo.CompanyPaperStudentVO;
import com.gkhy.exam.system.domain.vo.CompanyPhaseStudentVO;
import com.gkhy.exam.system.domain.vo.CompanyPhaseVO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@@ -47,4 +51,19 @@
     * @return
     */
    SysCompany checkNameUnique(String name);
    List<CompanyPhaseVO> getOnlineCompanyPhaseCount(@Param("companyIds") List<Long> companyIds, @Param("startTime")String startTime, @Param("endTime")String endTime);
    List<CompanyPhaseStudentVO> getOnlineCompanyPhaseStudentCount(@Param("companyIds")List<Long> companyIds,@Param("startTime")String startTime,@Param("endTime")String endTime);
    List<CompanyPaperStudentVO> getOnlineCompanyPaperStudentCount(@Param("companyIds")List<Long> companyIds,@Param("startTime")String startTime,@Param("endTime")String endTime);
    List<CompanyPhaseVO> getOfflineCompanyPhaseCount(@Param("companyIds") List<Long> companyIds, @Param("startTime")String startTime, @Param("endTime")String endTime);
    List<CompanyPhaseStudentVO> getOfflineCompanyPhaseStudentCount(@Param("companyIds")List<Long> companyIds,@Param("startTime")String startTime,@Param("endTime")String endTime);
    List<CompanyPaperStudentVO> getOfflineCompanyPaperStudentCount(@Param("companyIds")List<Long> companyIds,@Param("startTime")String startTime,@Param("endTime")String endTime);
}
exam-system/src/main/java/com/gkhy/exam/system/service/ExExamRecordService.java
对比新文件
@@ -0,0 +1,73 @@
package com.gkhy.exam.system.service;
import com.gkhy.exam.common.api.CommonPage;
import com.gkhy.exam.system.domain.ExExamRecord;
import com.baomidou.mybatisplus.extension.service.IService;
import org.springframework.web.multipart.MultipartFile;
/**
 * <p>
 * 线下教育登记表 服务类
 * </p>
 *
 * @author kzy
 * @since 2024-06-24 16:16:33
 */
public interface ExExamRecordService extends IService<ExExamRecord> {
    /**
     * 根据条件分页查询登记列表
     * @param examRecord
     * @return
     */
    CommonPage selectExamRecordList(ExExamRecord examRecord);
    /**
     * 根据id查询登记信息
     *
     * @param recordId
     * @return
     */
    public ExExamRecord selectExamRecordById(Long recordId);
    /**
     * 新增登记记录
     *
     * @param examRecord
     * @return 结果
     */
    public int insertExamRecord(ExExamRecord examRecord);
    /**
     * 修改登记记录
     *
     * @param examRecord
     * @return 结果
     */
    public int updateExamRecord(ExExamRecord examRecord);
    /**
     * 删除登记记录
     *
     * @param recordId
     * @return 结果
     */
    public int deleteExamRecordById(Long recordId);
    /**
     * 校验登记记录是否唯一
     *
     * @param examRecord
     * @return boolean
     */
    public boolean checkRecordUnique(ExExamRecord examRecord);
    /**
     * 导入登记记录
     */
    public void importRecord(MultipartFile file);
}
exam-system/src/main/java/com/gkhy/exam/system/service/ExPaperStudentService.java
@@ -5,6 +5,7 @@
import com.gkhy.exam.system.domain.ExPaperStudent;
import java.util.List;
import java.util.Map;
/**
 * <p>
@@ -25,10 +26,10 @@
    /**
     * 批量新增考卷与学员关系
     * @param paperStudents
     * @param paperStudentMap
     * @return
     */
    public int batchAddPaperStudent(List<ExPaperStudent> paperStudents);
    public int batchAddPaperStudent(Map<String,Object> paperStudentMap);
    /**
     * 分页获取学员的试卷列表
exam-system/src/main/java/com/gkhy/exam/system/service/ExStatisticService.java
对比新文件
@@ -0,0 +1,12 @@
package com.gkhy.exam.system.service;
import com.gkhy.exam.common.api.CommonPage;
import java.util.Date;
/**
 * 统计 服务类
 */
public interface ExStatisticService {
    public CommonPage companyStatic(Long companyId, Date startTime, Date  endTime, Integer type);
}
exam-system/src/main/java/com/gkhy/exam/system/service/SysCommonService.java
@@ -3,6 +3,8 @@
import com.gkhy.exam.system.domain.vo.UploadObjectVO;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
public interface SysCommonService {
    /**
@@ -22,4 +24,41 @@
    UploadObjectVO doUpload(String imageBase64);
    public boolean removeFile(String path);
    /**
     * 删除文件并转成m3u8格式
     * @param file
     * @return
     * @throws Exception
     */
    public String uploadVideo2M3u8(MultipartFile file) throws Exception;
    /**
     * 大文件上传至本地
     *
     * @param request :请求
     * @param guid    : 编码文件名
     * @param chunk   : 切片数
     * @param file    : 切片文件
     * @return : 是否成功
     */
    public boolean uploadSlice(HttpServletRequest request, String guid, Integer chunk, MultipartFile file);
    /**
     * 切片上传后合并转M3U8格式 :
     * @param fileName :文件名
     * @param guid: 随机id
     * @return :
     */
    public String uploadVideoMerge(String guid, String fileName);
    /**
     * 合并切片并上传至服务器
     * @param guid :
     * @param fileName :
     * @return :
     */
    public String uploadMerge(String guid, String fileName);
}
exam-system/src/main/java/com/gkhy/exam/system/service/impl/ExCourseServiceImpl.java
@@ -76,6 +76,7 @@
        checkUserAllowed(course);
        if(SecurityUtils.getLoginUser().getUser().getUserType().equals(UserTypeEnum.SYSTEM_USER.getCode())){
            course.setState(ApproveStatusEnum.APPROVED.getCode());
            course.setPrivatize(PrivatizeEnum.PUBLIC.getCode());
        }else{
            course.setState(ApproveStatusEnum.APPROVING.getCode());
        }
exam-system/src/main/java/com/gkhy/exam/system/service/impl/ExExamPaperServiceImpl.java
@@ -88,6 +88,8 @@
        examPaper.setCreateBy(SecurityUtils.getUsername());
        if(examPaper.getLimitTime()>0){
            examPaper.setLimit(1);
        }else{
            examPaper.setLimit(0);
        }
        int row=baseMapper.insert(examPaper);
        if(row<1){
@@ -135,19 +137,19 @@
    }
    private List<ExPaperQuestion> getPaperQuestions(Long paperId,Long bankId,Integer questionMethod,Integer questionCount,Integer questionScore, QuestionTypeEnum questionTypeEnum) {
        SysUser user=SecurityUtils.getLoginUser().getUser();
        Integer totalQuestionCount=questionMapper.selectCountByBankId(user.getCompanyId(), bankId, questionTypeEnum.getCode());
        SysUser currentUser=SecurityUtils.getLoginUser().getUser();
        Integer totalQuestionCount=questionMapper.selectCountByBankId(currentUser.getCompanyId(), bankId, questionTypeEnum.getCode());
        if(totalQuestionCount< questionCount){
            throw new ApiException(String.format("所选题库<%s>数量不足,无法分配",questionTypeEnum.getInfo()));
        }
        List<ExQuestion> questions=new ArrayList<>();
        if(Objects.equals(questionMethod, QuestionAssignEnum.RANDOM.getCode())){//随机分配
            questions=questionMapper.selectRandomQuestion(user.getCompanyId(), bankId,questionTypeEnum.getCode(), questionCount);
            questions=questionMapper.selectRandomQuestion(currentUser.getCompanyId(), bankId,questionTypeEnum.getCode(), questionCount);
        }else{//顺序分配
            int totalPage=questionCount/ questionMethod;//不能整除,忽略最后一页
            int totalPage=questionCount/questionMethod;//不能整除,忽略最后一页
            Random random=new Random();
            int startIndex=random.nextInt(totalPage)+1;
            questions=questionMapper.selectQuestionWithLimit(user.getCompanyId(), bankId,questionTypeEnum.getCode(),startIndex, questionCount);
            questions=questionMapper.selectQuestionWithLimit(currentUser.getCompanyId(), bankId,questionTypeEnum.getCode(),startIndex, questionCount);
        }
        List<ExPaperQuestion> paperQuestionList=questions.stream().map(item -> {
            ExPaperQuestion exPaperQuestion=new ExPaperQuestion();
@@ -162,6 +164,7 @@
    @Override
    public int updateExamPaper(ExExamPaper examPaper) {
        checkUserAllowed(examPaper);
        if(!checkNameUnique(examPaper)){
            throw new ApiException("试卷名称已存在");
        }
@@ -170,7 +173,9 @@
            throw new ApiException("该试卷下已分配学员,不能编辑");
        }
        examPaper.setCode(null);//编号不能修改
        if(examPaper.getLimitTime()==0){
        if(examPaper.getLimitTime()>0){
            examPaper.setLimit(1);
        }else{
            examPaper.setLimit(0);
        }
        int row=baseMapper.updateById(examPaper);
@@ -199,16 +204,17 @@
    @Override
    public int deleteExamPaperById(Long paperId) {
        checkUserAllowed(baseMapper.selectById(paperId));
        //查询该试卷分配的学员人数
        if(checkPaperHasStudent(paperId)){
            throw new ApiException("该试卷下已分配学员,不能删除");
        }
        int row=baseMapper.deleteById(paperId);
        int row=baseMapper.deletePaperById(paperId);
        if(row<1){
            throw new ApiException("删除试卷失败");
        }
        //删除考卷试题
        paperQuestionMapper.deletebyPapaerId(paperId);
     //   paperQuestionMapper.deletebyPapaerId(paperId);
        return row;
    }
@@ -233,9 +239,7 @@
    @Override
    public int changeExamPaperStatus(Long paperId, Integer status) {
        checkUserAllowed(baseMapper.selectById(paperId));
        return baseMapper.updateById(new ExExamPaper().setId(paperId).setStatus(status).setUpdateBy(SecurityUtils.getUsername()));
    }
}
exam-system/src/main/java/com/gkhy/exam/system/service/impl/ExExamRecordServiceImpl.java
对比新文件
@@ -0,0 +1,94 @@
package com.gkhy.exam.system.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gkhy.exam.common.api.CommonPage;
import com.gkhy.exam.common.domain.entity.SysUser;
import com.gkhy.exam.common.enums.UserTypeEnum;
import com.gkhy.exam.common.exception.ApiException;
import com.gkhy.exam.common.utils.PageUtils;
import com.gkhy.exam.common.utils.SecurityUtils;
import com.gkhy.exam.system.domain.ExExamRecord;
import com.gkhy.exam.system.mapper.ExExamRecordMapper;
import com.gkhy.exam.system.service.ExExamRecordService;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
/**
 * <p>
 * 线下教育登记表 服务实现类
 * </p>
 *
 * @author kzy
 * @since 2024-06-24 16:16:33
 */
@Service
public class ExExamRecordServiceImpl extends ServiceImpl<ExExamRecordMapper, ExExamRecord> implements ExExamRecordService {
    @Override
    public CommonPage selectExamRecordList(ExExamRecord examRecord) {
        SysUser user= SecurityUtils.getLoginUser().getUser();
        if(!user.getUserType().equals(UserTypeEnum.SYSTEM_USER.getCode())){
            examRecord.setCompanyId(user.getCompanyId());
        }
        PageUtils.startPage();
        List<ExExamRecord> recordList=baseMapper.selectExamRecordList(examRecord);
        return CommonPage.restPage(recordList);
    }
    @Override
    public ExExamRecord selectExamRecordById(Long recordId) {
        return baseMapper.selectExamRecordById(recordId);
    }
    @Override
    public int insertExamRecord(ExExamRecord examRecord) {
        checkUserAllowed(examRecord);
        int row=baseMapper.insert(examRecord);
        if(row<1){
            throw new ApiException("新增登记记录失败");
        }
        return row;
    }
    @Override
    public int updateExamRecord(ExExamRecord examRecord) {
        checkUserAllowed(examRecord);
        int row=baseMapper.updateById(examRecord);
        if(row<1){
            throw new ApiException("更新登记记录失败");
        }
        return row;
    }
    @Override
    public int deleteExamRecordById(Long recordId) {
        checkUserAllowed(baseMapper.selectById(recordId));
        return baseMapper.deleteById(recordId);
    }
    public void checkUserAllowed(ExExamRecord examRecord) {
        SysUser currentUser= SecurityUtils.getLoginUser().getUser();
        if(currentUser.getUserType().equals(UserTypeEnum.SYSTEM_USER.getCode())){
            return;
        }
        if(currentUser.getUserType().equals(UserTypeEnum.STUDENT.getCode())){
            throw new ApiException("没有权限操作");
        }
        if(!currentUser.getCompanyId().equals(examRecord.getCompanyId())){
            throw new ApiException("没有权限操作其他企业登记记录");
        }
    }
    @Override
    public boolean checkRecordUnique(ExExamRecord examRecord) {
        return false;
    }
    @Override
    public void importRecord(MultipartFile file) {
    }
}
exam-system/src/main/java/com/gkhy/exam/system/service/impl/ExPaperStudentServiceImpl.java
@@ -1,6 +1,7 @@
package com.gkhy.exam.system.service.impl;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gkhy.exam.common.api.CommonPage;
import com.gkhy.exam.common.domain.entity.SysUser;
@@ -11,19 +12,16 @@
import com.gkhy.exam.common.utils.SecurityUtils;
import com.gkhy.exam.system.domain.ExExamPaper;
import com.gkhy.exam.system.domain.ExPaperStudent;
import com.gkhy.exam.system.domain.ExPhaseStudent;
import com.gkhy.exam.system.domain.ExStudent;
import com.gkhy.exam.system.mapper.ExExamPaperMapper;
import com.gkhy.exam.system.mapper.ExPaperStudentMapper;
import com.gkhy.exam.system.mapper.ExStudentAnswerMapper;
import com.gkhy.exam.system.mapper.ExStudentMapper;
import com.gkhy.exam.system.mapper.*;
import com.gkhy.exam.system.service.ExPaperStudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.*;
import java.util.stream.Collectors;
/**
 * <p>
@@ -41,6 +39,8 @@
    private ExStudentAnswerMapper studentAnswerMapper;
    @Autowired
    private ExStudentMapper studentMapper;
    @Autowired
    private ExPhaseStudentMapper phaseStudentMapper;
    @Override
@@ -67,6 +67,7 @@
    @Override
    public int addPaperStudent(ExPaperStudent paperStudent) {
        checkUserAllowed(paperStudent);
        checkStudentUnique(Collections.singletonList(paperStudent));
        paperStudent.setCreateId(SecurityUtils.getUserId());
        int row=baseMapper.insert(paperStudent);
@@ -77,7 +78,25 @@
    }
    @Override
    public int batchAddPaperStudent(List<ExPaperStudent> paperStudents) {
    public int batchAddPaperStudent(Map<String,Object> paperStudentMap) {
        List<Long> phaseIds= (List<Long>) paperStudentMap.get("phaseIds");
        List<Long> studentIds= (List<Long>) paperStudentMap.get("studentIds");
        if(ObjectUtil.isEmpty(phaseIds) && ObjectUtil.isEmpty(studentIds)){
            throw new ApiException("批次id与学员id不能同时为空");
        }
        Long paperId= (Long) paperStudentMap.get("paperId");
        if(paperId==null){
            throw new ApiException("考卷id不能为空");
        }
        //按批次绑定用户
        if(phaseIds.size()>0){
            List<ExPhaseStudent> phaseStudentList=phaseStudentMapper.selectList( Wrappers.<ExPhaseStudent>lambdaQuery()
                    .in(ExPhaseStudent::getPhaseId, phaseIds));
            studentIds=phaseStudentList.stream().map(item -> item.getStudentId()).distinct().collect(Collectors.toList());
        }
        List<ExPaperStudent> paperStudents=studentIds.stream().map(item -> {
            return new ExPaperStudent().setPaperId(paperId).setStudentId(item);
        }).collect(Collectors.toList());
        checkStudentUnique(paperStudents);
        int row=baseMapper.batchInsert(paperStudents);
        if(row<1){
@@ -100,7 +119,7 @@
    @Override
    public CommonPage selectPaperStudentList(ExPaperStudent paperStudent) {
        if(paperStudent.getPaperId()==null){
            throw new ApiException("试卷id不能为空");
            throw new ApiException("考卷id不能为空");
        }
        PageUtils.startPage();
        List<ExPaperStudent> paperStudentList=baseMapper.selectPaperStudentList(paperStudent);
@@ -113,6 +132,7 @@
        if(ObjectUtil.isNull(paperStudent)){
            throw new ApiException(String.format("该试卷下不存在该学员<>",paperStudent.getStudentName()));
        }
        checkUserAllowed(paperStudent);
        int studentAnswerCount=studentAnswerMapper.countByPaperId(paperStudent.getPaperId(),paperStudent.getStudentId());
        if(studentAnswerCount>0){
            throw new ApiException(String.format("学员<%s>已进行答题,不能删除",paperStudent.getStudentName()));
@@ -130,7 +150,20 @@
    }
    public void checkUserAllowed(ExPaperStudent paperStudent) {
        SysUser currentUser= SecurityUtils.getLoginUser().getUser();
        if(currentUser.getUserType().equals(UserTypeEnum.SYSTEM_USER.getCode())){
            return;
        }
        if(currentUser.getUserType().equals(UserTypeEnum.STUDENT.getCode())){
            throw new ApiException("没有权限操作");
        }
        ExExamPaper examPaper=examPaperMapper.selectById(paperStudent.getPaperId());
        if(!currentUser.getCompanyId().equals(examPaper.getCompanyId())){
            throw new ApiException("没有权限操作其他企业考卷");
        }
    }
    @Override
    public void endExam(ExPaperStudent paperStudent) {
exam-system/src/main/java/com/gkhy/exam/system/service/impl/ExQuestionBankServiceImpl.java
@@ -33,6 +33,10 @@
    @Override
    public CommonPage selectQuestionBankList(ExQuestionBank questionBank) {
        SysUser user= SecurityUtils.getLoginUser().getUser();
        if(!user.getUserType().equals(UserTypeEnum.SYSTEM_USER.getCode())){
            questionBank.setCompanyId(user.getCompanyId());
        }
        PageUtils.startPage();
        List<ExQuestionBank> bankList=baseMapper.selectQuestionBankList(questionBank);
        return CommonPage.restPage(bankList);
@@ -40,11 +44,23 @@
    @Override
    public ExQuestionBank selectQuestionBankById(Long bankId) {
        return baseMapper.selectById(bankId);
        ExQuestionBank questionBank= baseMapper.selectById(bankId);
        if(questionBank.getPrivatize().equals(PrivatizeEnum.PUBLIC.getCode())){
            return questionBank;
        }
        SysUser currentUser=SecurityUtils.getLoginUser().getUser();
        if(currentUser.getUserType().equals(UserTypeEnum.SYSTEM_USER.getCode())){
            return questionBank;
        }
        if(!questionBank.getCompanyId().equals(currentUser.getCompanyId())){
            throw new ApiException("无权限查看其它企业题库");
        }
        return questionBank;
    }
    @Override
    public int insertQuestionBank(ExQuestionBank questionBank) {
        checkUserAllowed(questionBank);
        if(!checkNameUnique(questionBank)){
            throw new ApiException("题库名称已存在");
        }
@@ -52,10 +68,6 @@
        if(user.getUserType().equals(UserTypeEnum.SYSTEM_USER.getCode())){
            questionBank.setPrivatize(PrivatizeEnum.PUBLIC.getCode());
        }else{
            if(user.getCompanyId()==null){
                throw new ApiException("获取用户公司id为空");
            }
            questionBank.setPrivatize(PrivatizeEnum.PRIVATE.getCode());
            questionBank.setCompanyId(user.getCompanyId());
        }
        int row =baseMapper.insert(questionBank);
@@ -67,6 +79,7 @@
    @Override
    public int updateQuestionBank(ExQuestionBank questionBank) {
        checkUserAllowed(questionBank);
        if(!checkNameUnique(questionBank)){
            throw new ApiException("题库名称已存在");
        }
@@ -77,8 +90,22 @@
        return row;
    }
    public void checkUserAllowed(ExQuestionBank questionBank) {
        SysUser currentUser= SecurityUtils.getLoginUser().getUser();
        if(currentUser.getUserType().equals(UserTypeEnum.SYSTEM_USER.getCode())){
            return;
        }
        if(currentUser.getUserType().equals(UserTypeEnum.STUDENT.getCode())){
            throw new ApiException("没有权限操作");
        }
        if(!currentUser.getCompanyId().equals(questionBank.getCompanyId())){
            throw new ApiException("没有权限操作其他企业课程");
        }
    }
    @Override
    public int deleteQuestionBankById(Long bankId) {
        checkUserAllowed(baseMapper.selectById(bankId));
        return baseMapper.deleteByBankId(bankId);
    }
@@ -101,6 +128,9 @@
    @Override
    public CommonPage selectQuestionBankListForStudent(ExQuestionBank questionBank) {
        SysUser user= SecurityUtils.getLoginUser().getUser();
        if(!user.getUserType().equals(UserTypeEnum.STUDENT.getCode())){
            throw new ApiException("非学员用户,无法查看");
        }
        questionBank.setCompanyId(user.getCompanyId());
        questionBank.setStudentId(user.getId());
        PageUtils.startPage();
@@ -110,7 +140,11 @@
    @Override
    public ExQuestionBank selectQuestionBankByIdForStudent(Long bankId) {
        return baseMapper.selectQuestionBankByIdForStudent(bankId,SecurityUtils.getUserId());
        SysUser user= SecurityUtils.getLoginUser().getUser();
        if(!user.getUserType().equals(UserTypeEnum.STUDENT.getCode())){
            throw new ApiException("非学员用户,无法查看");
        }
        return baseMapper.selectQuestionBankByIdForStudent(bankId,user.getId());
    }
    @Override
exam-system/src/main/java/com/gkhy/exam/system/service/impl/ExQuestionServiceImpl.java
@@ -16,8 +16,10 @@
import com.gkhy.exam.system.domain.ExExamPaper;
import com.gkhy.exam.system.domain.ExPaperStudent;
import com.gkhy.exam.system.domain.ExQuestion;
import com.gkhy.exam.system.domain.ExQuestionBank;
import com.gkhy.exam.system.mapper.ExExamPaperMapper;
import com.gkhy.exam.system.mapper.ExPaperStudentMapper;
import com.gkhy.exam.system.mapper.ExQuestionBankMapper;
import com.gkhy.exam.system.mapper.ExQuestionMapper;
import com.gkhy.exam.system.service.ExQuestionService;
import org.springframework.beans.factory.annotation.Autowired;
@@ -41,11 +43,22 @@
    private ExPaperStudentMapper paperStudentMapper;
    @Autowired
    private ExExamPaperMapper examPaperMapper;
    @Autowired
    private ExQuestionBankMapper questionBankMapper;
    @Override
    public CommonPage selectQuestionList(ExQuestion question) {
        if(question.getBankId()==null){
            throw new ApiException("题库id不能为空");
        }
        ExQuestionBank questionBank=questionBankMapper.selectById(question.getBankId());
        if(!questionBank.getPrivatize().equals(PrivatizeEnum.PUBLIC.getCode())){
            SysUser currentUser=SecurityUtils.getLoginUser().getUser();
            if(!currentUser.getUserType().equals(UserTypeEnum.SYSTEM_USER.getCode())){
                if(!question.getCompanyId().equals(currentUser.getCompanyId())){
                    throw new ApiException("无权限查看其它企业题目");
                }
            }
        }
        PageUtils.startPage();
        List<ExQuestion> questionList=baseMapper.selectQuestionList(question);
@@ -54,18 +67,29 @@
    @Override
    public ExQuestion selectQuestionById(Long questionId) {
        return baseMapper.selectById(questionId);
        ExQuestion question= baseMapper.selectById(questionId);
        if(question.getPrivatize().equals(PrivatizeEnum.PUBLIC.getCode())){
            return question;
        }
        SysUser currentUser=SecurityUtils.getLoginUser().getUser();
        if(currentUser.getUserType().equals(UserTypeEnum.SYSTEM_USER.getCode())){
            return question;
        }
        if(!question.getCompanyId().equals(currentUser.getCompanyId())){
            throw new ApiException("无权限查看其它企业题目");
        }
        return question;
    }
    @Override
    public int insertQuestion(ExQuestion question) {
        checkUserAllowed(question);
        SysUser user= SecurityUtils.getLoginUser().getUser();
        if(user.getUserType().equals(UserTypeEnum.SYSTEM_USER.getCode())){
        //公开的题库新增题目,题目也是公开
        ExQuestionBank questionBank=questionBankMapper.selectById(question.getBankId());
        if(user.getUserType().equals(UserTypeEnum.SYSTEM_USER.getCode())||questionBank.getPrivatize().equals(PrivatizeEnum.PUBLIC.getCode())){
            question.setPrivatize(PrivatizeEnum.PUBLIC.getCode());
        }else{
            if(user.getCompanyId()==null){
                throw new ApiException("获取用户公司id失败");
            }
            question.setCompanyId(user.getCompanyId());
            question.setPrivatize(PrivatizeEnum.PRIVATE.getCode());
        }
@@ -80,6 +104,7 @@
    @Override
    public int updateQuestion(ExQuestion question) {
        validData(question);
        checkUserAllowed(question);
        int row=baseMapper.updateById(question);
        if(row<1){
            throw new ApiException("编辑题目失败");
@@ -108,8 +133,22 @@
        
    }
    public void checkUserAllowed(ExQuestion question) {
        SysUser currentUser= SecurityUtils.getLoginUser().getUser();
        if(currentUser.getUserType().equals(UserTypeEnum.SYSTEM_USER.getCode())){
            return;
        }
        if(currentUser.getUserType().equals(UserTypeEnum.STUDENT.getCode())){
            throw new ApiException("没有权限操作");
        }
        if(!currentUser.getCompanyId().equals(question.getCompanyId())){
            throw new ApiException("没有权限操作其他企业题目");
        }
    }
    @Override
    public int deleteQuestionById(Long questionId) {
        checkUserAllowed(baseMapper.selectById(questionId));
        return baseMapper.deleteById(questionId);
    }
exam-system/src/main/java/com/gkhy/exam/system/service/impl/ExResourceServiceImpl.java
@@ -44,16 +44,46 @@
    @Override
    public ExResource selectResourceById(Long resourceId) {
        return baseMapper.selectResourceById(resourceId);
        ExResource resource= baseMapper.selectResourceById(resourceId);
        if(resource==null){
            return resource;
        }
        if(resource.getPrivatize().equals(PrivatizeEnum.PUBLIC.getCode())){
            return resource;
        }
        SysUser currentUser=SecurityUtils.getLoginUser().getUser();
        if(currentUser.getUserType().equals(UserTypeEnum.SYSTEM_USER.getCode())){
            return resource;
        }
        if(!resource.getCompanyId().equals(currentUser.getCompanyId())){
            throw new ApiException("无权限查看其它企业资源");
        }
        return resource;
    }
    @Override
    public ExResource selectResourceByPeriodId(Long periodId) {
        return baseMapper.selectResourceByPeriodId(periodId);
        ExResource resource= baseMapper.selectResourceByPeriodId(periodId);
        if(resource==null){
            return resource;
        }
        if(resource.getPrivatize().equals(PrivatizeEnum.PUBLIC.getCode())){
            return resource;
        }
        SysUser currentUser=SecurityUtils.getLoginUser().getUser();
        if(currentUser.getUserType().equals(UserTypeEnum.SYSTEM_USER.getCode())){
            return resource;
        }
        if(!resource.getCompanyId().equals(currentUser.getCompanyId())){
            throw new ApiException("无权限查看其它企业资源");
        }
        return resource;
    }
    @Override
    public int insertResource(ExResource resource) {
        checkUserAllowed(resource);
        if(!checkNameUnique(resource)){
            throw new ApiException("资源名称已存在");
        }
@@ -61,11 +91,7 @@
        if(user.getUserType().equals(UserTypeEnum.SYSTEM_USER.getCode())){
            resource.setPrivatize(PrivatizeEnum.PUBLIC.getCode());
        }else{
            if(user.getCompanyId()==null){
                throw new ApiException("获取用户公司id失败");
            }
            resource.setCompanyId(user.getCompanyId());
            resource.setPrivatize(PrivatizeEnum.PRIVATE.getCode());
        }
        UploadObjectVO uploadObjectVO =commonService.doUpload(resource.getFile());
        resource.setResourceUri(uploadObjectVO.getPath());
@@ -87,6 +113,7 @@
    @Override
    public int updateResource(ExResource resource) {
        checkUserAllowed(resource);
        if(!checkNameUnique(resource)){
            throw new ApiException("资源名称已存在");
        }
@@ -97,9 +124,23 @@
        return row;
    }
    public void checkUserAllowed(ExResource resource) {
        SysUser currentUser= SecurityUtils.getLoginUser().getUser();
        if(currentUser.getUserType().equals(UserTypeEnum.SYSTEM_USER.getCode())){
            return;
        }
        if(currentUser.getUserType().equals(UserTypeEnum.STUDENT.getCode())){
            throw new ApiException("没有权限操作");
        }
        if(!currentUser.getCompanyId().equals(resource.getCompanyId())){
            throw new ApiException("没有权限操作其他企业资源");
        }
    }
    @Override
    public int deleteResourceById(Long resourceId) {
        //校验资源是否绑定
        checkUserAllowed(baseMapper.selectById(resourceId));
        ExResource resource=getById(resourceId);
        int row=baseMapper.deleteById(resourceId);
        if(row<1){
exam-system/src/main/java/com/gkhy/exam/system/service/impl/ExStatisticServiceImpl.java
对比新文件
@@ -0,0 +1,108 @@
package com.gkhy.exam.system.service.impl;
import cn.hutool.core.date.DateUtil;
import com.gkhy.exam.common.api.CommonPage;
import com.gkhy.exam.common.domain.entity.SysUser;
import com.gkhy.exam.common.enums.PhaseLevelEnum;
import com.gkhy.exam.common.enums.UserTypeEnum;
import com.gkhy.exam.common.utils.PageUtils;
import com.gkhy.exam.common.utils.SecurityUtils;
import com.gkhy.exam.system.domain.SysCompany;
import com.gkhy.exam.system.domain.vo.CompanyPaperStudentVO;
import com.gkhy.exam.system.domain.vo.CompanyPhaseStudentVO;
import com.gkhy.exam.system.domain.vo.CompanyPhaseVO;
import com.gkhy.exam.system.domain.vo.CompanyStatisticVO;
import com.gkhy.exam.system.mapper.SysCompanyMapper;
import com.gkhy.exam.system.service.ExStatisticService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Service
public class ExStatisticServiceImpl implements ExStatisticService {
    @Autowired
    private SysCompanyMapper companyMapper;
    @Override
    public CommonPage companyStatic(Long companyId, Date startTime, Date endTime,Integer type) {
        SysUser user= SecurityUtils.getLoginUser().getUser();
        if(!user.getUserType().equals(UserTypeEnum.SYSTEM_USER.getCode())){
            companyId=user.getCompanyId();
        }
        PageUtils.startPage();
        List<SysCompany> companyList=companyMapper.selectCompanyList(new SysCompany().setId(companyId));
        CommonPage commonPage= CommonPage.restPage(companyList);
        List<CompanyStatisticVO>companyStatisticVOList=staticData(companyList, DateUtil.formatDateTime(DateUtil.beginOfDay(startTime)),DateUtil.formatDateTime(DateUtil.endOfDay(endTime)),type);
        commonPage.setList(companyStatisticVOList);
        return commonPage;
    }
    public List<CompanyStatisticVO> staticData(List<SysCompany> companyList,String startTime,String endTime,Integer type){
        List<Long> companyIds=companyList.stream().map(item -> item.getId()).collect(Collectors.toList());
        List<CompanyPhaseVO> companyPhaseVOList=null;
        if(type==1) {
            companyPhaseVOList=companyMapper.getOnlineCompanyPhaseCount(companyIds, startTime, endTime);
        }else{
            companyPhaseVOList=companyMapper.getOfflineCompanyPhaseCount(companyIds, startTime, endTime);
        }
        Map<Long,List<CompanyPhaseVO>> companyPhaseVOMap=companyPhaseVOList.stream().collect(Collectors.groupingBy(CompanyPhaseVO::getCompanyId, LinkedHashMap::new,Collectors.toList()));
        List<CompanyPhaseStudentVO> companyPhaseStudentVOList=null;
        if(type==1) {
            companyPhaseStudentVOList=companyMapper.getOnlineCompanyPhaseStudentCount(companyIds, startTime, endTime);
        }else{
            companyPhaseStudentVOList=companyMapper.getOfflineCompanyPhaseStudentCount(companyIds, startTime, endTime);
        }
        Map<Long,List<CompanyPhaseStudentVO>> companyPhaseStudentVOMap=companyPhaseStudentVOList.stream().collect(Collectors.groupingBy(CompanyPhaseStudentVO::getCompanyId,LinkedHashMap::new,Collectors.toList()));
        List<CompanyPaperStudentVO> companyPaperStudentVOList=null;
        if(type==1) {
            companyPaperStudentVOList=companyMapper.getOnlineCompanyPaperStudentCount(companyIds, startTime, endTime);
        }else{
            companyPaperStudentVOList=companyMapper.getOfflineCompanyPaperStudentCount(companyIds, startTime, endTime);
        }
        Map<Long,CompanyPaperStudentVO> companyPaperStudentVOMap=companyPaperStudentVOList.stream().collect(Collectors.toMap(CompanyPaperStudentVO::getCompanyId,a ->a));
        List<CompanyStatisticVO> companyStatisticVOList=companyList.stream().map(item -> {
            CompanyStatisticVO companyStatisticVO=new CompanyStatisticVO();
            companyStatisticVO.setCompanyId(item.getId());
            companyStatisticVO.setCompanyName(item.getName());
            List<CompanyPhaseVO> companyPhaseVOs=companyPhaseVOMap.get(item.getId());
            if(companyPhaseVOs!=null&&companyPhaseVOs.size()>0){
                companyPhaseVOs.forEach(cp -> {
                    if(cp.getLevel().equals(PhaseLevelEnum.COMPANY)){
                        companyStatisticVO.setLevel1PhaseCount(cp.getPhaseCount());
                    }else if(cp.getLevel().equals(PhaseLevelEnum.DEPART)){
                        companyStatisticVO.setLevel2PhaseCount(cp.getPhaseCount());
                    }else if(cp.getLevel().equals(PhaseLevelEnum.WORkSHOP)) {
                        companyStatisticVO.setLevel3PhaseCount(cp.getPhaseCount());
                    }
                });
                companyStatisticVO.setPhaseCount(companyPhaseVOs.stream().mapToInt(CompanyPhaseVO::getPhaseCount).sum());
            }
            List<CompanyPhaseStudentVO> companyPhaseStudentVOs=companyPhaseStudentVOMap.get(item.getId());
            if(companyPhaseStudentVOs!=null&&companyPhaseStudentVOs.size()>0){
                companyPhaseStudentVOs.forEach(cp -> {
                    if(cp.getLevel().equals(PhaseLevelEnum.COMPANY)){
                        companyStatisticVO.setLevel1StudentCount(cp.getPhaseStudentCount());
                    }else if(cp.getLevel().equals(PhaseLevelEnum.DEPART)){
                        companyStatisticVO.setLevel2StudentCount(cp.getPhaseStudentCount());
                    }else if(cp.getLevel().equals(PhaseLevelEnum.WORkSHOP)) {
                        companyStatisticVO.setLevel3StudentCount(cp.getPhaseStudentCount());
                    }
                });
                companyStatisticVO.setPhaseStudentCount(companyPhaseStudentVOs.stream().mapToInt(CompanyPhaseStudentVO::getPhaseStudentCount).sum());
            }
            CompanyPaperStudentVO companyPaperStudentVO=companyPaperStudentVOMap.get(item.getId());
            if(companyPaperStudentVO!=null){
                companyStatisticVO.setPaperStudentCount(companyPaperStudentVO.getPaperStudentCount());
                companyStatisticVO.setPassStudentCount(companyPaperStudentVO.getPassStudentCount());
            }
            return companyStatisticVO;
        }).collect(Collectors.toList());
        return companyStatisticVOList;
    }
}
exam-system/src/main/java/com/gkhy/exam/system/service/impl/ExStudentServiceImpl.java
@@ -69,15 +69,22 @@
    @Override
    public ExStudent selectStudentById(Long studentId) {
        return baseMapper.selectStudentById(studentId);
        ExStudent student= baseMapper.selectStudentById(studentId);
        SysUser currentUser=SecurityUtils.getLoginUser().getUser();
        if(currentUser.getUserType().equals(UserTypeEnum.SYSTEM_USER.getCode())){
            return student;
        }
        if(!student.getCompanyId().equals(currentUser.getCompanyId())){
            throw new ApiException("无权限查看其它企业学员");
        }
        return student;
    }
    @Override
    public int insertStudent(ExStudent student) {
        SysUser currentUser= SecurityUtils.getLoginUser().getUser();
        if(currentUser.getUserType().equals(UserTypeEnum.SYSTEM_USER.getCode())){
            throw new ApiException("系统管理员不能新增学员");
        }
        checkUserAllowed(student);
        if(!checkPhoneUnique(student)){
            throw new ApiException("手机号已存在");
        }
@@ -94,6 +101,7 @@
    @Override
    public int updateStudent(ExStudent student) {
        checkUserAllowed(student);
        if(!checkPhoneUnique(student)){
            throw new ApiException("手机号已存在");
        }
@@ -112,6 +120,7 @@
    @Override
    public int deleteStudentById(Long studentId) {
        ExStudent existStudent=checkUserDataScope(studentId);
        checkUserAllowed(existStudent);
        int row=baseMapper.deleteByStudentId(studentId);
        if(row<0){
            throw new ApiException("删除学员失败");
@@ -153,6 +162,7 @@
    @Override
    public boolean resetUserPwd(ExStudent student) {
        ExStudent existStudent=getById(student.getId());
        checkUserAllowed(existStudent);
        ExStudent su=new ExStudent().setId(student.getId()).setPassword(SecurityUtils.encryptPassword(Base64.decodeStr(student.getPassword())));
        su.setUpdateBy(SecurityUtils.getUsername());
        delCacheByPhone(existStudent.getPhone());
@@ -170,4 +180,18 @@
        }
        return student;
    }
    public void checkUserAllowed(ExStudent student) {
        SysUser currentUser= SecurityUtils.getLoginUser().getUser();
        if(currentUser.getUserType().equals(UserTypeEnum.SYSTEM_USER.getCode())){
            throw new ApiException("系统管理员没有权限操作");
        }
        if(currentUser.getUserType().equals(UserTypeEnum.STUDENT.getCode())){
            throw new ApiException("没有权限操作");
        }
        if(!currentUser.getCompanyId().equals(student.getCompanyId())){
            throw new ApiException("没有权限操作其他企业学员");
        }
    }
}
exam-system/src/main/java/com/gkhy/exam/system/service/impl/SysCommonServiceImpl.java
@@ -1,23 +1,45 @@
package com.gkhy.exam.system.service.impl;
import cn.hutool.core.date.DateUtil;
import com.gkhy.exam.common.config.FilePathConfig;
import com.gkhy.exam.common.exception.ApiException;
import com.gkhy.exam.common.utils.M3u8Utils;
import com.gkhy.exam.common.utils.MinioUtils;
import com.gkhy.exam.system.domain.vo.UploadObjectVO;
import com.gkhy.exam.system.service.SysCommonService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;
import sun.misc.BASE64Decoder;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.util.Date;
import java.util.UUID;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.CountDownLatch;
@Service
@Slf4j
public class SysCommonServiceImpl implements SysCommonService {
    @Value("${image.upload_image}")
    private String uploadPath;
    @Autowired
    private M3u8Utils m3u8Utils;
    @Autowired
    private MinioUtils minioUtils;
    @Resource
    private FilePathConfig filePath;
    @Resource(name = "threadPoolTaskExecutor")
    private ThreadPoolTaskExecutor poolTaskExecutor;
    String projectUrl = System.getProperty("user.dir").replaceAll("\\\\", "/");
    @Override
    public UploadObjectVO uploadFile(MultipartFile file) {
@@ -44,6 +66,93 @@
    }
    @Override
    public String uploadVideo2M3u8(MultipartFile file) throws Exception {
        String path=m3u8Utils.mediaFileToM3u8(file);
        return upload2M3u8(path);
    }
    /**
     * 上传转码后得视频至OSS或minIOn
     * @param path
     * @return 路径
     * @throws Exception
     */
    public String upload2M3u8(String path) throws Exception {
        //存储转码后文件
        String realPath = path.substring(0, path.lastIndexOf("/"));
        log.info("视频解析后的 realPath {}", realPath);
        String name = path.substring(path.lastIndexOf("/") + 1);
        log.info("解析后视频 name {}", name);
        File allFile = new File(realPath);
        File[] files = allFile.listFiles();
        if (null == files || files.length == 0) {
            return null;
        }
        String patch = DateUtil.format(LocalDateTime.now(), "yyyy/MM/") + name.substring(0, name.lastIndexOf(".")) + "/";
        List<File> errorFile = new ArrayList<>();
        long start = System.currentTimeMillis();
//        //替换m3u8文件中的路径
//        FileUtil.replaceTextContent(path, name.substring(0, name.lastIndexOf(".")),
//                aliOssProperties.getMyHostUrl() + filePath.getProxy() + patch +
//                        name.substring(0, name.lastIndexOf(".")));
        //开始上传
        CountDownLatch countDownLatch = new CountDownLatch(files.length);
        Arrays.stream(files).forEach(li -> poolTaskExecutor.execute(() -> {
            try (FileInputStream fileInputStream = new FileInputStream(li)) {
                minioUtils.fileUploader(patch + li.getName(), fileInputStream);
                log.info("文件:{} 正在上传", li.getName());
            } catch (Exception e) {
                errorFile.add(li);
                e.printStackTrace();
            } finally {
                countDownLatch.countDown();
            }
        }));
        countDownLatch.await();
        long end = System.currentTimeMillis();
        log.info("解析文件上传成功,共计:{} 个文件,失败:{},共耗时: {}ms", files.length, errorFile.size(), end - start);
        //  try {
        //      minioComponent.mkBucket("m3u8");
        //  } catch (Exception e) {
        //      log.error("创建Bucket失败!");
        //  }
        //异步移除所有文件
        poolTaskExecutor.execute(() -> {
            deleteFile(projectUrl+filePath.getTempPath());
        });
        if (CollectionUtils.isEmpty(errorFile)) {
            return  filePath.getProxy() + patch + name;
        }
        return "";
    }
    public static void deleteFile(String path){
        File dest = new File(path);
        if (dest.isFile() && dest.exists()) {
            dest.delete();
        }
    }
    @Override
    public boolean uploadSlice(HttpServletRequest request, String guid, Integer chunk, MultipartFile file) {
        return false;
    }
    @Override
    public String uploadVideoMerge(String guid, String fileName) {
        return null;
    }
    @Override
    public String uploadMerge(String guid, String fileName) {
        return null;
    }
    @Override
    public UploadObjectVO doUpload(MultipartFile file){
        String originName=file.getOriginalFilename();
        String filename=originName;
exam-system/src/main/resources/mapper/system/ExExamPaperMapper.xml
@@ -50,6 +50,7 @@
        update ex_exam_paper set del_flag=1 where id=#{paperId}
    </update>
    <select id="selectExamPaperList" resultMap="ExamPaperResult">
        <include refid="selectExamPaperVo"/>
        <where>
exam-system/src/main/resources/mapper/system/ExExamRecordMapper.xml
对比新文件
@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.gkhy.exam.system.mapper.ExExamRecordMapper">
    <resultMap type="com.gkhy.exam.system.domain.ExExamRecord" id="ExamRecordResult">
        <result property="id"       column="id"       />
        <result property="companyId"    column="company_id"    />
        <result property="studentId"     column="student_id"     />
        <result property="planName"         column="plan_name"          />
        <result property="courseName"         column="course_name"          />
        <result property="level"         column="level"          />
        <result property="period"         column="period"          />
        <result property="actualPeriod"         column="actual_period"          />
        <result property="score"         column="score"          />
        <result property="companyId"         column="company_id"          />
        <result property="passed"         column="passed"          />
        <result property="createBy"       column="create_by"       />
        <result property="createTime"     column="create_time"     />
        <result property="updateBy"       column="update_by"       />
        <result property="updateTime"     column="update_time"     />
        <result property="remark"         column="remark"          />
        <result property="companyName"         column="company_name"          />
    </resultMap>
    <sql id="selectExamRecordVo">
        select a.id, a.company_id, a.student_id, a.plan_name, a.course_name,a.level,a.period,a.actual_period,a.score,
               a.company_id,a.passed, a.create_by, a.create_time, a.update_by, a.update_time, a.remark,b.name as company_name
        from ex_exam_record a
        left join sys_company b on b.id=a.company_id
    </sql>
    <select id="selectExamRecordList" resultMap="ExamRecordResult">
        <include refid="selectExamRecordVo"/>
        <where>
            <if test="planName != null and planName != ''">
                AND a.plan_name like concat('%', #{planName}, '%')
            </if>
            <if test="companyId != null ">
                AND a.company_id =#{companyId}
            </if>
        </where>
        order by a.id desc
    </select>
    <select id="selectExamRecordById" resultMap="ExamRecordResult">
        <include refid="selectExamRecordVo"/>
        where a.id=#{recordId}
    </select>
</mapper>
exam-system/src/main/resources/mapper/system/ExPaperStudentMapper.xml
@@ -57,6 +57,7 @@
        left join ex_student b on a.student_id=b.id
        left join ex_exam_paper c on c.id=a.paper_id
        <where>
            and c.del_flag=0
            <if test="paperId!=null'">
                and a.paper_id=#{paperId}
            </if>
exam-system/src/main/resources/mapper/system/SysCompanyMapper.xml
@@ -34,8 +34,11 @@
            <if test="creditCode != null and creditCode != ''">
                AND credit_code like concat('%', #{creditCode}, '%')
            </if>
            <if test="id!=null">
                AND id=#{id}
            </if>
        </where>
        order by create_time desc
        order by id desc
    </select>
    <select id="selectCompanyById" resultMap="SysCompanyResult">
@@ -52,4 +55,101 @@
    <select id="checkNameUnique" resultMap="SysCompanyResult">
        select id,name from sys_company where name=#{name} and del_flag=0 limit 1
    </select>
    <select id="getOnlineCompanyPhaseCount" resultType="com.gkhy.exam.system.domain.vo.CompanyPhaseVO">
        select count(a.id) as phase_count,a.level,a.company_id from ex_course_phase a
        inner join sys_company b on b.id=a.company_id
        where a.del_flag=0 and b.del_flag=0 and a.company_id in
        <foreach collection="companyIds" item="companyId" open="(" separator="," close=")">
            #{companyId}
        </foreach>
        <if test="startTime!=null and startTime!=''">
            and a.create_time &gt;= #{startTime}
        </if>
        <if test="endTime!=null and endTime!=''">
            and a.create_time &lt;= #{endTime}
        </if>
        group by a.company_id,a.level
    </select>
    <select id="getOnlineCompanyPhaseStudentCount" resultType="com.gkhy.exam.system.domain.vo.CompanyPhaseStudentVO">
        select count(1) as phase_student_count,b.company_id,b.level from ex_phase_student a
        inner join ex_course_phase b on b.id=a.phase_id
        where b.del_flag=0 and b.company_id in
        <foreach collection="companyIds" item="companyId" open="(" separator="," close=")">
            #{companyId}
        </foreach>
        <if test="startTime!=null and startTime!=''">
            and b.create_time &gt;= #{startTime}
        </if>
        <if test="endTime!=null and endTime!=''">
            and b.create_time &lt;= #{endTime}
        </if>
        group by b.company_id,b.level
    </select>
    <select id="getOnlineCompanyPaperStudentCount" resultType="com.gkhy.exam.system.domain.vo.CompanyPaperStudentVO">
        select count(a.id) as paper_student_count,sum(a.passed) as pass_student_count,b.company_id from ex_paper_student a
        inner join ex_exam_paper b on b.id=a.paper_id
        where b.del_flag=0 and b.company_id in
        <foreach collection="companyIds" item="companyId" open="(" separator="," close=")">
            #{companyId}
        </foreach>
        <if test="startTime!=null and startTime!=''">
            and b.create_time &gt;= #{startTime}
        </if>
        <if test="endTime!=null and endTime!=''">
            and b.create_time &lt;= #{endTime}
        </if>
        group by b.company_id
    </select>
    <select id="getOfflineCompanyPhaseCount" resultType="com.gkhy.exam.system.domain.vo.CompanyPhaseVO">
        select count(f.plan_name)as phase_count,f.company_id,f.level  from (
        select a.plan_name,a.company_id,a.level from ex_exam_record a
        inner join sys_company b on b.id=a.company_id
        where b.del_flag=0 and a.company_id in
        <foreach collection="companyIds" item="companyId" open="(" separator="," close=")">
            #{companyId}
        </foreach>
        <if test="startTime!=null and startTime!=''">
            and a.create_time &gt;= #{startTime}
        </if>
        <if test="endTime!=null and endTime!=''">
            and a.create_time &lt;= #{endTime}
        </if>
        group by a.company_id,a.level,a.plan_name
        ) as f group by f.company_id,f.level
    </select>
    <select id="getOfflineCompanyPhaseStudentCount" resultType="com.gkhy.exam.system.domain.vo.CompanyPhaseStudentVO">
        select count(1) as phase_student_count,b.company_id,b.level from ex_exam_record a
        inner join sys_company b on b.id=a.company_id
        where b.del_flag=0 and a.company_id in
        <foreach collection="companyIds" item="companyId" open="(" separator="," close=")">
            #{companyId}
        </foreach>
        <if test="startTime!=null and startTime!=''">
            and a.create_time &gt;= #{startTime}
        </if>
        <if test="endTime!=null and endTime!=''">
            and a.create_time &lt;= #{endTime}
        </if>
        group by a.company_id,a.level
    </select>
    <select id="getOfflineCompanyPaperStudentCount" resultType="com.gkhy.exam.system.domain.vo.CompanyPaperStudentVO">
        select count(a.id) as paper_student_count,sum(a.passed) as pass_student_count,a.company_id from ex_exam_record a
        inner join sys_company b on b.id=a.paper_id
        where b.del_flag=0 and score is not null and a.company_id in
        <foreach collection="companyIds" item="companyId" open="(" separator="," close=")">
            #{companyId}
        </foreach>
        <if test="startTime!=null and startTime!=''">
            and a.create_time &gt;= #{startTime}
        </if>
        <if test="endTime!=null and endTime!=''">
            and a.create_time &lt;= #{endTime}
        </if>
        group by a.company_id
    </select>
</mapper>
exam-system/src/test/java/com/gkhy/exam/system/MybatisPlusGenerator.java
@@ -16,7 +16,7 @@
        String model="/exam-system";
        // 数据库配置
        DataSourceConfig.Builder dataSourceConfigBuilder = new DataSourceConfig
                .Builder("jdbc:mysql://192.168.0.23:7006/train_exam" +
                .Builder("jdbc:mysql://192.168.2.16:7006/train_exam" +
                "?useSSL=false&allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&autoReconnect=true"
                , "root", "2farwL3yPXfbH2AP");
        FastAutoGenerator.create(dataSourceConfigBuilder)
pom.xml
@@ -40,6 +40,7 @@
        <minio.version>8.4.5</minio.version>
        <kaptcha.version>2.3.3</kaptcha.version>
        <bitwalker.version>1.21</bitwalker.version>
        <ffmpeg.version>0.7.0</ffmpeg.version>
    </properties>
    <dependencyManagement>
        <dependencies>
@@ -69,7 +70,6 @@
                <groupId>com.github.pagehelper</groupId>
                <artifactId>pagehelper-spring-boot-starter</artifactId>
                <version>${pagehelper.version}</version>
            </dependency>
            <!--Hutool Java工具包-->
            <dependency>
@@ -151,6 +151,12 @@
                <version>${bitwalker.version}</version>
            </dependency>
            <dependency>
                <groupId>net.bramp.ffmpeg</groupId>
                <artifactId>ffmpeg</artifactId>
                <version>${ffmpeg.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>