ly преди 1 година
родител
ревизия
761d25dd21
променени са 95 файла, в които са добавени 12022 реда и са изтрити 98 реда
  1. 13 0
      master/src/main/java/com/ruoyi/framework/job/enums/JobGroup.java
  2. 14 0
      master/src/main/java/com/ruoyi/framework/job/enums/JobPrefix.java
  3. 53 0
      master/src/main/java/com/ruoyi/framework/job/service/JobService.java
  4. 124 0
      master/src/main/java/com/ruoyi/framework/job/service/impl/JobServiceImpl.java
  5. 9 1
      master/src/main/java/com/ruoyi/project/plant/controller/TConfInfoController.java
  6. 3 2
      master/src/main/java/com/ruoyi/project/plant/controller/TMtMeetingController.java
  7. 2 2
      master/src/main/java/com/ruoyi/project/plant/controller/TMtdDailyController.java
  8. 4 0
      master/src/main/java/com/ruoyi/project/sems/controller/TApproveController.java
  9. 103 0
      master/src/main/java/com/ruoyi/project/training/bccnew/controller/TTsFirstplanTmplController.java
  10. 103 0
      master/src/main/java/com/ruoyi/project/training/bccnew/controller/TTsNewController.java
  11. 291 0
      master/src/main/java/com/ruoyi/project/training/bccnew/domain/TTsFirstplanTmpl.java
  12. 263 0
      master/src/main/java/com/ruoyi/project/training/bccnew/domain/TTsNew.java
  13. 63 0
      master/src/main/java/com/ruoyi/project/training/bccnew/mapper/TTsFirstplanTmplMapper.java
  14. 63 0
      master/src/main/java/com/ruoyi/project/training/bccnew/mapper/TTsNewMapper.java
  15. 61 0
      master/src/main/java/com/ruoyi/project/training/bccnew/service/ITTsFirstplanTmplService.java
  16. 61 0
      master/src/main/java/com/ruoyi/project/training/bccnew/service/ITTsNewService.java
  17. 93 0
      master/src/main/java/com/ruoyi/project/training/bccnew/service/impl/TTsFirstplanTmplServiceImpl.java
  18. 93 0
      master/src/main/java/com/ruoyi/project/training/bccnew/service/impl/TTsNewServiceImpl.java
  19. 103 0
      master/src/main/java/com/ruoyi/project/training/elearn/controller/TElExamController.java
  20. 122 0
      master/src/main/java/com/ruoyi/project/training/elearn/controller/TElPaperController.java
  21. 103 0
      master/src/main/java/com/ruoyi/project/training/elearn/controller/TElQuController.java
  22. 103 0
      master/src/main/java/com/ruoyi/project/training/elearn/controller/TElRepoController.java
  23. 292 0
      master/src/main/java/com/ruoyi/project/training/elearn/domain/TElExam.java
  24. 216 0
      master/src/main/java/com/ruoyi/project/training/elearn/domain/TElExamRepo.java
  25. 335 0
      master/src/main/java/com/ruoyi/project/training/elearn/domain/TElPaper.java
  26. 163 0
      master/src/main/java/com/ruoyi/project/training/elearn/domain/TElPaperQu.java
  27. 135 0
      master/src/main/java/com/ruoyi/project/training/elearn/domain/TElPaperQuAnswer.java
  28. 228 0
      master/src/main/java/com/ruoyi/project/training/elearn/domain/TElQu.java
  29. 208 0
      master/src/main/java/com/ruoyi/project/training/elearn/domain/TElQuAnswer.java
  30. 94 0
      master/src/main/java/com/ruoyi/project/training/elearn/domain/TElQuRepo.java
  31. 194 0
      master/src/main/java/com/ruoyi/project/training/elearn/domain/TElRepo.java
  32. 46 0
      master/src/main/java/com/ruoyi/project/training/elearn/job/BreakExamJob.java
  33. 63 0
      master/src/main/java/com/ruoyi/project/training/elearn/mapper/TElExamMapper.java
  34. 64 0
      master/src/main/java/com/ruoyi/project/training/elearn/mapper/TElExamRepoMapper.java
  35. 63 0
      master/src/main/java/com/ruoyi/project/training/elearn/mapper/TElPaperMapper.java
  36. 63 0
      master/src/main/java/com/ruoyi/project/training/elearn/mapper/TElPaperQuAnswerMapper.java
  37. 63 0
      master/src/main/java/com/ruoyi/project/training/elearn/mapper/TElPaperQuMapper.java
  38. 62 0
      master/src/main/java/com/ruoyi/project/training/elearn/mapper/TElQuAnswerMapper.java
  39. 65 0
      master/src/main/java/com/ruoyi/project/training/elearn/mapper/TElQuMapper.java
  40. 63 0
      master/src/main/java/com/ruoyi/project/training/elearn/mapper/TElQuRepoMapper.java
  41. 63 0
      master/src/main/java/com/ruoyi/project/training/elearn/mapper/TElRepoMapper.java
  42. 61 0
      master/src/main/java/com/ruoyi/project/training/elearn/service/ITElExamService.java
  43. 63 0
      master/src/main/java/com/ruoyi/project/training/elearn/service/ITElPaperService.java
  44. 61 0
      master/src/main/java/com/ruoyi/project/training/elearn/service/ITElQuAnswerService.java
  45. 61 0
      master/src/main/java/com/ruoyi/project/training/elearn/service/ITElQuService.java
  46. 61 0
      master/src/main/java/com/ruoyi/project/training/elearn/service/ITElRepoService.java
  47. 126 0
      master/src/main/java/com/ruoyi/project/training/elearn/service/impl/TElExamServiceImpl.java
  48. 297 0
      master/src/main/java/com/ruoyi/project/training/elearn/service/impl/TElPaperServiceImpl.java
  49. 93 0
      master/src/main/java/com/ruoyi/project/training/elearn/service/impl/TElQuAnswerServiceImpl.java
  50. 251 0
      master/src/main/java/com/ruoyi/project/training/elearn/service/impl/TElQuServiceImpl.java
  51. 93 0
      master/src/main/java/com/ruoyi/project/training/elearn/service/impl/TElRepoServiceImpl.java
  52. 1 1
      master/src/main/resources/application.yml
  53. 1 0
      master/src/main/resources/mybatis/plant/TMtActionlistMapper.xml
  54. 1 0
      master/src/main/resources/mybatis/plant/TMtEhsopenitemMapper.xml
  55. 1 0
      master/src/main/resources/mybatis/plant/TMtInterlockMapper.xml
  56. 1 0
      master/src/main/resources/mybatis/plant/TMtKeymaintenanceMapper.xml
  57. 1 0
      master/src/main/resources/mybatis/plant/TMtMessageattentionMapper.xml
  58. 1 0
      master/src/main/resources/mybatis/plant/TMtOpextrackMapper.xml
  59. 1 0
      master/src/main/resources/mybatis/plant/TMtRiskreminderMapper.xml
  60. 146 0
      master/src/main/resources/mybatis/training/bccnew/TTsFirstplanTmplMapper.xml
  61. 136 0
      master/src/main/resources/mybatis/training/bccnew/TTsNewMapper.xml
  62. 146 0
      master/src/main/resources/mybatis/training/elearn/TElExamMapper.xml
  63. 117 0
      master/src/main/resources/mybatis/training/elearn/TElExamRepoMapper.xml
  64. 166 0
      master/src/main/resources/mybatis/training/elearn/TElPaperMapper.xml
  65. 95 0
      master/src/main/resources/mybatis/training/elearn/TElPaperQuAnswerMapper.xml
  66. 105 0
      master/src/main/resources/mybatis/training/elearn/TElPaperQuMapper.xml
  67. 116 0
      master/src/main/resources/mybatis/training/elearn/TElQuAnswerMapper.xml
  68. 126 0
      master/src/main/resources/mybatis/training/elearn/TElQuMapper.xml
  69. 78 0
      master/src/main/resources/mybatis/training/elearn/TElQuRepoMapper.xml
  70. 114 0
      master/src/main/resources/mybatis/training/elearn/TElRepoMapper.xml
  71. 53 0
      ui/src/api/training/bccnew/firstPlanTmpl.js
  72. 53 0
      ui/src/api/training/bccnew/tsnew.js
  73. 53 0
      ui/src/api/training/elearn/answer.js
  74. 53 0
      ui/src/api/training/elearn/exam.js
  75. 63 0
      ui/src/api/training/elearn/paper.js
  76. 53 0
      ui/src/api/training/elearn/qu.js
  77. 53 0
      ui/src/api/training/elearn/repo.js
  78. 76 0
      ui/src/components/RepoSelect/index.vue
  79. 20 0
      ui/src/router/index.js
  80. 12 21
      ui/src/views/components/meeting/ehsopenitem.vue
  81. 1 1
      ui/src/views/components/meeting/keymaintenance.vue
  82. 1 1
      ui/src/views/components/meeting/messageattention.vue
  83. 126 68
      ui/src/views/plant/confInfo/index.vue
  84. 0 1
      ui/src/views/plant/confInfo/list.vue
  85. 606 0
      ui/src/views/training/bccnew/firstPlanTmpl/index.vue
  86. 3 0
      ui/src/views/training/bccnew/index.vue
  87. 776 0
      ui/src/views/training/bccnew/tsnew/index.vue
  88. 467 0
      ui/src/views/training/elearn/answer/index.vue
  89. 658 0
      ui/src/views/training/elearn/exam/index.vue
  90. 3 0
      ui/src/views/training/elearn/index.vue
  91. 675 0
      ui/src/views/training/elearn/paper/index.vue
  92. 296 0
      ui/src/views/training/elearn/paper/list.vue
  93. 113 0
      ui/src/views/training/elearn/paper/preview.vue
  94. 512 0
      ui/src/views/training/elearn/qu/index.vue
  95. 449 0
      ui/src/views/training/elearn/repo/index.vue

+ 13 - 0
master/src/main/java/com/ruoyi/framework/job/enums/JobGroup.java

@@ -0,0 +1,13 @@
+package com.ruoyi.framework.job.enums;
+
+/**
+ * 任务分组
+ * @author van
+ */
+public interface JobGroup {
+
+    /**
+     * 系统任务
+     */
+    String SYSTEM = "system";
+}

+ 14 - 0
master/src/main/java/com/ruoyi/framework/job/enums/JobPrefix.java

@@ -0,0 +1,14 @@
+package com.ruoyi.framework.job.enums;
+
+/**
+ * 任务前缀
+ * @author bool
+ */
+public interface JobPrefix {
+
+    /**
+     * 强制交卷的
+     */
+    String BREAK_EXAM = "break_exam_";
+
+}

+ 53 - 0
master/src/main/java/com/ruoyi/framework/job/service/JobService.java

@@ -0,0 +1,53 @@
+package com.ruoyi.framework.job.service;
+
+/**
+ * 任务业务类,用于动态处理任务信息
+ * @author bool
+ * @date 2020/11/29 下午2:17
+ */
+public interface JobService {
+
+
+    /**
+     * 任务数据
+     */
+    String TASK_DATA = "taskData";
+
+    /**
+     * 添加定时任务
+     * @param jobClass
+     * @param jobName
+     * @param cron
+     * @param data
+     */
+    void addCronJob(Class jobClass, String jobName, String cron, String data);
+
+    /**
+     * 添加立即执行的任务
+     * @param jobClass
+     * @param jobName
+     * @param data
+     */
+    void addCronJob(Class jobClass, String jobName, String data);
+
+    /**
+     * 暂停任务
+     * @param jobName
+     * @param jobGroup
+     */
+    void pauseJob(String jobName, String jobGroup);
+
+    /**
+     * 恢复任务
+     * @param triggerName
+     * @param triggerGroup
+     */
+    void resumeJob(String triggerName, String triggerGroup);
+
+    /**
+     * 删除job
+     * @param jobName
+     * @param jobGroup
+     */
+    void deleteJob(String jobName, String jobGroup);
+}

+ 124 - 0
master/src/main/java/com/ruoyi/framework/job/service/impl/JobServiceImpl.java

@@ -0,0 +1,124 @@
+package com.ruoyi.framework.job.service.impl;
+
+import com.alibaba.fastjson.JSON;
+import com.baomidou.mybatisplus.core.toolkit.IdWorker;
+
+import com.ruoyi.framework.job.enums.JobGroup;
+import com.ruoyi.framework.job.service.JobService;
+import lombok.extern.log4j.Log4j2;
+import org.quartz.*;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.quartz.SchedulerFactoryBean;
+import org.springframework.stereotype.Service;
+import org.springframework.util.StringUtils;
+
+/**
+ * @author bool
+ */
+@Log4j2
+@Service
+public class JobServiceImpl implements JobService {
+
+    /**
+     * Quartz定时任务核心的功能实现类
+     */
+    private Scheduler scheduler;
+
+    /**
+     * 注入
+     * @param schedulerFactoryBean
+     */
+    public JobServiceImpl(@Autowired SchedulerFactoryBean schedulerFactoryBean) {
+        scheduler = schedulerFactoryBean.getScheduler();
+    }
+
+
+    @Override
+    public void addCronJob(Class jobClass, String jobName, String cron, String data) {
+
+
+        String jobGroup = JobGroup.SYSTEM;
+
+        // 自动命名
+        if(StringUtils.isEmpty(jobName)){
+            jobName = jobClass.getSimpleName().toUpperCase() + "_"+IdWorker.getIdStr();
+        }
+
+        try {
+            JobKey jobKey = JobKey.jobKey(jobName, jobGroup);
+            JobDetail jobDetail = scheduler.getJobDetail(jobKey);
+            if (jobDetail != null) {
+                log.info("++++++++++任务:{} 已存在", jobName);
+                this.deleteJob(jobName, jobGroup);
+            }
+
+            log.info("++++++++++构建任务:{},{},{},{},{} ", jobClass.toString(), jobName, jobGroup, cron, data);
+
+            //构建job信息
+            jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroup).build();
+            //用JopDataMap来传递数据
+            jobDetail.getJobDataMap().put(TASK_DATA, data);
+
+            //按新的cronExpression表达式构建一个新的trigger
+            Trigger trigger = null;
+
+            // 有表达式的按表达式
+            if(!StringUtils.isEmpty(cron)){
+                log.info("+++++表达式执行:"+ JSON.toJSONString(jobDetail));
+                //表达式调度构建器
+                CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cron);
+                trigger = TriggerBuilder.newTrigger().withIdentity(jobName, jobGroup).withSchedule(scheduleBuilder).build();
+            }else{
+                // 无表达式则立即执行
+                log.info("+++++立即执行:"+ JSON.toJSONString(jobDetail));
+                trigger = TriggerBuilder.newTrigger().withIdentity(jobName, jobGroup).startNow().build();
+            }
+
+            scheduler.scheduleJob(jobDetail, trigger);
+
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+
+    @Override
+    public void addCronJob(Class jobClass, String jobName, String data) {
+        // 立即执行任务
+        this.addCronJob(jobClass, jobName, null, data);
+    }
+
+
+    @Override
+    public void pauseJob(String jobName, String jobGroup) {
+        try {
+            TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);
+            scheduler.pauseTrigger(triggerKey);
+            log.info("++++++++++暂停任务:{}", jobName);
+        } catch (SchedulerException e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Override
+    public void resumeJob(String jobName, String jobGroup) {
+        try {
+            TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);
+            scheduler.resumeTrigger(triggerKey);
+            log.info("++++++++++重启任务:{}", jobName);
+        } catch (SchedulerException e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Override
+    public void deleteJob(String jobName, String jobGroup) {
+        try {
+            JobKey jobKey = JobKey.jobKey(jobName,jobGroup);
+            scheduler.deleteJob(jobKey);
+            log.info("++++++++++删除任务:{}", jobKey);
+        } catch (SchedulerException e) {
+            e.printStackTrace();
+        }
+    }
+}

+ 9 - 1
master/src/main/java/com/ruoyi/project/plant/controller/TConfInfoController.java

@@ -1,6 +1,9 @@
 package com.ruoyi.project.plant.controller;
 
 import java.util.List;
+
+import com.ruoyi.project.plant.domain.TConfRoom;
+import com.ruoyi.project.plant.service.ITConfRoomService;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -32,7 +35,8 @@ public class TConfInfoController extends BaseController
 {
     @Autowired
     private ITConfInfoService tConfInfoService;
-
+    @Autowired
+    private ITConfRoomService tConfRoomService;
     /**
      * 查询会议预约信息列表
      */
@@ -76,6 +80,8 @@ public class TConfInfoController extends BaseController
     @PostMapping
     public AjaxResult add(@RequestBody TConfInfo tConfInfo)
     {
+        TConfRoom room = tConfRoomService.selectTConfRoomById(tConfInfo.getRoomId());
+        tConfInfo.setRoomName(room.getRoomName());
         return toAjax(tConfInfoService.insertTConfInfo(tConfInfo));
     }
 
@@ -87,6 +93,8 @@ public class TConfInfoController extends BaseController
     @PutMapping
     public AjaxResult edit(@RequestBody TConfInfo tConfInfo)
     {
+        TConfRoom room = tConfRoomService.selectTConfRoomById(tConfInfo.getRoomId());
+        tConfInfo.setRoomName(room.getRoomName());
         return toAjax(tConfInfoService.updateTConfInfo(tConfInfo));
     }
 

+ 3 - 2
master/src/main/java/com/ruoyi/project/plant/controller/TMtMeetingController.java

@@ -182,7 +182,8 @@ public class TMtMeetingController extends BaseController {
             // 生成word的路径
             String fileDir = RuoYiConfig.getProfile() + "/" + "plant/meeting";
             // 生成word的文件名称
-            String fileName = "装置周会议" + meetingId + ".docx";
+            TMtMeeting tMtMeeting = tMtMeetingService.selectTMtMeetingById(meetingId);
+            String fileName = DateUtils.parseDateToStr("YYYY-MM-dd", tMtMeeting.getMeetingDate()) +"weekMeeting" + meetingId + ".docx";
             String filePath = fileDir + "/" + fileName;
             File dir = new File(fileDir);
             if (!dir.exists()) {
@@ -439,7 +440,7 @@ public class TMtMeetingController extends BaseController {
             logger.info("发送人:" + JSON.toJSONString(email));
             logger.info("抄送人:" + JSON.toJSONString(emailCc));
 
-            mailService.sendAttachmentsMail(email, "CPMS:您有一条" + formattedDate + "装置周会议信息", html, emailCc, filePath);
+            mailService.sendAttachmentsMail(email, "周会议:您有一条" + formattedDate + "装置周会议信息", html, emailCc, filePath);
             tMtMeeting.setEmailStatus(1);
             return AjaxResult.success();
         } catch (Exception e) {

+ 2 - 2
master/src/main/java/com/ruoyi/project/plant/controller/TMtdDailyController.java

@@ -298,7 +298,7 @@ public class TMtdDailyController extends BaseController {
             logger.info("抄送人:" + emailCc.toString());
             logger.info("文件地址:" + filePath);
 
-            mailService.sendAttachmentsMail(email, "CPMS:您有一条" + formattedDate + "装置调度会议信息", html, emailCc, filePath);
+            mailService.sendAttachmentsMail(email, "调度会:您有一条" + formattedDate + "装置调度会议信息", html, emailCc, filePath);
             daily.setEmailStatus(1);
             return AjaxResult.success();
         } catch (Exception e) {
@@ -382,7 +382,7 @@ public class TMtdDailyController extends BaseController {
         // 生成word的路径
         String fileDir = RuoYiConfig.getProfile() + "/" + "plant/dailymeeting";
         // 生成word的文件名称
-        String fileName = DateUtils.parseDateToStr("YYYY-MM-dd", tMtdDaily.getMeetingDate()) + "装置调度会议" + tMtdDaily.getId() + ".docx";
+        String fileName = DateUtils.parseDateToStr("YYYY-MM-dd", tMtdDaily.getMeetingDate()) + "Coordinating " + tMtdDaily.getId() + ".docx";
         String wordPath = this.createWord(templatePath, fileDir, fileName, params);
         return wordPath;
     }

+ 4 - 0
master/src/main/java/com/ruoyi/project/sems/controller/TApproveController.java

@@ -17,6 +17,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
 import com.itextpdf.text.Document;
 import com.itextpdf.text.pdf.PdfWriter;
 import com.ruoyi.common.utils.ServletUtils;
+import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.document.DocumentHandler;
 import com.ruoyi.common.utils.document.PDFTemplateUtil;
 import com.ruoyi.common.utils.spring.SpringUtils;
@@ -870,6 +871,9 @@ public class TApproveController extends BaseController {
      */
     @RequestMapping("/month")
     public AjaxResult month(@RequestBody TApprove tApprove) {
+        if (tApprove.getMechanical() == null || tApprove.getElectric()==null || tApprove.getCraft()== null) {
+           return AjaxResult.error("缺少审批人");
+        }
         //任务开始时间
         long startTime = System.currentTimeMillis();
         logger.info("任务申请" + JSON.toJSONString(tApprove));

+ 103 - 0
master/src/main/java/com/ruoyi/project/training/bccnew/controller/TTsFirstplanTmplController.java

@@ -0,0 +1,103 @@
+package com.ruoyi.project.training.bccnew.controller;
+
+import java.util.List;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.project.training.bccnew.domain.TTsFirstplanTmpl;
+import com.ruoyi.project.training.bccnew.service.ITTsFirstplanTmplService;
+import com.ruoyi.framework.web.controller.BaseController;
+import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.framework.web.page.TableDataInfo;
+
+/**
+ * 进组培训模版Controller
+ *
+ * @author ssy
+ * @date 2024-05-22
+ */
+@RestController
+@RequestMapping("/bccnew/firstPlanTmpl")
+public class TTsFirstplanTmplController extends BaseController
+{
+    @Autowired
+    private ITTsFirstplanTmplService tTsFirstplanTmplService;
+
+    /**
+     * 查询进组培训模版列表
+     */
+    @PreAuthorize("@ss.hasPermi('bccnew:firstPlanTmpl:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(TTsFirstplanTmpl tTsFirstplanTmpl)
+    {
+        startPage();
+        List<TTsFirstplanTmpl> list = tTsFirstplanTmplService.selectTTsFirstplanTmplList(tTsFirstplanTmpl);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出进组培训模版列表
+     */
+    @PreAuthorize("@ss.hasPermi('bccnew:firstPlanTmpl:export')")
+    @Log(title = "进组培训模版", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(TTsFirstplanTmpl tTsFirstplanTmpl)
+    {
+        List<TTsFirstplanTmpl> list = tTsFirstplanTmplService.selectTTsFirstplanTmplList(tTsFirstplanTmpl);
+        ExcelUtil<TTsFirstplanTmpl> util = new ExcelUtil<TTsFirstplanTmpl>(TTsFirstplanTmpl.class);
+        return util.exportExcel(list, "firstPlanTmpl");
+    }
+
+    /**
+     * 获取进组培训模版详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('bccnew:firstPlanTmpl:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return AjaxResult.success(tTsFirstplanTmplService.selectTTsFirstplanTmplById(id));
+    }
+
+    /**
+     * 新增进组培训模版
+     */
+    @PreAuthorize("@ss.hasPermi('bccnew:firstPlanTmpl:add')")
+    @Log(title = "进组培训模版", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody TTsFirstplanTmpl tTsFirstplanTmpl)
+    {
+        return toAjax(tTsFirstplanTmplService.insertTTsFirstplanTmpl(tTsFirstplanTmpl));
+    }
+
+    /**
+     * 修改进组培训模版
+     */
+    @PreAuthorize("@ss.hasPermi('bccnew:firstPlanTmpl:edit')")
+    @Log(title = "进组培训模版", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody TTsFirstplanTmpl tTsFirstplanTmpl)
+    {
+        return toAjax(tTsFirstplanTmplService.updateTTsFirstplanTmpl(tTsFirstplanTmpl));
+    }
+
+    /**
+     * 删除进组培训模版
+     */
+    @PreAuthorize("@ss.hasPermi('bccnew:firstPlanTmpl:remove')")
+    @Log(title = "进组培训模版", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(tTsFirstplanTmplService.deleteTTsFirstplanTmplByIds(ids));
+    }
+}

+ 103 - 0
master/src/main/java/com/ruoyi/project/training/bccnew/controller/TTsNewController.java

@@ -0,0 +1,103 @@
+package com.ruoyi.project.training.bccnew.controller;
+
+import java.util.List;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.project.training.bccnew.domain.TTsNew;
+import com.ruoyi.project.training.bccnew.service.ITTsNewService;
+import com.ruoyi.framework.web.controller.BaseController;
+import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.framework.web.page.TableDataInfo;
+
+/**
+ * 导师带徒Controller
+ *
+ * @author ssy
+ * @date 2024-05-20
+ */
+@RestController
+@RequestMapping("/bccnew/tsnew")
+public class TTsNewController extends BaseController
+{
+    @Autowired
+    private ITTsNewService tTsNewService;
+
+    /**
+     * 查询导师带徒列表
+     */
+    @PreAuthorize("@ss.hasPermi('bccnew:tsnew:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(TTsNew tTsNew)
+    {
+        startPage();
+        List<TTsNew> list = tTsNewService.selectTTsNewList(tTsNew);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出导师带徒列表
+     */
+    @PreAuthorize("@ss.hasPermi('bccnew:tsnew:export')")
+    @Log(title = "导师带徒", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(TTsNew tTsNew)
+    {
+        List<TTsNew> list = tTsNewService.selectTTsNewList(tTsNew);
+        ExcelUtil<TTsNew> util = new ExcelUtil<TTsNew>(TTsNew.class);
+        return util.exportExcel(list, "tsnew");
+    }
+
+    /**
+     * 获取导师带徒详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('bccnew:tsnew:query')")
+    @GetMapping(value = "/{newId}")
+    public AjaxResult getInfo(@PathVariable("newId") Long newId)
+    {
+        return AjaxResult.success(tTsNewService.selectTTsNewById(newId));
+    }
+
+    /**
+     * 新增导师带徒
+     */
+    @PreAuthorize("@ss.hasPermi('bccnew:tsnew:add')")
+    @Log(title = "导师带徒", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody TTsNew tTsNew)
+    {
+        return toAjax(tTsNewService.insertTTsNew(tTsNew));
+    }
+
+    /**
+     * 修改导师带徒
+     */
+    @PreAuthorize("@ss.hasPermi('bccnew:tsnew:edit')")
+    @Log(title = "导师带徒", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody TTsNew tTsNew)
+    {
+        return toAjax(tTsNewService.updateTTsNew(tTsNew));
+    }
+
+    /**
+     * 删除导师带徒
+     */
+    @PreAuthorize("@ss.hasPermi('bccnew:tsnew:remove')")
+    @Log(title = "导师带徒", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{newIds}")
+    public AjaxResult remove(@PathVariable Long[] newIds)
+    {
+        return toAjax(tTsNewService.deleteTTsNewByIds(newIds));
+    }
+}

+ 291 - 0
master/src/main/java/com/ruoyi/project/training/bccnew/domain/TTsFirstplanTmpl.java

@@ -0,0 +1,291 @@
+package com.ruoyi.project.training.bccnew.domain;
+
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import com.ruoyi.framework.web.domain.BaseEntity;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+/**
+ * 进组培训模版对象 t_ts_firstplan_tmpl
+ *
+ * @author ssy
+ * @date 2024-05-22
+ */
+public class TTsFirstplanTmpl extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 唯一标识ID */
+    private Long id;
+
+    /** 培训员工编号 */
+    @Excel(name = "培训员工编号")
+    private Long newId;
+
+    /** 课程编号 */
+    @Excel(name = "课程编号")
+    private String courseCode;
+
+    /** 培训主题 */
+    @Excel(name = "培训主题")
+    private String topic;
+
+    /** 培训内容 */
+    @Excel(name = "培训内容")
+    private String content;
+
+    /** 培训天 */
+    @Excel(name = "培训天")
+    private Long courseDay;
+
+    /** 培训小时 */
+    @Excel(name = "培训小时")
+    private Long courseHour;
+
+    /** 培训类型 */
+    @Excel(name = "培训类型")
+    private String courseType;
+
+    /** 讲师 */
+    @Excel(name = "讲师")
+    private String trainer;
+
+    /** 培训日期 */
+    @JsonFormat(pattern = "yyyy-MM-dd" , timezone = "GMT+8")
+    @Excel(name = "培训日期", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date courseDate;
+
+    /** 考核情况 */
+    @Excel(name = "考核情况")
+    private String assess;
+
+    /** 删除状态 */
+    private Long delFlag;
+
+    /** 创建人 */
+    @Excel(name = "创建人")
+    private String createrCode;
+
+    /** 创建时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd" , timezone = "GMT+8")
+    @Excel(name = "创建时间", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date createdate;
+
+    /** 修改人 */
+    @Excel(name = "修改人")
+    private String updaterCode;
+
+    /** 修改时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd" , timezone = "GMT+8")
+    @Excel(name = "修改时间", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date updatedate;
+
+    /** 部门编号 */
+    @Excel(name = "部门编号")
+    private Long deptId;
+
+    /** 部门名称 */
+    @Excel(name = "部门名称")
+    private String deptName;
+
+    /** 备注 */
+    @Excel(name = "备注")
+    private String remarks;
+
+    public void setId(Long id)
+    {
+        this.id = id;
+    }
+
+    public Long getId()
+    {
+        return id;
+    }
+    public void setNewId(Long newId)
+    {
+        this.newId = newId;
+    }
+
+    public Long getNewId()
+    {
+        return newId;
+    }
+    public void setCourseCode(String courseCode)
+    {
+        this.courseCode = courseCode;
+    }
+
+    public String getCourseCode()
+    {
+        return courseCode;
+    }
+    public void setTopic(String topic)
+    {
+        this.topic = topic;
+    }
+
+    public String getTopic()
+    {
+        return topic;
+    }
+    public void setContent(String content)
+    {
+        this.content = content;
+    }
+
+    public String getContent()
+    {
+        return content;
+    }
+    public void setCourseDay(Long courseDay)
+    {
+        this.courseDay = courseDay;
+    }
+
+    public Long getCourseDay()
+    {
+        return courseDay;
+    }
+    public void setCourseHour(Long courseHour)
+    {
+        this.courseHour = courseHour;
+    }
+
+    public Long getCourseHour()
+    {
+        return courseHour;
+    }
+    public void setCourseType(String courseType)
+    {
+        this.courseType = courseType;
+    }
+
+    public String getCourseType()
+    {
+        return courseType;
+    }
+    public void setTrainer(String trainer)
+    {
+        this.trainer = trainer;
+    }
+
+    public String getTrainer()
+    {
+        return trainer;
+    }
+    public void setCourseDate(Date courseDate)
+    {
+        this.courseDate = courseDate;
+    }
+
+    public Date getCourseDate()
+    {
+        return courseDate;
+    }
+    public void setAssess(String assess)
+    {
+        this.assess = assess;
+    }
+
+    public String getAssess()
+    {
+        return assess;
+    }
+    public void setDelFlag(Long delFlag)
+    {
+        this.delFlag = delFlag;
+    }
+
+    public Long getDelFlag()
+    {
+        return delFlag;
+    }
+    public void setCreaterCode(String createrCode)
+    {
+        this.createrCode = createrCode;
+    }
+
+    public String getCreaterCode()
+    {
+        return createrCode;
+    }
+    public void setCreatedate(Date createdate)
+    {
+        this.createdate = createdate;
+    }
+
+    public Date getCreatedate()
+    {
+        return createdate;
+    }
+    public void setUpdaterCode(String updaterCode)
+    {
+        this.updaterCode = updaterCode;
+    }
+
+    public String getUpdaterCode()
+    {
+        return updaterCode;
+    }
+    public void setUpdatedate(Date updatedate)
+    {
+        this.updatedate = updatedate;
+    }
+
+    public Date getUpdatedate()
+    {
+        return updatedate;
+    }
+    public void setDeptId(Long deptId)
+    {
+        this.deptId = deptId;
+    }
+
+    public Long getDeptId()
+    {
+        return deptId;
+    }
+    public void setRemarks(String remarks)
+    {
+        this.remarks = remarks;
+    }
+
+    public String getRemarks()
+    {
+        return remarks;
+    }
+
+    public String getDeptName() {
+        return deptName;
+    }
+
+    public void setDeptName(String deptName) {
+        this.deptName = deptName;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("id", getId())
+            .append("newId", getNewId())
+            .append("courseCode", getCourseCode())
+            .append("topic", getTopic())
+            .append("content", getContent())
+            .append("courseDay", getCourseDay())
+            .append("courseHour", getCourseHour())
+            .append("courseType", getCourseType())
+            .append("trainer", getTrainer())
+            .append("courseDate", getCourseDate())
+            .append("assess", getAssess())
+            .append("delFlag", getDelFlag())
+            .append("createrCode", getCreaterCode())
+            .append("createdate", getCreatedate())
+            .append("updaterCode", getUpdaterCode())
+            .append("updatedate", getUpdatedate())
+            .append("deptId", getDeptId())
+            .append("remarks", getRemarks())
+            .toString();
+    }
+}

+ 263 - 0
master/src/main/java/com/ruoyi/project/training/bccnew/domain/TTsNew.java

@@ -0,0 +1,263 @@
+package com.ruoyi.project.training.bccnew.domain;
+
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import com.ruoyi.framework.web.domain.BaseEntity;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+/**
+ * 导师带徒对象 t_ts_new
+ *
+ * @author ssy
+ * @date 2024-05-20
+ */
+public class TTsNew extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 唯一标识ID */
+    private Long newId;
+
+    /** 培训员工编号 */
+    @Excel(name = "培训员工编号")
+    private String staffId;
+
+    /** 年度培训标题 */
+    @Excel(name = "年度培训标题")
+    private String name;
+
+    /** 删除状态 */
+    private Long delFlag;
+
+    /** 创建人 */
+    @Excel(name = "创建人")
+    private String createrCode;
+
+    /** 创建时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd" , timezone = "GMT+8")
+    @Excel(name = "创建时间", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date createdate;
+
+    /** 修改人 */
+    @Excel(name = "修改人")
+    private String updaterCode;
+
+    /** 修改时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd" , timezone = "GMT+8")
+    @Excel(name = "修改时间", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date updatedate;
+
+    /** 部门编号 */
+    @Excel(name = "部门编号")
+    private Long deptId;
+
+    /** 培训状态 */
+    @Excel(name = "培训状态")
+    private Long planStatus;
+
+    /** 年份 */
+    @Excel(name = "年份")
+    private Long planYear;
+
+    /** 开始时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd" , timezone = "GMT+8")
+    @Excel(name = "开始时间", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date startdate;
+
+    /** 结束时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd" , timezone = "GMT+8")
+    @Excel(name = "结束时间", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date enddate;
+
+    /** 导师员工编号 */
+    @Excel(name = "导师员工编号")
+    private String mentorStaffId;
+
+    /** 培训岗位 1-裂解 2-压缩 3-分离 4-芳烃 */
+    @Excel(name = "培训岗位 1-裂解 2-压缩 3-分离 4-芳烃")
+    private Long planType;
+    /** 部门名称 */
+    @Excel(name = "部门名称")
+    private String deptName;
+
+    /** 备注 */
+    @Excel(name = "备注")
+    private String remarks;
+
+    public void setNewId(Long newId)
+    {
+        this.newId = newId;
+    }
+
+    public Long getNewId()
+    {
+        return newId;
+    }
+    public void setStaffId(String staffId)
+    {
+        this.staffId = staffId;
+    }
+
+    public String getStaffId()
+    {
+        return staffId;
+    }
+    public void setName(String name)
+    {
+        this.name = name;
+    }
+
+    public String getName()
+    {
+        return name;
+    }
+    public void setDelFlag(Long delFlag)
+    {
+        this.delFlag = delFlag;
+    }
+
+    public Long getDelFlag()
+    {
+        return delFlag;
+    }
+    public void setCreaterCode(String createrCode)
+    {
+        this.createrCode = createrCode;
+    }
+
+    public String getCreaterCode()
+    {
+        return createrCode;
+    }
+    public void setCreatedate(Date createdate)
+    {
+        this.createdate = createdate;
+    }
+
+    public Date getCreatedate()
+    {
+        return createdate;
+    }
+    public void setUpdaterCode(String updaterCode)
+    {
+        this.updaterCode = updaterCode;
+    }
+
+    public String getUpdaterCode()
+    {
+        return updaterCode;
+    }
+    public void setUpdatedate(Date updatedate)
+    {
+        this.updatedate = updatedate;
+    }
+
+    public Date getUpdatedate()
+    {
+        return updatedate;
+    }
+    public void setDeptId(Long deptId)
+    {
+        this.deptId = deptId;
+    }
+
+    public Long getDeptId()
+    {
+        return deptId;
+    }
+    public void setPlanStatus(Long planStatus)
+    {
+        this.planStatus = planStatus;
+    }
+
+    public Long getPlanStatus()
+    {
+        return planStatus;
+    }
+    public void setPlanYear(Long planYear)
+    {
+        this.planYear = planYear;
+    }
+
+    public Long getPlanYear()
+    {
+        return planYear;
+    }
+    public void setStartdate(Date startdate)
+    {
+        this.startdate = startdate;
+    }
+
+    public Date getStartdate()
+    {
+        return startdate;
+    }
+    public void setEnddate(Date enddate)
+    {
+        this.enddate = enddate;
+    }
+
+    public Date getEnddate()
+    {
+        return enddate;
+    }
+    public void setMentorStaffId(String mentorStaffId)
+    {
+        this.mentorStaffId = mentorStaffId;
+    }
+
+    public String getMentorStaffId()
+    {
+        return mentorStaffId;
+    }
+    public void setPlanType(Long planType)
+    {
+        this.planType = planType;
+    }
+
+    public Long getPlanType()
+    {
+        return planType;
+    }
+    public void setRemarks(String remarks)
+    {
+        this.remarks = remarks;
+    }
+
+    public String getRemarks()
+    {
+        return remarks;
+    }
+
+    public String getDeptName() {
+        return deptName;
+    }
+
+    public void setDeptName(String deptName) {
+        this.deptName = deptName;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("newId", getNewId())
+            .append("staffId", getStaffId())
+            .append("name", getName())
+            .append("delFlag", getDelFlag())
+            .append("createrCode", getCreaterCode())
+            .append("createdate", getCreatedate())
+            .append("updaterCode", getUpdaterCode())
+            .append("updatedate", getUpdatedate())
+            .append("deptId", getDeptId())
+            .append("planStatus", getPlanStatus())
+            .append("planYear", getPlanYear())
+            .append("startdate", getStartdate())
+            .append("enddate", getEnddate())
+            .append("mentorStaffId", getMentorStaffId())
+            .append("planType", getPlanType())
+            .append("remarks", getRemarks())
+            .toString();
+    }
+}

+ 63 - 0
master/src/main/java/com/ruoyi/project/training/bccnew/mapper/TTsFirstplanTmplMapper.java

@@ -0,0 +1,63 @@
+package com.ruoyi.project.training.bccnew.mapper;
+
+import java.util.List;
+import com.ruoyi.framework.aspectj.lang.annotation.DataScope;
+import com.ruoyi.project.training.bccnew.domain.TTsFirstplanTmpl;
+
+/**
+ * 进组培训模版Mapper接口
+ * 
+ * @author ssy
+ * @date 2024-05-22
+ */
+public interface TTsFirstplanTmplMapper 
+{
+    /**
+     * 查询进组培训模版
+     * 
+     * @param id 进组培训模版ID
+     * @return 进组培训模版
+     */
+    public TTsFirstplanTmpl selectTTsFirstplanTmplById(Long id);
+
+    /**
+     * 查询进组培训模版列表
+     * 
+     * @param tTsFirstplanTmpl 进组培训模版
+     * @return 进组培训模版集合
+     */
+    @DataScope(deptAlias = "d")
+    public List<TTsFirstplanTmpl> selectTTsFirstplanTmplList(TTsFirstplanTmpl tTsFirstplanTmpl);
+
+    /**
+     * 新增进组培训模版
+     * 
+     * @param tTsFirstplanTmpl 进组培训模版
+     * @return 结果
+     */
+    public int insertTTsFirstplanTmpl(TTsFirstplanTmpl tTsFirstplanTmpl);
+
+    /**
+     * 修改进组培训模版
+     * 
+     * @param tTsFirstplanTmpl 进组培训模版
+     * @return 结果
+     */
+    public int updateTTsFirstplanTmpl(TTsFirstplanTmpl tTsFirstplanTmpl);
+
+    /**
+     * 删除进组培训模版
+     * 
+     * @param id 进组培训模版ID
+     * @return 结果
+     */
+    public int deleteTTsFirstplanTmplById(Long id);
+
+    /**
+     * 批量删除进组培训模版
+     * 
+     * @param ids 需要删除的数据ID
+     * @return 结果
+     */
+    public int deleteTTsFirstplanTmplByIds(Long[] ids);
+}

+ 63 - 0
master/src/main/java/com/ruoyi/project/training/bccnew/mapper/TTsNewMapper.java

@@ -0,0 +1,63 @@
+package com.ruoyi.project.training.bccnew.mapper;
+
+import java.util.List;
+import com.ruoyi.framework.aspectj.lang.annotation.DataScope;
+import com.ruoyi.project.training.bccnew.domain.TTsNew;
+
+/**
+ * 导师带徒Mapper接口
+ * 
+ * @author ssy
+ * @date 2024-05-20
+ */
+public interface TTsNewMapper 
+{
+    /**
+     * 查询导师带徒
+     * 
+     * @param newId 导师带徒ID
+     * @return 导师带徒
+     */
+    public TTsNew selectTTsNewById(Long newId);
+
+    /**
+     * 查询导师带徒列表
+     * 
+     * @param tTsNew 导师带徒
+     * @return 导师带徒集合
+     */
+    @DataScope(deptAlias = "d")
+    public List<TTsNew> selectTTsNewList(TTsNew tTsNew);
+
+    /**
+     * 新增导师带徒
+     * 
+     * @param tTsNew 导师带徒
+     * @return 结果
+     */
+    public int insertTTsNew(TTsNew tTsNew);
+
+    /**
+     * 修改导师带徒
+     * 
+     * @param tTsNew 导师带徒
+     * @return 结果
+     */
+    public int updateTTsNew(TTsNew tTsNew);
+
+    /**
+     * 删除导师带徒
+     * 
+     * @param newId 导师带徒ID
+     * @return 结果
+     */
+    public int deleteTTsNewById(Long newId);
+
+    /**
+     * 批量删除导师带徒
+     * 
+     * @param newIds 需要删除的数据ID
+     * @return 结果
+     */
+    public int deleteTTsNewByIds(Long[] newIds);
+}

+ 61 - 0
master/src/main/java/com/ruoyi/project/training/bccnew/service/ITTsFirstplanTmplService.java

@@ -0,0 +1,61 @@
+package com.ruoyi.project.training.bccnew.service;
+
+import java.util.List;
+import com.ruoyi.project.training.bccnew.domain.TTsFirstplanTmpl;
+
+/**
+ * 进组培训模版Service接口
+ * 
+ * @author ssy
+ * @date 2024-05-22
+ */
+public interface ITTsFirstplanTmplService 
+{
+    /**
+     * 查询进组培训模版
+     * 
+     * @param id 进组培训模版ID
+     * @return 进组培训模版
+     */
+    public TTsFirstplanTmpl selectTTsFirstplanTmplById(Long id);
+
+    /**
+     * 查询进组培训模版列表
+     * 
+     * @param tTsFirstplanTmpl 进组培训模版
+     * @return 进组培训模版集合
+     */
+    public List<TTsFirstplanTmpl> selectTTsFirstplanTmplList(TTsFirstplanTmpl tTsFirstplanTmpl);
+
+    /**
+     * 新增进组培训模版
+     * 
+     * @param tTsFirstplanTmpl 进组培训模版
+     * @return 结果
+     */
+    public int insertTTsFirstplanTmpl(TTsFirstplanTmpl tTsFirstplanTmpl);
+
+    /**
+     * 修改进组培训模版
+     * 
+     * @param tTsFirstplanTmpl 进组培训模版
+     * @return 结果
+     */
+    public int updateTTsFirstplanTmpl(TTsFirstplanTmpl tTsFirstplanTmpl);
+
+    /**
+     * 批量删除进组培训模版
+     * 
+     * @param ids 需要删除的进组培训模版ID
+     * @return 结果
+     */
+    public int deleteTTsFirstplanTmplByIds(Long[] ids);
+
+    /**
+     * 删除进组培训模版信息
+     * 
+     * @param id 进组培训模版ID
+     * @return 结果
+     */
+    public int deleteTTsFirstplanTmplById(Long id);
+}

+ 61 - 0
master/src/main/java/com/ruoyi/project/training/bccnew/service/ITTsNewService.java

@@ -0,0 +1,61 @@
+package com.ruoyi.project.training.bccnew.service;
+
+import java.util.List;
+import com.ruoyi.project.training.bccnew.domain.TTsNew;
+
+/**
+ * 导师带徒Service接口
+ * 
+ * @author ssy
+ * @date 2024-05-20
+ */
+public interface ITTsNewService 
+{
+    /**
+     * 查询导师带徒
+     * 
+     * @param newId 导师带徒ID
+     * @return 导师带徒
+     */
+    public TTsNew selectTTsNewById(Long newId);
+
+    /**
+     * 查询导师带徒列表
+     * 
+     * @param tTsNew 导师带徒
+     * @return 导师带徒集合
+     */
+    public List<TTsNew> selectTTsNewList(TTsNew tTsNew);
+
+    /**
+     * 新增导师带徒
+     * 
+     * @param tTsNew 导师带徒
+     * @return 结果
+     */
+    public int insertTTsNew(TTsNew tTsNew);
+
+    /**
+     * 修改导师带徒
+     * 
+     * @param tTsNew 导师带徒
+     * @return 结果
+     */
+    public int updateTTsNew(TTsNew tTsNew);
+
+    /**
+     * 批量删除导师带徒
+     * 
+     * @param newIds 需要删除的导师带徒ID
+     * @return 结果
+     */
+    public int deleteTTsNewByIds(Long[] newIds);
+
+    /**
+     * 删除导师带徒信息
+     * 
+     * @param newId 导师带徒ID
+     * @return 结果
+     */
+    public int deleteTTsNewById(Long newId);
+}

+ 93 - 0
master/src/main/java/com/ruoyi/project/training/bccnew/service/impl/TTsFirstplanTmplServiceImpl.java

@@ -0,0 +1,93 @@
+package com.ruoyi.project.training.bccnew.service.impl;
+
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.ruoyi.project.training.bccnew.mapper.TTsFirstplanTmplMapper;
+import com.ruoyi.project.training.bccnew.domain.TTsFirstplanTmpl;
+import com.ruoyi.project.training.bccnew.service.ITTsFirstplanTmplService;
+
+/**
+ * 进组培训模版Service业务层处理
+ *
+ * @author ssy
+ * @date 2024-05-22
+ */
+@Service
+public class TTsFirstplanTmplServiceImpl implements ITTsFirstplanTmplService
+{
+    @Autowired
+    private TTsFirstplanTmplMapper tTsFirstplanTmplMapper;
+
+    /**
+     * 查询进组培训模版
+     *
+     * @param id 进组培训模版ID
+     * @return 进组培训模版
+     */
+    @Override
+    public TTsFirstplanTmpl selectTTsFirstplanTmplById(Long id)
+    {
+        return tTsFirstplanTmplMapper.selectTTsFirstplanTmplById(id);
+    }
+
+    /**
+     * 查询进组培训模版列表
+     *
+     * @param tTsFirstplanTmpl 进组培训模版
+     * @return 进组培训模版
+     */
+    @Override
+    public List<TTsFirstplanTmpl> selectTTsFirstplanTmplList(TTsFirstplanTmpl tTsFirstplanTmpl)
+    {
+        return tTsFirstplanTmplMapper.selectTTsFirstplanTmplList(tTsFirstplanTmpl);
+    }
+
+    /**
+     * 新增进组培训模版
+     *
+     * @param tTsFirstplanTmpl 进组培训模版
+     * @return 结果
+     */
+    @Override
+    public int insertTTsFirstplanTmpl(TTsFirstplanTmpl tTsFirstplanTmpl)
+    {
+        return tTsFirstplanTmplMapper.insertTTsFirstplanTmpl(tTsFirstplanTmpl);
+    }
+
+    /**
+     * 修改进组培训模版
+     *
+     * @param tTsFirstplanTmpl 进组培训模版
+     * @return 结果
+     */
+    @Override
+    public int updateTTsFirstplanTmpl(TTsFirstplanTmpl tTsFirstplanTmpl)
+    {
+        return tTsFirstplanTmplMapper.updateTTsFirstplanTmpl(tTsFirstplanTmpl);
+    }
+
+    /**
+     * 批量删除进组培训模版
+     *
+     * @param ids 需要删除的进组培训模版ID
+     * @return 结果
+     */
+    @Override
+    public int deleteTTsFirstplanTmplByIds(Long[] ids)
+    {
+        return tTsFirstplanTmplMapper.deleteTTsFirstplanTmplByIds(ids);
+    }
+
+    /**
+     * 删除进组培训模版信息
+     *
+     * @param id 进组培训模版ID
+     * @return 结果
+     */
+    @Override
+    public int deleteTTsFirstplanTmplById(Long id)
+    {
+        return tTsFirstplanTmplMapper.deleteTTsFirstplanTmplById(id);
+    }
+}

+ 93 - 0
master/src/main/java/com/ruoyi/project/training/bccnew/service/impl/TTsNewServiceImpl.java

@@ -0,0 +1,93 @@
+package com.ruoyi.project.training.bccnew.service.impl;
+
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.ruoyi.project.training.bccnew.mapper.TTsNewMapper;
+import com.ruoyi.project.training.bccnew.domain.TTsNew;
+import com.ruoyi.project.training.bccnew.service.ITTsNewService;
+
+/**
+ * 导师带徒Service业务层处理
+ *
+ * @author ssy
+ * @date 2024-05-20
+ */
+@Service
+public class TTsNewServiceImpl implements ITTsNewService
+{
+    @Autowired
+    private TTsNewMapper tTsNewMapper;
+
+    /**
+     * 查询导师带徒
+     *
+     * @param newId 导师带徒ID
+     * @return 导师带徒
+     */
+    @Override
+    public TTsNew selectTTsNewById(Long newId)
+    {
+        return tTsNewMapper.selectTTsNewById(newId);
+    }
+
+    /**
+     * 查询导师带徒列表
+     *
+     * @param tTsNew 导师带徒
+     * @return 导师带徒
+     */
+    @Override
+    public List<TTsNew> selectTTsNewList(TTsNew tTsNew)
+    {
+        return tTsNewMapper.selectTTsNewList(tTsNew);
+    }
+
+    /**
+     * 新增导师带徒
+     *
+     * @param tTsNew 导师带徒
+     * @return 结果
+     */
+    @Override
+    public int insertTTsNew(TTsNew tTsNew)
+    {
+        return tTsNewMapper.insertTTsNew(tTsNew);
+    }
+
+    /**
+     * 修改导师带徒
+     *
+     * @param tTsNew 导师带徒
+     * @return 结果
+     */
+    @Override
+    public int updateTTsNew(TTsNew tTsNew)
+    {
+        return tTsNewMapper.updateTTsNew(tTsNew);
+    }
+
+    /**
+     * 批量删除导师带徒
+     *
+     * @param newIds 需要删除的导师带徒ID
+     * @return 结果
+     */
+    @Override
+    public int deleteTTsNewByIds(Long[] newIds)
+    {
+        return tTsNewMapper.deleteTTsNewByIds(newIds);
+    }
+
+    /**
+     * 删除导师带徒信息
+     *
+     * @param newId 导师带徒ID
+     * @return 结果
+     */
+    @Override
+    public int deleteTTsNewById(Long newId)
+    {
+        return tTsNewMapper.deleteTTsNewById(newId);
+    }
+}

+ 103 - 0
master/src/main/java/com/ruoyi/project/training/elearn/controller/TElExamController.java

@@ -0,0 +1,103 @@
+package com.ruoyi.project.training.elearn.controller;
+
+import java.util.List;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.project.training.elearn.domain.TElExam;
+import com.ruoyi.project.training.elearn.service.ITElExamService;
+import com.ruoyi.framework.web.controller.BaseController;
+import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.framework.web.page.TableDataInfo;
+
+/**
+ * 考试Controller
+ *
+ * @author ssy
+ * @date 2024-05-29
+ */
+@RestController
+@RequestMapping("/elearn/exam")
+public class TElExamController extends BaseController
+{
+    @Autowired
+    private ITElExamService tElExamService;
+
+    /**
+     * 查询考试列表
+     */
+    @PreAuthorize("@ss.hasPermi('elearn:exam:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(TElExam tElExam)
+    {
+        startPage();
+        List<TElExam> list = tElExamService.selectTElExamList(tElExam);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出考试列表
+     */
+    @PreAuthorize("@ss.hasPermi('elearn:exam:export')")
+    @Log(title = "考试", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(TElExam tElExam)
+    {
+        List<TElExam> list = tElExamService.selectTElExamList(tElExam);
+        ExcelUtil<TElExam> util = new ExcelUtil<TElExam>(TElExam.class);
+        return util.exportExcel(list, "exam");
+    }
+
+    /**
+     * 获取考试详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('elearn:exam:query')")
+    @GetMapping(value = "/{examId}")
+    public AjaxResult getInfo(@PathVariable("examId") Long examId)
+    {
+        return AjaxResult.success(tElExamService.selectTElExamById(examId));
+    }
+
+    /**
+     * 新增考试
+     */
+    @PreAuthorize("@ss.hasPermi('elearn:exam:add')")
+    @Log(title = "考试", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody TElExam tElExam)
+    {
+        return toAjax(tElExamService.insertTElExam(tElExam));
+    }
+
+    /**
+     * 修改考试
+     */
+    @PreAuthorize("@ss.hasPermi('elearn:exam:edit')")
+    @Log(title = "考试", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody TElExam tElExam)
+    {
+        return toAjax(tElExamService.updateTElExam(tElExam));
+    }
+
+    /**
+     * 删除考试
+     */
+    @PreAuthorize("@ss.hasPermi('elearn:exam:remove')")
+    @Log(title = "考试", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{examIds}")
+    public AjaxResult remove(@PathVariable Long[] examIds)
+    {
+        return toAjax(tElExamService.deleteTElExamByIds(examIds));
+    }
+}

+ 122 - 0
master/src/main/java/com/ruoyi/project/training/elearn/controller/TElPaperController.java

@@ -0,0 +1,122 @@
+package com.ruoyi.project.training.elearn.controller;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.List;
+
+import com.ruoyi.framework.job.service.JobService;
+import com.ruoyi.project.training.elearn.job.BreakExamJob;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.project.training.elearn.domain.TElPaper;
+import com.ruoyi.project.training.elearn.service.ITElPaperService;
+import com.ruoyi.framework.web.controller.BaseController;
+import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.framework.web.page.TableDataInfo;
+
+/**
+ * 在线考试Controller
+ *
+ * @author ssy
+ * @date 2024-05-29
+ */
+@RestController
+@RequestMapping("/elearn/paper")
+public class TElPaperController extends BaseController
+{
+    @Autowired
+    private ITElPaperService tElPaperService;
+
+
+    /**
+     * 查询在线考试列表
+     */
+    @PreAuthorize("@ss.hasPermi('elearn:paper:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(TElPaper tElPaper)
+    {
+        startPage();
+        List<TElPaper> list = tElPaperService.selectTElPaperList(tElPaper);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出在线考试列表
+     */
+    @PreAuthorize("@ss.hasPermi('elearn:paper:export')")
+    @Log(title = "在线考试", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(TElPaper tElPaper)
+    {
+        List<TElPaper> list = tElPaperService.selectTElPaperList(tElPaper);
+        ExcelUtil<TElPaper> util = new ExcelUtil<TElPaper>(TElPaper.class);
+        return util.exportExcel(list, "paper");
+    }
+
+    /**
+     * 获取在线考试详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('elearn:paper:query')")
+    @GetMapping(value = "/{paperId}")
+    public AjaxResult getInfo(@PathVariable("paperId") Long paperId)
+    {
+        return AjaxResult.success(tElPaperService.selectTElPaperById(paperId));
+    }
+
+    /**
+     * 新增在线考试
+     */
+    @PreAuthorize("@ss.hasPermi('elearn:paper:add')")
+    @Log(title = "在线考试", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody TElPaper tElPaper)
+    {
+        return toAjax(tElPaperService.insertTElPaper(tElPaper));
+    }
+
+    /**
+     * 创建考试
+     */
+    @Log(title = "创建考试", businessType = BusinessType.INSERT)
+    @PostMapping(value = "/createPaper")
+    public AjaxResult createPaper(@RequestBody TElPaper tElPaper)
+    {
+        getUserId();
+        return AjaxResult.success(tElPaperService.createPaper(tElPaper,getUserId()));
+    }
+
+    /**
+     * 修改在线考试
+     */
+    @PreAuthorize("@ss.hasPermi('elearn:paper:edit')")
+    @Log(title = "在线考试", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody TElPaper tElPaper)
+    {
+        return toAjax(tElPaperService.updateTElPaper(tElPaper));
+    }
+
+    /**
+     * 删除在线考试
+     */
+    @PreAuthorize("@ss.hasPermi('elearn:paper:remove')")
+    @Log(title = "在线考试", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{paperIds}")
+    public AjaxResult remove(@PathVariable Long[] paperIds)
+    {
+        return toAjax(tElPaperService.deleteTElPaperByIds(paperIds));
+    }
+
+
+}

+ 103 - 0
master/src/main/java/com/ruoyi/project/training/elearn/controller/TElQuController.java

@@ -0,0 +1,103 @@
+package com.ruoyi.project.training.elearn.controller;
+
+import java.util.List;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.project.training.elearn.domain.TElQu;
+import com.ruoyi.project.training.elearn.service.ITElQuService;
+import com.ruoyi.framework.web.controller.BaseController;
+import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.framework.web.page.TableDataInfo;
+
+/**
+ * 试题Controller
+ *
+ * @author ssy
+ * @date 2024-05-28
+ */
+@RestController
+@RequestMapping("/elearn/qu")
+public class TElQuController extends BaseController
+{
+    @Autowired
+    private ITElQuService tElQuService;
+
+    /**
+     * 查询试题列表
+     */
+    @PreAuthorize("@ss.hasPermi('elearn:qu:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(TElQu tElQu)
+    {
+        startPage();
+        List<TElQu> list = tElQuService.selectTElQuList(tElQu);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出试题列表
+     */
+    @PreAuthorize("@ss.hasPermi('elearn:qu:export')")
+    @Log(title = "试题", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(TElQu tElQu)
+    {
+        List<TElQu> list = tElQuService.selectTElQuList(tElQu);
+        ExcelUtil<TElQu> util = new ExcelUtil<TElQu>(TElQu.class);
+        return util.exportExcel(list, "qu");
+    }
+
+    /**
+     * 获取试题详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('elearn:qu:query')")
+    @GetMapping(value = "/{quId}")
+    public AjaxResult getInfo(@PathVariable("quId") Long quId)
+    {
+        return AjaxResult.success(tElQuService.selectTElQuById(quId));
+    }
+
+    /**
+     * 新增试题
+     */
+    @PreAuthorize("@ss.hasPermi('elearn:qu:add')")
+    @Log(title = "试题", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody TElQu tElQu)
+    {
+        return toAjax(tElQuService.insertTElQu(tElQu));
+    }
+
+    /**
+     * 修改试题
+     */
+    @PreAuthorize("@ss.hasPermi('elearn:qu:edit')")
+    @Log(title = "试题", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody TElQu tElQu)
+    {
+        return toAjax(tElQuService.updateTElQu(tElQu));
+    }
+
+    /**
+     * 删除试题
+     */
+    @PreAuthorize("@ss.hasPermi('elearn:qu:remove')")
+    @Log(title = "试题", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{quIds}")
+    public AjaxResult remove(@PathVariable Long[] quIds)
+    {
+        return toAjax(tElQuService.deleteTElQuByIds(quIds));
+    }
+}

+ 103 - 0
master/src/main/java/com/ruoyi/project/training/elearn/controller/TElRepoController.java

@@ -0,0 +1,103 @@
+package com.ruoyi.project.training.elearn.controller;
+
+import java.util.List;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.project.training.elearn.domain.TElRepo;
+import com.ruoyi.project.training.elearn.service.ITElRepoService;
+import com.ruoyi.framework.web.controller.BaseController;
+import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.framework.web.page.TableDataInfo;
+
+/**
+ * 题库Controller
+ *
+ * @author ssy
+ * @date 2024-05-27
+ */
+@RestController
+@RequestMapping("/elearn/repo")
+public class TElRepoController extends BaseController
+{
+    @Autowired
+    private ITElRepoService tElRepoService;
+
+    /**
+     * 查询题库列表
+     */
+    @PreAuthorize("@ss.hasPermi('elearn:repo:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(TElRepo tElRepo)
+    {
+        startPage();
+        List<TElRepo> list = tElRepoService.selectTElRepoList(tElRepo);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出题库列表
+     */
+    @PreAuthorize("@ss.hasPermi('elearn:repo:export')")
+    @Log(title = "题库", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(TElRepo tElRepo)
+    {
+        List<TElRepo> list = tElRepoService.selectTElRepoList(tElRepo);
+        ExcelUtil<TElRepo> util = new ExcelUtil<TElRepo>(TElRepo.class);
+        return util.exportExcel(list, "repo");
+    }
+
+    /**
+     * 获取题库详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('elearn:repo:query')")
+    @GetMapping(value = "/{repoId}")
+    public AjaxResult getInfo(@PathVariable("repoId") Long repoId)
+    {
+        return AjaxResult.success(tElRepoService.selectTElRepoById(repoId));
+    }
+
+    /**
+     * 新增题库
+     */
+    @PreAuthorize("@ss.hasPermi('elearn:repo:add')")
+    @Log(title = "题库", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody TElRepo tElRepo)
+    {
+        return toAjax(tElRepoService.insertTElRepo(tElRepo));
+    }
+
+    /**
+     * 修改题库
+     */
+    @PreAuthorize("@ss.hasPermi('elearn:repo:edit')")
+    @Log(title = "题库", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody TElRepo tElRepo)
+    {
+        return toAjax(tElRepoService.updateTElRepo(tElRepo));
+    }
+
+    /**
+     * 删除题库
+     */
+    @PreAuthorize("@ss.hasPermi('elearn:repo:remove')")
+    @Log(title = "题库", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{repoIds}")
+    public AjaxResult remove(@PathVariable Long[] repoIds)
+    {
+        return toAjax(tElRepoService.deleteTElRepoByIds(repoIds));
+    }
+}

+ 292 - 0
master/src/main/java/com/ruoyi/project/training/elearn/domain/TElExam.java

@@ -0,0 +1,292 @@
+package com.ruoyi.project.training.elearn.domain;
+
+import java.util.Date;
+import java.util.List;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import com.ruoyi.framework.web.domain.BaseEntity;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+/**
+ * 考试对象 t_el_exam
+ *
+ * @author ssy
+ * @date 2024-05-29
+ */
+public class TElExam extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** id */
+    private Long examId;
+
+    /** 考试名称 */
+    @Excel(name = "考试名称")
+    private String title;
+
+    /** 考试内容 */
+    @Excel(name = "考试内容")
+    private String content;
+
+    /** 1公开2部门3定员 */
+    @Excel(name = "1公开2部门3定员")
+    private Long openType;
+
+    /** 考试状态 */
+    @Excel(name = "考试状态")
+    private Long state;
+
+    /** 是否限时 */
+    @Excel(name = "是否限时")
+    private Long timeLimit;
+
+    /** 开始时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd" , timezone = "GMT+8")
+    @Excel(name = "开始时间", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date examStartTime;
+
+    /** 结束时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd" , timezone = "GMT+8")
+    @Excel(name = "结束时间", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date examEndTime;
+
+    /** 总分 */
+    @Excel(name = "总分")
+    private Long totalScore;
+
+    /** 总时长 */
+    @Excel(name = "总时长")
+    private Long totalTime;
+
+    /** 及格分 */
+    @Excel(name = "及格分")
+    private Long qualifyScore;
+
+    /** 删除 */
+    private Long delFlag;
+
+    /** 创建人 */
+    @Excel(name = "创建人")
+    private String createrCode;
+
+    /** 创建时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd" , timezone = "GMT+8")
+    @Excel(name = "创建时间", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date createdate;
+
+    /** 更新人 */
+    @Excel(name = "更新人")
+    private String updaterCode;
+
+    /** 更新日期 */
+    @JsonFormat(pattern = "yyyy-MM-dd" , timezone = "GMT+8")
+    @Excel(name = "更新日期", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date updatedate;
+
+    /** 所属部门 */
+    @Excel(name = "所属部门")
+    private Long deptId;
+
+    /** 备注 */
+    @Excel(name = "备注")
+    private String remarks;
+
+    private List<TElExamRepo> repoList;
+
+    public void setExamId(Long examId)
+    {
+        this.examId = examId;
+    }
+
+    public Long getExamId()
+    {
+        return examId;
+    }
+    public void setTitle(String title)
+    {
+        this.title = title;
+    }
+
+    public String getTitle()
+    {
+        return title;
+    }
+    public void setContent(String content)
+    {
+        this.content = content;
+    }
+
+    public String getContent()
+    {
+        return content;
+    }
+    public void setOpenType(Long openType)
+    {
+        this.openType = openType;
+    }
+
+    public Long getOpenType()
+    {
+        return openType;
+    }
+    public void setState(Long state)
+    {
+        this.state = state;
+    }
+
+    public Long getState()
+    {
+        return state;
+    }
+    public void setTimeLimit(Long timeLimit)
+    {
+        this.timeLimit = timeLimit;
+    }
+
+    public Long getTimeLimit()
+    {
+        return timeLimit;
+    }
+    public void setExamStartTime(Date examStartTime)
+    {
+        this.examStartTime = examStartTime;
+    }
+
+    public Date getExamStartTime()
+    {
+        return examStartTime;
+    }
+    public void setExamEndTime(Date examEndTime)
+    {
+        this.examEndTime = examEndTime;
+    }
+
+    public Date getExamEndTime()
+    {
+        return examEndTime;
+    }
+    public void setTotalScore(Long totalScore)
+    {
+        this.totalScore = totalScore;
+    }
+
+    public Long getTotalScore()
+    {
+        return totalScore;
+    }
+    public void setTotalTime(Long totalTime)
+    {
+        this.totalTime = totalTime;
+    }
+
+    public Long getTotalTime()
+    {
+        return totalTime;
+    }
+    public void setQualifyScore(Long qualifyScore)
+    {
+        this.qualifyScore = qualifyScore;
+    }
+
+    public Long getQualifyScore()
+    {
+        return qualifyScore;
+    }
+    public void setDelFlag(Long delFlag)
+    {
+        this.delFlag = delFlag;
+    }
+
+    public Long getDelFlag()
+    {
+        return delFlag;
+    }
+    public void setCreaterCode(String createrCode)
+    {
+        this.createrCode = createrCode;
+    }
+
+    public String getCreaterCode()
+    {
+        return createrCode;
+    }
+    public void setCreatedate(Date createdate)
+    {
+        this.createdate = createdate;
+    }
+
+    public Date getCreatedate()
+    {
+        return createdate;
+    }
+    public void setUpdaterCode(String updaterCode)
+    {
+        this.updaterCode = updaterCode;
+    }
+
+    public String getUpdaterCode()
+    {
+        return updaterCode;
+    }
+    public void setUpdatedate(Date updatedate)
+    {
+        this.updatedate = updatedate;
+    }
+
+    public Date getUpdatedate()
+    {
+        return updatedate;
+    }
+    public void setDeptId(Long deptId)
+    {
+        this.deptId = deptId;
+    }
+
+    public Long getDeptId()
+    {
+        return deptId;
+    }
+    public void setRemarks(String remarks)
+    {
+        this.remarks = remarks;
+    }
+
+    public String getRemarks()
+    {
+        return remarks;
+    }
+
+    public List<TElExamRepo> getRepoList() {
+        return repoList;
+    }
+
+    public void setRepoList(List<TElExamRepo> repoList) {
+        this.repoList = repoList;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("examId", getExamId())
+            .append("title", getTitle())
+            .append("content", getContent())
+            .append("openType", getOpenType())
+            .append("state", getState())
+            .append("timeLimit", getTimeLimit())
+            .append("examStartTime", getExamStartTime())
+            .append("examEndTime", getExamEndTime())
+            .append("totalScore", getTotalScore())
+            .append("totalTime", getTotalTime())
+            .append("qualifyScore", getQualifyScore())
+            .append("delFlag", getDelFlag())
+            .append("createrCode", getCreaterCode())
+            .append("createdate", getCreatedate())
+            .append("updaterCode", getUpdaterCode())
+            .append("updatedate", getUpdatedate())
+            .append("deptId", getDeptId())
+            .append("remarks", getRemarks())
+            .toString();
+    }
+}

+ 216 - 0
master/src/main/java/com/ruoyi/project/training/elearn/domain/TElExamRepo.java

@@ -0,0 +1,216 @@
+package com.ruoyi.project.training.elearn.domain;
+
+import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import com.ruoyi.framework.web.domain.BaseEntity;
+import io.swagger.annotations.ApiModelProperty;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+/**
+ * 考试题库关联对象 t_el_exam_repo
+ *
+ * @author ssy
+ * @date 2024-05-29
+ */
+public class TElExamRepo extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** id */
+    private Long id;
+
+    /** 考试ID */
+    @Excel(name = "考试ID")
+    private Long examId;
+
+    /** 题库ID */
+    @Excel(name = "题库ID")
+    private Long repoId;
+
+    /** 单选题数量 */
+    @Excel(name = "单选题数量")
+    private Long radioCount;
+
+    /** 单选题分数 */
+    @Excel(name = "单选题分数")
+    private Long radioScore;
+
+    /** 多选题数量 */
+    @Excel(name = "多选题数量")
+    private Long multiCount;
+
+    /** 多选题分数 */
+    @Excel(name = "多选题分数")
+    private Long multiScore;
+
+    /** 判断题数量 */
+    @Excel(name = "判断题数量")
+    private Long judgeCount;
+
+    /** 判断题分数 */
+    @Excel(name = "判断题分数")
+    private Long judgeScore;
+
+    /** 简答题数量 */
+    @Excel(name = "简答题数量")
+    private Long saqCount;
+
+    /** 简答题分数 */
+    @Excel(name = "简答题分数")
+    private Long saqScore;
+
+    private Integer totalRadio;
+
+    private Integer totalMulti;
+
+    private Integer totalJudge;
+    private Integer quType;
+    public void setId(Long id)
+    {
+        this.id = id;
+    }
+
+    public Long getId()
+    {
+        return id;
+    }
+    public void setExamId(Long examId)
+    {
+        this.examId = examId;
+    }
+
+    public Long getExamId()
+    {
+        return examId;
+    }
+    public void setRepoId(Long repoId)
+    {
+        this.repoId = repoId;
+    }
+
+    public Long getRepoId()
+    {
+        return repoId;
+    }
+    public void setRadioCount(Long radioCount)
+    {
+        this.radioCount = radioCount;
+    }
+
+    public Long getRadioCount()
+    {
+        return radioCount;
+    }
+    public void setRadioScore(Long radioScore)
+    {
+        this.radioScore = radioScore;
+    }
+
+    public Long getRadioScore()
+    {
+        return radioScore;
+    }
+    public void setMultiCount(Long multiCount)
+    {
+        this.multiCount = multiCount;
+    }
+
+    public Long getMultiCount()
+    {
+        return multiCount;
+    }
+    public void setMultiScore(Long multiScore)
+    {
+        this.multiScore = multiScore;
+    }
+
+    public Long getMultiScore()
+    {
+        return multiScore;
+    }
+    public void setJudgeCount(Long judgeCount)
+    {
+        this.judgeCount = judgeCount;
+    }
+
+    public Long getJudgeCount()
+    {
+        return judgeCount;
+    }
+    public void setJudgeScore(Long judgeScore)
+    {
+        this.judgeScore = judgeScore;
+    }
+
+    public Long getJudgeScore()
+    {
+        return judgeScore;
+    }
+    public void setSaqCount(Long saqCount)
+    {
+        this.saqCount = saqCount;
+    }
+
+    public Long getSaqCount()
+    {
+        return saqCount;
+    }
+    public void setSaqScore(Long saqScore)
+    {
+        this.saqScore = saqScore;
+    }
+
+    public Long getSaqScore()
+    {
+        return saqScore;
+    }
+
+    public Integer getQuType() {
+        return quType;
+    }
+
+    public void setQuType(Integer quType) {
+        this.quType = quType;
+    }
+
+    public Integer getTotalRadio() {
+        return totalRadio;
+    }
+
+    public void setTotalRadio(Integer totalRadio) {
+        this.totalRadio = totalRadio;
+    }
+
+    public Integer getTotalMulti() {
+        return totalMulti;
+    }
+
+    public void setTotalMulti(Integer totalMulti) {
+        this.totalMulti = totalMulti;
+    }
+
+    public Integer getTotalJudge() {
+        return totalJudge;
+    }
+
+    public void setTotalJudge(Integer totalJudge) {
+        this.totalJudge = totalJudge;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("id", getId())
+            .append("examId", getExamId())
+            .append("repoId", getRepoId())
+            .append("radioCount", getRadioCount())
+            .append("radioScore", getRadioScore())
+            .append("multiCount", getMultiCount())
+            .append("multiScore", getMultiScore())
+            .append("judgeCount", getJudgeCount())
+            .append("judgeScore", getJudgeScore())
+            .append("saqCount", getSaqCount())
+            .append("saqScore", getSaqScore())
+            .toString();
+    }
+}

+ 335 - 0
master/src/main/java/com/ruoyi/project/training/elearn/domain/TElPaper.java

@@ -0,0 +1,335 @@
+package com.ruoyi.project.training.elearn.domain;
+
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import com.ruoyi.framework.web.domain.BaseEntity;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+/**
+ * 在线考试对象 t_el_paper
+ *
+ * @author ssy
+ * @date 2024-05-29
+ */
+public class TElPaper extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** id */
+    private Long paperId;
+
+    /** 用户id */
+    @Excel(name = "用户id")
+    private Long userId;
+
+    /** 员工编号 */
+    @Excel(name = "员工编号")
+    private Long staffId;
+
+    /** 考试id */
+    @Excel(name = "考试id")
+    private Long examId;
+
+    /** 考试标题 */
+    @Excel(name = "考试标题")
+    private String title;
+
+    /** 考试时长 */
+    @Excel(name = "考试时长")
+    private Long totalTime;
+
+    /** 用户时长 */
+    @Excel(name = "用户时长")
+    private Long userTime;
+
+    /** 试卷总分 */
+    @Excel(name = "试卷总分")
+    private Long totalScore;
+
+    /** 及格分 */
+    @Excel(name = "及格分")
+    private Long qualifyScore;
+
+    /** 客观分 */
+    @Excel(name = "客观分")
+    private Long objScore;
+
+    /** 主观分 */
+    @Excel(name = "主观分")
+    private Long subjScore;
+
+    /** 用户得分 */
+    @Excel(name = "用户得分")
+    private Long userScore;
+
+    /** 是否包含简答题 */
+    @Excel(name = "是否包含简答题")
+    private Long hasSaq;
+
+    /** 试卷状态 */
+    @Excel(name = "试卷状态")
+    private Long state;
+
+    /** 截止时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd" , timezone = "GMT+8")
+    @Excel(name = "截止时间", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date limitTime;
+
+    /** 删除 */
+    private Long delFlag;
+
+    /** 创建人 */
+    @Excel(name = "创建人")
+    private String createrCode;
+
+    /** 创建时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd" , timezone = "GMT+8")
+    @Excel(name = "创建时间", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date createdate;
+
+    /** 更新人 */
+    @Excel(name = "更新人")
+    private String updaterCode;
+
+    /** 更新日期 */
+    @JsonFormat(pattern = "yyyy-MM-dd" , timezone = "GMT+8")
+    @Excel(name = "更新日期", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date updatedate;
+
+    /** 所属部门 */
+    @Excel(name = "所属部门")
+    private Long deptId;
+
+    /** 备注 */
+    @Excel(name = "备注")
+    private String remarks;
+
+    public void setPaperId(Long paperId)
+    {
+        this.paperId = paperId;
+    }
+
+    public Long getPaperId()
+    {
+        return paperId;
+    }
+    public void setUserId(Long userId)
+    {
+        this.userId = userId;
+    }
+
+    public Long getUserId()
+    {
+        return userId;
+    }
+    public void setStaffId(Long staffId)
+    {
+        this.staffId = staffId;
+    }
+
+    public Long getStaffId()
+    {
+        return staffId;
+    }
+    public void setExamId(Long examId)
+    {
+        this.examId = examId;
+    }
+
+    public Long getExamId()
+    {
+        return examId;
+    }
+    public void setTitle(String title)
+    {
+        this.title = title;
+    }
+
+    public String getTitle()
+    {
+        return title;
+    }
+    public void setTotalTime(Long totalTime)
+    {
+        this.totalTime = totalTime;
+    }
+
+    public Long getTotalTime()
+    {
+        return totalTime;
+    }
+    public void setUserTime(Long userTime)
+    {
+        this.userTime = userTime;
+    }
+
+    public Long getUserTime()
+    {
+        return userTime;
+    }
+    public void setTotalScore(Long totalScore)
+    {
+        this.totalScore = totalScore;
+    }
+
+    public Long getTotalScore()
+    {
+        return totalScore;
+    }
+    public void setQualifyScore(Long qualifyScore)
+    {
+        this.qualifyScore = qualifyScore;
+    }
+
+    public Long getQualifyScore()
+    {
+        return qualifyScore;
+    }
+    public void setObjScore(Long objScore)
+    {
+        this.objScore = objScore;
+    }
+
+    public Long getObjScore()
+    {
+        return objScore;
+    }
+    public void setSubjScore(Long subjScore)
+    {
+        this.subjScore = subjScore;
+    }
+
+    public Long getSubjScore()
+    {
+        return subjScore;
+    }
+    public void setUserScore(Long userScore)
+    {
+        this.userScore = userScore;
+    }
+
+    public Long getUserScore()
+    {
+        return userScore;
+    }
+    public void setHasSaq(Long hasSaq)
+    {
+        this.hasSaq = hasSaq;
+    }
+
+    public Long getHasSaq()
+    {
+        return hasSaq;
+    }
+    public void setState(Long state)
+    {
+        this.state = state;
+    }
+
+    public Long getState()
+    {
+        return state;
+    }
+    public void setLimitTime(Date limitTime)
+    {
+        this.limitTime = limitTime;
+    }
+
+    public Date getLimitTime()
+    {
+        return limitTime;
+    }
+    public void setDelFlag(Long delFlag)
+    {
+        this.delFlag = delFlag;
+    }
+
+    public Long getDelFlag()
+    {
+        return delFlag;
+    }
+    public void setCreaterCode(String createrCode)
+    {
+        this.createrCode = createrCode;
+    }
+
+    public String getCreaterCode()
+    {
+        return createrCode;
+    }
+    public void setCreatedate(Date createdate)
+    {
+        this.createdate = createdate;
+    }
+
+    public Date getCreatedate()
+    {
+        return createdate;
+    }
+    public void setUpdaterCode(String updaterCode)
+    {
+        this.updaterCode = updaterCode;
+    }
+
+    public String getUpdaterCode()
+    {
+        return updaterCode;
+    }
+    public void setUpdatedate(Date updatedate)
+    {
+        this.updatedate = updatedate;
+    }
+
+    public Date getUpdatedate()
+    {
+        return updatedate;
+    }
+    public void setDeptId(Long deptId)
+    {
+        this.deptId = deptId;
+    }
+
+    public Long getDeptId()
+    {
+        return deptId;
+    }
+    public void setRemarks(String remarks)
+    {
+        this.remarks = remarks;
+    }
+
+    public String getRemarks()
+    {
+        return remarks;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("paperId", getPaperId())
+            .append("userId", getUserId())
+            .append("staffId", getStaffId())
+            .append("examId", getExamId())
+            .append("title", getTitle())
+            .append("totalTime", getTotalTime())
+            .append("userTime", getUserTime())
+            .append("totalScore", getTotalScore())
+            .append("qualifyScore", getQualifyScore())
+            .append("objScore", getObjScore())
+            .append("subjScore", getSubjScore())
+            .append("userScore", getUserScore())
+            .append("hasSaq", getHasSaq())
+            .append("state", getState())
+            .append("limitTime", getLimitTime())
+            .append("delFlag", getDelFlag())
+            .append("createrCode", getCreaterCode())
+            .append("createdate", getCreatedate())
+            .append("updaterCode", getUpdaterCode())
+            .append("updatedate", getUpdatedate())
+            .append("deptId", getDeptId())
+            .append("remarks", getRemarks())
+            .toString();
+    }
+}

+ 163 - 0
master/src/main/java/com/ruoyi/project/training/elearn/domain/TElPaperQu.java

@@ -0,0 +1,163 @@
+package com.ruoyi.project.training.elearn.domain;
+
+import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import com.ruoyi.framework.web.domain.BaseEntity;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+/**
+ * 试卷题目对象 t_el_paper_qu
+ *
+ * @author ssy
+ * @date 2024-05-29
+ */
+public class TElPaperQu extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** id */
+    private Long id;
+
+    /** 试卷ID */
+    @Excel(name = "试卷ID")
+    private Long paperId;
+
+    /** 题目ID */
+    @Excel(name = "题目ID")
+    private Long quId;
+
+    /** 题目类型 */
+    @Excel(name = "题目类型")
+    private Long quType;
+
+    /** 是否已答 */
+    @Excel(name = "是否已答")
+    private Long answered;
+
+    /** 主观答案 */
+    @Excel(name = "主观答案")
+    private String answer;
+
+    /** 问题排序 */
+    @Excel(name = "问题排序")
+    private Long sort;
+
+    /** 单题分分值 */
+    @Excel(name = "单题分分值")
+    private Long score;
+
+    /** 实际得分(主观题) */
+    @Excel(name = "实际得分(主观题)")
+    private Long actualScore;
+
+    /** 是否答对 */
+    @Excel(name = "是否答对")
+    private Long isRight;
+
+    public void setId(Long id)
+    {
+        this.id = id;
+    }
+
+    public Long getId()
+    {
+        return id;
+    }
+    public void setPaperId(Long paperId)
+    {
+        this.paperId = paperId;
+    }
+
+    public Long getPaperId()
+    {
+        return paperId;
+    }
+    public void setQuId(Long quId)
+    {
+        this.quId = quId;
+    }
+
+    public Long getQuId()
+    {
+        return quId;
+    }
+    public void setQuType(Long quType)
+    {
+        this.quType = quType;
+    }
+
+    public Long getQuType()
+    {
+        return quType;
+    }
+    public void setAnswered(Long answered)
+    {
+        this.answered = answered;
+    }
+
+    public Long getAnswered()
+    {
+        return answered;
+    }
+    public void setAnswer(String answer)
+    {
+        this.answer = answer;
+    }
+
+    public String getAnswer()
+    {
+        return answer;
+    }
+    public void setSort(Long sort)
+    {
+        this.sort = sort;
+    }
+
+    public Long getSort()
+    {
+        return sort;
+    }
+    public void setScore(Long score)
+    {
+        this.score = score;
+    }
+
+    public Long getScore()
+    {
+        return score;
+    }
+    public void setActualScore(Long actualScore)
+    {
+        this.actualScore = actualScore;
+    }
+
+    public Long getActualScore()
+    {
+        return actualScore;
+    }
+    public void setIsRight(Long isRight)
+    {
+        this.isRight = isRight;
+    }
+
+    public Long getIsRight()
+    {
+        return isRight;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("id", getId())
+            .append("paperId", getPaperId())
+            .append("quId", getQuId())
+            .append("quType", getQuType())
+            .append("answered", getAnswered())
+            .append("answer", getAnswer())
+            .append("sort", getSort())
+            .append("score", getScore())
+            .append("actualScore", getActualScore())
+            .append("isRight", getIsRight())
+            .toString();
+    }
+}

+ 135 - 0
master/src/main/java/com/ruoyi/project/training/elearn/domain/TElPaperQuAnswer.java

@@ -0,0 +1,135 @@
+package com.ruoyi.project.training.elearn.domain;
+
+import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import com.ruoyi.framework.web.domain.BaseEntity;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+/**
+ * 试卷题目答案对象 t_el_paper_qu_answer
+ *
+ * @author ssy
+ * @date 2024-05-29
+ */
+public class TElPaperQuAnswer extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** id */
+    private Long id;
+
+    /** 试卷ID */
+    @Excel(name = "试卷ID")
+    private Long paperId;
+
+    /** 题目ID */
+    @Excel(name = "题目ID")
+    private Long quId;
+
+    /** 回答项ID */
+    @Excel(name = "回答项ID")
+    private Long answerId;
+
+    /** 是否正确项 */
+    @Excel(name = "是否正确项")
+    private Long isRight;
+
+    /** 是否选中 */
+    @Excel(name = "是否选中")
+    private Long checked;
+
+    /** 排序 */
+    @Excel(name = "排序")
+    private Long sort;
+
+    /** 选项标签 */
+    @Excel(name = "选项标签")
+    private String abc;
+
+    public void setId(Long id)
+    {
+        this.id = id;
+    }
+
+    public Long getId()
+    {
+        return id;
+    }
+    public void setPaperId(Long paperId)
+    {
+        this.paperId = paperId;
+    }
+
+    public Long getPaperId()
+    {
+        return paperId;
+    }
+    public void setQuId(Long quId)
+    {
+        this.quId = quId;
+    }
+
+    public Long getQuId()
+    {
+        return quId;
+    }
+    public void setAnswerId(Long answerId)
+    {
+        this.answerId = answerId;
+    }
+
+    public Long getAnswerId()
+    {
+        return answerId;
+    }
+    public void setIsRight(Long isRight)
+    {
+        this.isRight = isRight;
+    }
+
+    public Long getIsRight()
+    {
+        return isRight;
+    }
+    public void setChecked(Long checked)
+    {
+        this.checked = checked;
+    }
+
+    public Long getChecked()
+    {
+        return checked;
+    }
+    public void setSort(Long sort)
+    {
+        this.sort = sort;
+    }
+
+    public Long getSort()
+    {
+        return sort;
+    }
+    public void setAbc(String abc)
+    {
+        this.abc = abc;
+    }
+
+    public String getAbc()
+    {
+        return abc;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("id", getId())
+            .append("paperId", getPaperId())
+            .append("quId", getQuId())
+            .append("answerId", getAnswerId())
+            .append("isRight", getIsRight())
+            .append("checked", getChecked())
+            .append("sort", getSort())
+            .append("abc", getAbc())
+            .toString();
+    }
+}

+ 228 - 0
master/src/main/java/com/ruoyi/project/training/elearn/domain/TElQu.java

@@ -0,0 +1,228 @@
+package com.ruoyi.project.training.elearn.domain;
+
+import java.util.Date;
+import java.util.List;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import com.ruoyi.framework.web.domain.BaseEntity;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+/**
+ * 试题对象 t_el_qu
+ *
+ * @author ssy
+ * @date 2024-05-28
+ */
+public class TElQu extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** id */
+    private Long quId;
+
+    /** 题目类型 */
+    @Excel(name = "题目类型")
+    private Long quType;
+
+    /** 等级 */
+    @Excel(name = "等级")
+    private Long qlevel;
+
+    /** 题目内容 */
+    @Excel(name = "题目内容")
+    private String content;
+
+    /** 照片 */
+    @Excel(name = "照片")
+    private String image;
+
+    /** 解析 */
+    @Excel(name = "解析")
+    private String analysis;
+
+    /** 删除 */
+    private Long delFlag;
+
+    /** 创建人 */
+    @Excel(name = "创建人")
+    private String createrCode;
+
+    /** 创建时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd" , timezone = "GMT+8")
+    @Excel(name = "创建时间", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date createdate;
+
+    /** 更新人 */
+    @Excel(name = "更新人")
+    private String updaterCode;
+
+    /** 更新日期 */
+    @JsonFormat(pattern = "yyyy-MM-dd" , timezone = "GMT+8")
+    @Excel(name = "更新日期", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date updatedate;
+
+    /** 所属部门 */
+    @Excel(name = "所属部门")
+    private Long deptId;
+
+    /** 备注 */
+    @Excel(name = "备注")
+    private String remarks;
+
+    private List<TElQuAnswer> answerList;
+    private List<String> repoIds;
+
+    public void setQuId(Long quId)
+    {
+        this.quId = quId;
+    }
+
+    public Long getQuId()
+    {
+        return quId;
+    }
+    public void setQuType(Long quType)
+    {
+        this.quType = quType;
+    }
+
+    public Long getQuType()
+    {
+        return quType;
+    }
+
+    public Long getQlevel() {
+        return qlevel;
+    }
+
+    public void setQlevel(Long qlevel) {
+        this.qlevel = qlevel;
+    }
+
+    public void setContent(String content)
+    {
+        this.content = content;
+    }
+
+    public String getContent()
+    {
+        return content;
+    }
+    public void setImage(String image)
+    {
+        this.image = image;
+    }
+
+    public String getImage()
+    {
+        return image;
+    }
+    public void setAnalysis(String analysis)
+    {
+        this.analysis = analysis;
+    }
+
+    public String getAnalysis()
+    {
+        return analysis;
+    }
+    public void setDelFlag(Long delFlag)
+    {
+        this.delFlag = delFlag;
+    }
+
+    public Long getDelFlag()
+    {
+        return delFlag;
+    }
+    public void setCreaterCode(String createrCode)
+    {
+        this.createrCode = createrCode;
+    }
+
+    public String getCreaterCode()
+    {
+        return createrCode;
+    }
+    public void setCreatedate(Date createdate)
+    {
+        this.createdate = createdate;
+    }
+
+    public Date getCreatedate()
+    {
+        return createdate;
+    }
+    public void setUpdaterCode(String updaterCode)
+    {
+        this.updaterCode = updaterCode;
+    }
+
+    public String getUpdaterCode()
+    {
+        return updaterCode;
+    }
+    public void setUpdatedate(Date updatedate)
+    {
+        this.updatedate = updatedate;
+    }
+
+    public Date getUpdatedate()
+    {
+        return updatedate;
+    }
+    public void setDeptId(Long deptId)
+    {
+        this.deptId = deptId;
+    }
+
+    public Long getDeptId()
+    {
+        return deptId;
+    }
+    public void setRemarks(String remarks)
+    {
+        this.remarks = remarks;
+    }
+
+    public String getRemarks()
+    {
+        return remarks;
+    }
+
+    public List<TElQuAnswer> getAnswerList() {
+        return answerList;
+    }
+
+    public void setAnswerList(List<TElQuAnswer> answerList) {
+        this.answerList = answerList;
+    }
+
+    public List<String> getRepoIds() {
+        return repoIds;
+    }
+
+    public void setRepoIds(List<String> repoIds) {
+        this.repoIds = repoIds;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("quId", getQuId())
+            .append("quType", getQuType())
+            .append("content", getContent())
+            .append("image", getImage())
+            .append("analysis", getAnalysis())
+            .append("delFlag", getDelFlag())
+            .append("createrCode", getCreaterCode())
+            .append("createdate", getCreatedate())
+            .append("updaterCode", getUpdaterCode())
+            .append("updatedate", getUpdatedate())
+            .append("deptId", getDeptId())
+            .append("remarks", getRemarks())
+            .toString();
+    }
+}

+ 208 - 0
master/src/main/java/com/ruoyi/project/training/elearn/domain/TElQuAnswer.java

@@ -0,0 +1,208 @@
+package com.ruoyi.project.training.elearn.domain;
+
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import com.ruoyi.framework.web.domain.BaseEntity;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+/**
+ * 试题选项答案对象 t_el_qu_answer
+ *
+ * @author ssy
+ * @date 2024-05-28
+ */
+public class TElQuAnswer extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** id */
+    private Long answerId;
+
+    /** 题目id */
+    @Excel(name = "题目id")
+    private Long quId;
+
+    /** 是否正确答案 */
+    @Excel(name = "是否正确答案")
+    private Long isRight;
+
+    /** 答案内容 */
+    @Excel(name = "答案内容")
+    private String content;
+
+    /** 照片 */
+    @Excel(name = "照片")
+    private String image;
+
+    /** 解析 */
+    @Excel(name = "解析")
+    private String analysis;
+
+    /** 删除 */
+    private Long delFlag;
+
+    /** 创建人 */
+    @Excel(name = "创建人")
+    private String createrCode;
+
+    /** 创建时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd" , timezone = "GMT+8")
+    @Excel(name = "创建时间", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date createdate;
+
+    /** 更新人 */
+    @Excel(name = "更新人")
+    private String updaterCode;
+
+    /** 更新日期 */
+    @JsonFormat(pattern = "yyyy-MM-dd" , timezone = "GMT+8")
+    @Excel(name = "更新日期", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date updatedate;
+
+    /** 所属部门 */
+    @Excel(name = "所属部门")
+    private Long deptId;
+
+    /** 备注 */
+    @Excel(name = "备注")
+    private String remarks;
+
+    public void setAnswerId(Long answerId)
+    {
+        this.answerId = answerId;
+    }
+
+    public Long getAnswerId()
+    {
+        return answerId;
+    }
+    public void setQuId(Long quId)
+    {
+        this.quId = quId;
+    }
+
+    public Long getQuId()
+    {
+        return quId;
+    }
+    public void setIsRight(Long isRight)
+    {
+        this.isRight = isRight;
+    }
+
+    public Long getIsRight()
+    {
+        return isRight;
+    }
+    public void setContent(String content)
+    {
+        this.content = content;
+    }
+
+    public String getContent()
+    {
+        return content;
+    }
+    public void setImage(String image)
+    {
+        this.image = image;
+    }
+
+    public String getImage()
+    {
+        return image;
+    }
+    public void setAnalysis(String analysis)
+    {
+        this.analysis = analysis;
+    }
+
+    public String getAnalysis()
+    {
+        return analysis;
+    }
+    public void setDelFlag(Long delFlag)
+    {
+        this.delFlag = delFlag;
+    }
+
+    public Long getDelFlag()
+    {
+        return delFlag;
+    }
+    public void setCreaterCode(String createrCode)
+    {
+        this.createrCode = createrCode;
+    }
+
+    public String getCreaterCode()
+    {
+        return createrCode;
+    }
+    public void setCreatedate(Date createdate)
+    {
+        this.createdate = createdate;
+    }
+
+    public Date getCreatedate()
+    {
+        return createdate;
+    }
+    public void setUpdaterCode(String updaterCode)
+    {
+        this.updaterCode = updaterCode;
+    }
+
+    public String getUpdaterCode()
+    {
+        return updaterCode;
+    }
+    public void setUpdatedate(Date updatedate)
+    {
+        this.updatedate = updatedate;
+    }
+
+    public Date getUpdatedate()
+    {
+        return updatedate;
+    }
+    public void setDeptId(Long deptId)
+    {
+        this.deptId = deptId;
+    }
+
+    public Long getDeptId()
+    {
+        return deptId;
+    }
+    public void setRemarks(String remarks)
+    {
+        this.remarks = remarks;
+    }
+
+    public String getRemarks()
+    {
+        return remarks;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("answerId", getAnswerId())
+            .append("quId", getQuId())
+            .append("isRight", getIsRight())
+            .append("content", getContent())
+            .append("image", getImage())
+            .append("analysis", getAnalysis())
+            .append("delFlag", getDelFlag())
+            .append("createrCode", getCreaterCode())
+            .append("createdate", getCreatedate())
+            .append("updaterCode", getUpdaterCode())
+            .append("updatedate", getUpdatedate())
+            .append("deptId", getDeptId())
+            .append("remarks", getRemarks())
+            .toString();
+    }
+}

+ 94 - 0
master/src/main/java/com/ruoyi/project/training/elearn/domain/TElQuRepo.java

@@ -0,0 +1,94 @@
+package com.ruoyi.project.training.elearn.domain;
+
+import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import com.ruoyi.framework.web.domain.BaseEntity;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+/**
+ * 题目题库关联对象 t_el_qu_repo
+ *
+ * @author ssy
+ * @date 2024-05-28
+ */
+public class TElQuRepo extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** id */
+    private Long id;
+
+    /** 题目id
+ */
+
+    private Long quId;
+
+    /** 题库id */
+    @Excel(name = "题库id")
+    private Long repoId;
+
+    /** 题目类型 */
+    @Excel(name = "题目类型")
+    private Long quType;
+
+    /** 排序 */
+    @Excel(name = "排序")
+    private Long sort;
+
+    public void setId(Long id)
+    {
+        this.id = id;
+    }
+
+    public Long getId()
+    {
+        return id;
+    }
+    public void setQuId(Long quId)
+    {
+        this.quId = quId;
+    }
+
+    public Long getQuId()
+    {
+        return quId;
+    }
+    public void setRepoId(Long repoId)
+    {
+        this.repoId = repoId;
+    }
+
+    public Long getRepoId()
+    {
+        return repoId;
+    }
+    public void setQuType(Long quType)
+    {
+        this.quType = quType;
+    }
+
+    public Long getQuType()
+    {
+        return quType;
+    }
+    public void setSort(Long sort)
+    {
+        this.sort = sort;
+    }
+
+    public Long getSort()
+    {
+        return sort;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("id", getId())
+            .append("quId", getQuId())
+            .append("repoId", getRepoId())
+            .append("quType", getQuType())
+            .append("sort", getSort())
+            .toString();
+    }
+}

+ 194 - 0
master/src/main/java/com/ruoyi/project/training/elearn/domain/TElRepo.java

@@ -0,0 +1,194 @@
+package com.ruoyi.project.training.elearn.domain;
+
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import com.ruoyi.framework.web.domain.BaseEntity;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+/**
+ * 题库对象 t_el_repo
+ *
+ * @author ssy
+ * @date 2024-05-27
+ */
+public class TElRepo extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** id */
+    private Long repoId;
+
+    /** 题库编号 */
+    @Excel(name = "题库编号")
+    private String code;
+
+    /** 题库名称 */
+    @Excel(name = "题库名称")
+    private String title;
+
+    /** 删除 */
+    private Long delFlag;
+
+    /** 创建人 */
+    @Excel(name = "创建人")
+    private String createrCode;
+
+    /** 创建时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd" , timezone = "GMT+8")
+    @Excel(name = "创建时间", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date createdate;
+
+    /** 更新人 */
+    @Excel(name = "更新人")
+    private String updaterCode;
+
+    /** 更新日期 */
+    @JsonFormat(pattern = "yyyy-MM-dd" , timezone = "GMT+8")
+    @Excel(name = "更新日期", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date updatedate;
+
+    /** 所属部门 */
+    @Excel(name = "所属部门")
+    private Long deptId;
+
+    /** 备注 */
+    @Excel(name = "备注")
+    private String remarks;
+
+    private Long radioCount;
+    private Long multiCount;
+    private Long judgeCount;
+
+    public void setRepoId(Long repoId)
+    {
+        this.repoId = repoId;
+    }
+
+    public Long getRepoId()
+    {
+        return repoId;
+    }
+    public void setCode(String code)
+    {
+        this.code = code;
+    }
+
+    public String getCode()
+    {
+        return code;
+    }
+    public void setTitle(String title)
+    {
+        this.title = title;
+    }
+
+    public String getTitle()
+    {
+        return title;
+    }
+    public void setDelFlag(Long delFlag)
+    {
+        this.delFlag = delFlag;
+    }
+
+    public Long getDelFlag()
+    {
+        return delFlag;
+    }
+    public void setCreaterCode(String createrCode)
+    {
+        this.createrCode = createrCode;
+    }
+
+    public String getCreaterCode()
+    {
+        return createrCode;
+    }
+    public void setCreatedate(Date createdate)
+    {
+        this.createdate = createdate;
+    }
+
+    public Date getCreatedate()
+    {
+        return createdate;
+    }
+    public void setUpdaterCode(String updaterCode)
+    {
+        this.updaterCode = updaterCode;
+    }
+
+    public String getUpdaterCode()
+    {
+        return updaterCode;
+    }
+    public void setUpdatedate(Date updatedate)
+    {
+        this.updatedate = updatedate;
+    }
+
+    public Date getUpdatedate()
+    {
+        return updatedate;
+    }
+    public void setDeptId(Long deptId)
+    {
+        this.deptId = deptId;
+    }
+
+    public Long getDeptId()
+    {
+        return deptId;
+    }
+    public void setRemarks(String remarks)
+    {
+        this.remarks = remarks;
+    }
+
+    public String getRemarks()
+    {
+        return remarks;
+    }
+
+    public Long getRadioCount() {
+        return radioCount;
+    }
+
+    public void setRadioCount(Long radioCount) {
+        this.radioCount = radioCount;
+    }
+
+    public Long getMultiCount() {
+        return multiCount;
+    }
+
+    public void setMultiCount(Long multiCount) {
+        this.multiCount = multiCount;
+    }
+
+    public Long getJudgeCount() {
+        return judgeCount;
+    }
+
+    public void setJudgeCount(Long judgeCount) {
+        this.judgeCount = judgeCount;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("repoId", getRepoId())
+            .append("code", getCode())
+            .append("title", getTitle())
+            .append("delFlag", getDelFlag())
+            .append("createrCode", getCreaterCode())
+            .append("createdate", getCreatedate())
+            .append("updaterCode", getUpdaterCode())
+            .append("updatedate", getUpdatedate())
+            .append("deptId", getDeptId())
+            .append("remarks", getRemarks())
+            .toString();
+    }
+}

+ 46 - 0
master/src/main/java/com/ruoyi/project/training/elearn/job/BreakExamJob.java

@@ -0,0 +1,46 @@
+package com.ruoyi.project.training.elearn.job;
+
+
+import com.ruoyi.framework.job.service.JobService;
+import com.ruoyi.project.training.elearn.service.ITElPaperService;
+import lombok.extern.log4j.Log4j2;
+import org.quartz.Job;
+import org.quartz.JobDetail;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobExecutionException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ * 超时自动交卷任务
+ * @author bool
+ */
+@Log4j2
+@Component
+public class BreakExamJob implements Job {
+
+    @Autowired
+    private ITElPaperService paperService;
+
+    @Override
+    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
+
+        JobDetail detail = jobExecutionContext.getJobDetail();
+        String name = detail.getKey().getName();
+        String group = detail.getKey().getGroup();
+        String data = String.valueOf(detail.getJobDataMap().get(JobService.TASK_DATA));
+
+        log.info("++++++++++定时任务:处理到期的交卷");
+        log.info("++++++++++jobName:{}", name);
+        log.info("++++++++++jobGroup:{}", group);
+        log.info("++++++++++taskData:{}", data);
+
+
+        // 强制交卷
+//        paperService.handExam(data);
+
+    }
+
+
+
+}

+ 63 - 0
master/src/main/java/com/ruoyi/project/training/elearn/mapper/TElExamMapper.java

@@ -0,0 +1,63 @@
+package com.ruoyi.project.training.elearn.mapper;
+
+import java.util.List;
+import com.ruoyi.framework.aspectj.lang.annotation.DataScope;
+import com.ruoyi.project.training.elearn.domain.TElExam;
+
+/**
+ * 考试Mapper接口
+ * 
+ * @author ssy
+ * @date 2024-05-29
+ */
+public interface TElExamMapper 
+{
+    /**
+     * 查询考试
+     * 
+     * @param examId 考试ID
+     * @return 考试
+     */
+    public TElExam selectTElExamById(Long examId);
+
+    /**
+     * 查询考试列表
+     * 
+     * @param tElExam 考试
+     * @return 考试集合
+     */
+    @DataScope(deptAlias = "d")
+    public List<TElExam> selectTElExamList(TElExam tElExam);
+
+    /**
+     * 新增考试
+     * 
+     * @param tElExam 考试
+     * @return 结果
+     */
+    public int insertTElExam(TElExam tElExam);
+
+    /**
+     * 修改考试
+     * 
+     * @param tElExam 考试
+     * @return 结果
+     */
+    public int updateTElExam(TElExam tElExam);
+
+    /**
+     * 删除考试
+     * 
+     * @param examId 考试ID
+     * @return 结果
+     */
+    public int deleteTElExamById(Long examId);
+
+    /**
+     * 批量删除考试
+     * 
+     * @param examIds 需要删除的数据ID
+     * @return 结果
+     */
+    public int deleteTElExamByIds(Long[] examIds);
+}

+ 64 - 0
master/src/main/java/com/ruoyi/project/training/elearn/mapper/TElExamRepoMapper.java

@@ -0,0 +1,64 @@
+package com.ruoyi.project.training.elearn.mapper;
+
+import java.util.List;
+import com.ruoyi.framework.aspectj.lang.annotation.DataScope;
+import com.ruoyi.project.training.elearn.domain.TElExamRepo;
+
+/**
+ * 考试题库关联Mapper接口
+ *
+ * @author ssy
+ * @date 2024-05-29
+ */
+public interface TElExamRepoMapper
+{
+    /**
+     * 查询考试题库关联
+     *
+     * @param id 考试题库关联ID
+     * @return 考试题库关联
+     */
+    public TElExamRepo selectTElExamRepoById(Long id);
+
+    /**
+     * 查询考试题库关联列表
+     *
+     * @param tElExamRepo 考试题库关联
+     * @return 考试题库关联集合
+     */
+    public List<TElExamRepo> selectTElExamRepoList(TElExamRepo tElExamRepo);
+
+    /**
+     * 新增考试题库关联
+     *
+     * @param tElExamRepo 考试题库关联
+     * @return 结果
+     */
+    public int insertTElExamRepo(TElExamRepo tElExamRepo);
+
+    /**
+     * 修改考试题库关联
+     *
+     * @param tElExamRepo 考试题库关联
+     * @return 结果
+     */
+    public int updateTElExamRepo(TElExamRepo tElExamRepo);
+
+    /**
+     * 删除考试题库关联
+     *
+     * @param id 考试题库关联ID
+     * @return 结果
+     */
+    public int deleteTElExamRepoById(Long id);
+
+    /**
+     * 批量删除考试题库关联
+     *
+     * @param ids 需要删除的数据ID
+     * @return 结果
+     */
+    public int deleteTElExamRepoByIds(Long[] ids);
+
+    void deleteTElExamRepoByExamId(Long examId);
+}

+ 63 - 0
master/src/main/java/com/ruoyi/project/training/elearn/mapper/TElPaperMapper.java

@@ -0,0 +1,63 @@
+package com.ruoyi.project.training.elearn.mapper;
+
+import java.util.List;
+import com.ruoyi.framework.aspectj.lang.annotation.DataScope;
+import com.ruoyi.project.training.elearn.domain.TElPaper;
+
+/**
+ * 在线考试Mapper接口
+ * 
+ * @author ssy
+ * @date 2024-05-29
+ */
+public interface TElPaperMapper 
+{
+    /**
+     * 查询在线考试
+     * 
+     * @param paperId 在线考试ID
+     * @return 在线考试
+     */
+    public TElPaper selectTElPaperById(Long paperId);
+
+    /**
+     * 查询在线考试列表
+     * 
+     * @param tElPaper 在线考试
+     * @return 在线考试集合
+     */
+    @DataScope(deptAlias = "d")
+    public List<TElPaper> selectTElPaperList(TElPaper tElPaper);
+
+    /**
+     * 新增在线考试
+     * 
+     * @param tElPaper 在线考试
+     * @return 结果
+     */
+    public int insertTElPaper(TElPaper tElPaper);
+
+    /**
+     * 修改在线考试
+     * 
+     * @param tElPaper 在线考试
+     * @return 结果
+     */
+    public int updateTElPaper(TElPaper tElPaper);
+
+    /**
+     * 删除在线考试
+     * 
+     * @param paperId 在线考试ID
+     * @return 结果
+     */
+    public int deleteTElPaperById(Long paperId);
+
+    /**
+     * 批量删除在线考试
+     * 
+     * @param paperIds 需要删除的数据ID
+     * @return 结果
+     */
+    public int deleteTElPaperByIds(Long[] paperIds);
+}

+ 63 - 0
master/src/main/java/com/ruoyi/project/training/elearn/mapper/TElPaperQuAnswerMapper.java

@@ -0,0 +1,63 @@
+package com.ruoyi.project.training.elearn.mapper;
+
+import java.util.List;
+import com.ruoyi.framework.aspectj.lang.annotation.DataScope;
+import com.ruoyi.project.training.elearn.domain.TElPaperQuAnswer;
+
+/**
+ * 试卷题目答案Mapper接口
+ * 
+ * @author ssy
+ * @date 2024-05-29
+ */
+public interface TElPaperQuAnswerMapper 
+{
+    /**
+     * 查询试卷题目答案
+     * 
+     * @param id 试卷题目答案ID
+     * @return 试卷题目答案
+     */
+    public TElPaperQuAnswer selectTElPaperQuAnswerById(Long id);
+
+    /**
+     * 查询试卷题目答案列表
+     * 
+     * @param tElPaperQuAnswer 试卷题目答案
+     * @return 试卷题目答案集合
+     */
+    @DataScope(deptAlias = "d")
+    public List<TElPaperQuAnswer> selectTElPaperQuAnswerList(TElPaperQuAnswer tElPaperQuAnswer);
+
+    /**
+     * 新增试卷题目答案
+     * 
+     * @param tElPaperQuAnswer 试卷题目答案
+     * @return 结果
+     */
+    public int insertTElPaperQuAnswer(TElPaperQuAnswer tElPaperQuAnswer);
+
+    /**
+     * 修改试卷题目答案
+     * 
+     * @param tElPaperQuAnswer 试卷题目答案
+     * @return 结果
+     */
+    public int updateTElPaperQuAnswer(TElPaperQuAnswer tElPaperQuAnswer);
+
+    /**
+     * 删除试卷题目答案
+     * 
+     * @param id 试卷题目答案ID
+     * @return 结果
+     */
+    public int deleteTElPaperQuAnswerById(Long id);
+
+    /**
+     * 批量删除试卷题目答案
+     * 
+     * @param ids 需要删除的数据ID
+     * @return 结果
+     */
+    public int deleteTElPaperQuAnswerByIds(Long[] ids);
+}

+ 63 - 0
master/src/main/java/com/ruoyi/project/training/elearn/mapper/TElPaperQuMapper.java

@@ -0,0 +1,63 @@
+package com.ruoyi.project.training.elearn.mapper;
+
+import java.util.List;
+import com.ruoyi.framework.aspectj.lang.annotation.DataScope;
+import com.ruoyi.project.training.elearn.domain.TElPaperQu;
+
+/**
+ * 试卷题目Mapper接口
+ * 
+ * @author ssy
+ * @date 2024-05-29
+ */
+public interface TElPaperQuMapper 
+{
+    /**
+     * 查询试卷题目
+     * 
+     * @param id 试卷题目ID
+     * @return 试卷题目
+     */
+    public TElPaperQu selectTElPaperQuById(Long id);
+
+    /**
+     * 查询试卷题目列表
+     * 
+     * @param tElPaperQu 试卷题目
+     * @return 试卷题目集合
+     */
+    @DataScope(deptAlias = "d")
+    public List<TElPaperQu> selectTElPaperQuList(TElPaperQu tElPaperQu);
+
+    /**
+     * 新增试卷题目
+     * 
+     * @param tElPaperQu 试卷题目
+     * @return 结果
+     */
+    public int insertTElPaperQu(TElPaperQu tElPaperQu);
+
+    /**
+     * 修改试卷题目
+     * 
+     * @param tElPaperQu 试卷题目
+     * @return 结果
+     */
+    public int updateTElPaperQu(TElPaperQu tElPaperQu);
+
+    /**
+     * 删除试卷题目
+     * 
+     * @param id 试卷题目ID
+     * @return 结果
+     */
+    public int deleteTElPaperQuById(Long id);
+
+    /**
+     * 批量删除试卷题目
+     * 
+     * @param ids 需要删除的数据ID
+     * @return 结果
+     */
+    public int deleteTElPaperQuByIds(Long[] ids);
+}

+ 62 - 0
master/src/main/java/com/ruoyi/project/training/elearn/mapper/TElQuAnswerMapper.java

@@ -0,0 +1,62 @@
+package com.ruoyi.project.training.elearn.mapper;
+
+import java.util.List;
+import com.ruoyi.framework.aspectj.lang.annotation.DataScope;
+import com.ruoyi.project.training.elearn.domain.TElQuAnswer;
+
+/**
+ * 试题选项答案Mapper接口
+ *
+ * @author ssy
+ * @date 2024-05-28
+ */
+public interface TElQuAnswerMapper
+{
+    /**
+     * 查询试题选项答案
+     *
+     * @param answerId 试题选项答案ID
+     * @return 试题选项答案
+     */
+    public TElQuAnswer selectTElQuAnswerById(Long answerId);
+
+    /**
+     * 查询试题选项答案列表
+     *
+     * @param tElQuAnswer 试题选项答案
+     * @return 试题选项答案集合
+     */
+    public List<TElQuAnswer> selectTElQuAnswerList(TElQuAnswer tElQuAnswer);
+
+    /**
+     * 新增试题选项答案
+     *
+     * @param tElQuAnswer 试题选项答案
+     * @return 结果
+     */
+    public int insertTElQuAnswer(TElQuAnswer tElQuAnswer);
+
+    /**
+     * 修改试题选项答案
+     *
+     * @param tElQuAnswer 试题选项答案
+     * @return 结果
+     */
+    public int updateTElQuAnswer(TElQuAnswer tElQuAnswer);
+
+    /**
+     * 删除试题选项答案
+     *
+     * @param answerId 试题选项答案ID
+     * @return 结果
+     */
+    public int deleteTElQuAnswerById(Long answerId);
+
+    /**
+     * 批量删除试题选项答案
+     *
+     * @param answerIds 需要删除的数据ID
+     * @return 结果
+     */
+    public int deleteTElQuAnswerByIds(Long[] answerIds);
+}

+ 65 - 0
master/src/main/java/com/ruoyi/project/training/elearn/mapper/TElQuMapper.java

@@ -0,0 +1,65 @@
+package com.ruoyi.project.training.elearn.mapper;
+
+import java.util.List;
+import com.ruoyi.framework.aspectj.lang.annotation.DataScope;
+import com.ruoyi.project.training.elearn.domain.TElExamRepo;
+import com.ruoyi.project.training.elearn.domain.TElQu;
+
+/**
+ * 试题Mapper接口
+ *
+ * @author ssy
+ * @date 2024-05-28
+ */
+public interface TElQuMapper
+{
+    /**
+     * 查询试题
+     *
+     * @param quId 试题ID
+     * @return 试题
+     */
+    public TElQu selectTElQuById(Long quId);
+
+    /**
+     * 查询试题列表
+     *
+     * @param tElQu 试题
+     * @return 试题集合
+     */
+    public List<TElQu> selectTElQuList(TElQu tElQu);
+
+    /**
+     * 新增试题
+     *
+     * @param tElQu 试题
+     * @return 结果
+     */
+    public int insertTElQu(TElQu tElQu);
+
+    /**
+     * 修改试题
+     *
+     * @param tElQu 试题
+     * @return 结果
+     */
+    public int updateTElQu(TElQu tElQu);
+
+    /**
+     * 删除试题
+     *
+     * @param quId 试题ID
+     * @return 结果
+     */
+    public int deleteTElQuById(Long quId);
+
+    /**
+     * 批量删除试题
+     *
+     * @param quIds 需要删除的数据ID
+     * @return 结果
+     */
+    public int deleteTElQuByIds(Long[] quIds);
+
+    List<TElQu> selectTElQuListByRepo(TElExamRepo item);
+}

+ 63 - 0
master/src/main/java/com/ruoyi/project/training/elearn/mapper/TElQuRepoMapper.java

@@ -0,0 +1,63 @@
+package com.ruoyi.project.training.elearn.mapper;
+
+import java.util.List;
+import com.ruoyi.framework.aspectj.lang.annotation.DataScope;
+import com.ruoyi.project.training.elearn.domain.TElQuRepo;
+
+/**
+ * 题目题库关联Mapper接口
+ * 
+ * @author ssy
+ * @date 2024-05-28
+ */
+public interface TElQuRepoMapper 
+{
+    /**
+     * 查询题目题库关联
+     * 
+     * @param id 题目题库关联ID
+     * @return 题目题库关联
+     */
+    public TElQuRepo selectTElQuRepoById(Long id);
+
+    /**
+     * 查询题目题库关联列表
+     * 
+     * @param tElQuRepo 题目题库关联
+     * @return 题目题库关联集合
+     */
+    @DataScope(deptAlias = "d")
+    public List<TElQuRepo> selectTElQuRepoList(TElQuRepo tElQuRepo);
+
+    /**
+     * 新增题目题库关联
+     * 
+     * @param tElQuRepo 题目题库关联
+     * @return 结果
+     */
+    public int insertTElQuRepo(TElQuRepo tElQuRepo);
+
+    /**
+     * 修改题目题库关联
+     * 
+     * @param tElQuRepo 题目题库关联
+     * @return 结果
+     */
+    public int updateTElQuRepo(TElQuRepo tElQuRepo);
+
+    /**
+     * 删除题目题库关联
+     * 
+     * @param id 题目题库关联ID
+     * @return 结果
+     */
+    public int deleteTElQuRepoById(Long id);
+
+    /**
+     * 批量删除题目题库关联
+     * 
+     * @param ids 需要删除的数据ID
+     * @return 结果
+     */
+    public int deleteTElQuRepoByIds(Long[] ids);
+}

+ 63 - 0
master/src/main/java/com/ruoyi/project/training/elearn/mapper/TElRepoMapper.java

@@ -0,0 +1,63 @@
+package com.ruoyi.project.training.elearn.mapper;
+
+import java.util.List;
+import com.ruoyi.framework.aspectj.lang.annotation.DataScope;
+import com.ruoyi.project.training.elearn.domain.TElRepo;
+
+/**
+ * 题库Mapper接口
+ * 
+ * @author ssy
+ * @date 2024-05-27
+ */
+public interface TElRepoMapper 
+{
+    /**
+     * 查询题库
+     * 
+     * @param repoId 题库ID
+     * @return 题库
+     */
+    public TElRepo selectTElRepoById(Long repoId);
+
+    /**
+     * 查询题库列表
+     * 
+     * @param tElRepo 题库
+     * @return 题库集合
+     */
+    @DataScope(deptAlias = "d")
+    public List<TElRepo> selectTElRepoList(TElRepo tElRepo);
+
+    /**
+     * 新增题库
+     * 
+     * @param tElRepo 题库
+     * @return 结果
+     */
+    public int insertTElRepo(TElRepo tElRepo);
+
+    /**
+     * 修改题库
+     * 
+     * @param tElRepo 题库
+     * @return 结果
+     */
+    public int updateTElRepo(TElRepo tElRepo);
+
+    /**
+     * 删除题库
+     * 
+     * @param repoId 题库ID
+     * @return 结果
+     */
+    public int deleteTElRepoById(Long repoId);
+
+    /**
+     * 批量删除题库
+     * 
+     * @param repoIds 需要删除的数据ID
+     * @return 结果
+     */
+    public int deleteTElRepoByIds(Long[] repoIds);
+}

+ 61 - 0
master/src/main/java/com/ruoyi/project/training/elearn/service/ITElExamService.java

@@ -0,0 +1,61 @@
+package com.ruoyi.project.training.elearn.service;
+
+import java.util.List;
+import com.ruoyi.project.training.elearn.domain.TElExam;
+
+/**
+ * 考试Service接口
+ * 
+ * @author ssy
+ * @date 2024-05-29
+ */
+public interface ITElExamService 
+{
+    /**
+     * 查询考试
+     * 
+     * @param examId 考试ID
+     * @return 考试
+     */
+    public TElExam selectTElExamById(Long examId);
+
+    /**
+     * 查询考试列表
+     * 
+     * @param tElExam 考试
+     * @return 考试集合
+     */
+    public List<TElExam> selectTElExamList(TElExam tElExam);
+
+    /**
+     * 新增考试
+     * 
+     * @param tElExam 考试
+     * @return 结果
+     */
+    public int insertTElExam(TElExam tElExam);
+
+    /**
+     * 修改考试
+     * 
+     * @param tElExam 考试
+     * @return 结果
+     */
+    public int updateTElExam(TElExam tElExam);
+
+    /**
+     * 批量删除考试
+     * 
+     * @param examIds 需要删除的考试ID
+     * @return 结果
+     */
+    public int deleteTElExamByIds(Long[] examIds);
+
+    /**
+     * 删除考试信息
+     * 
+     * @param examId 考试ID
+     * @return 结果
+     */
+    public int deleteTElExamById(Long examId);
+}

+ 63 - 0
master/src/main/java/com/ruoyi/project/training/elearn/service/ITElPaperService.java

@@ -0,0 +1,63 @@
+package com.ruoyi.project.training.elearn.service;
+
+import java.util.List;
+import com.ruoyi.project.training.elearn.domain.TElPaper;
+
+/**
+ * 在线考试Service接口
+ *
+ * @author ssy
+ * @date 2024-05-29
+ */
+public interface ITElPaperService
+{
+    /**
+     * 查询在线考试
+     *
+     * @param paperId 在线考试ID
+     * @return 在线考试
+     */
+    public TElPaper selectTElPaperById(Long paperId);
+
+    /**
+     * 查询在线考试列表
+     *
+     * @param tElPaper 在线考试
+     * @return 在线考试集合
+     */
+    public List<TElPaper> selectTElPaperList(TElPaper tElPaper);
+
+    /**
+     * 新增在线考试
+     *
+     * @param tElPaper 在线考试
+     * @return 结果
+     */
+    public int insertTElPaper(TElPaper tElPaper);
+
+    /**
+     * 修改在线考试
+     *
+     * @param tElPaper 在线考试
+     * @return 结果
+     */
+    public int updateTElPaper(TElPaper tElPaper);
+
+    /**
+     * 批量删除在线考试
+     *
+     * @param paperIds 需要删除的在线考试ID
+     * @return 结果
+     */
+    public int deleteTElPaperByIds(Long[] paperIds);
+
+    /**
+     * 删除在线考试信息
+     *
+     * @param paperId 在线考试ID
+     * @return 结果
+     */
+    public int deleteTElPaperById(Long paperId);
+
+    TElPaper createPaper(TElPaper tElPaper, Long userId);
+}

+ 61 - 0
master/src/main/java/com/ruoyi/project/training/elearn/service/ITElQuAnswerService.java

@@ -0,0 +1,61 @@
+package com.ruoyi.project.training.elearn.service;
+
+import java.util.List;
+import com.ruoyi.project.training.elearn.domain.TElQuAnswer;
+
+/**
+ * 试题选项答案Service接口
+ * 
+ * @author ssy
+ * @date 2024-05-28
+ */
+public interface ITElQuAnswerService 
+{
+    /**
+     * 查询试题选项答案
+     * 
+     * @param answerId 试题选项答案ID
+     * @return 试题选项答案
+     */
+    public TElQuAnswer selectTElQuAnswerById(Long answerId);
+
+    /**
+     * 查询试题选项答案列表
+     * 
+     * @param tElQuAnswer 试题选项答案
+     * @return 试题选项答案集合
+     */
+    public List<TElQuAnswer> selectTElQuAnswerList(TElQuAnswer tElQuAnswer);
+
+    /**
+     * 新增试题选项答案
+     * 
+     * @param tElQuAnswer 试题选项答案
+     * @return 结果
+     */
+    public int insertTElQuAnswer(TElQuAnswer tElQuAnswer);
+
+    /**
+     * 修改试题选项答案
+     * 
+     * @param tElQuAnswer 试题选项答案
+     * @return 结果
+     */
+    public int updateTElQuAnswer(TElQuAnswer tElQuAnswer);
+
+    /**
+     * 批量删除试题选项答案
+     * 
+     * @param answerIds 需要删除的试题选项答案ID
+     * @return 结果
+     */
+    public int deleteTElQuAnswerByIds(Long[] answerIds);
+
+    /**
+     * 删除试题选项答案信息
+     * 
+     * @param answerId 试题选项答案ID
+     * @return 结果
+     */
+    public int deleteTElQuAnswerById(Long answerId);
+}

+ 61 - 0
master/src/main/java/com/ruoyi/project/training/elearn/service/ITElQuService.java

@@ -0,0 +1,61 @@
+package com.ruoyi.project.training.elearn.service;
+
+import java.util.List;
+import com.ruoyi.project.training.elearn.domain.TElQu;
+
+/**
+ * 试题Service接口
+ * 
+ * @author ssy
+ * @date 2024-05-28
+ */
+public interface ITElQuService 
+{
+    /**
+     * 查询试题
+     * 
+     * @param quId 试题ID
+     * @return 试题
+     */
+    public TElQu selectTElQuById(Long quId);
+
+    /**
+     * 查询试题列表
+     * 
+     * @param tElQu 试题
+     * @return 试题集合
+     */
+    public List<TElQu> selectTElQuList(TElQu tElQu);
+
+    /**
+     * 新增试题
+     * 
+     * @param tElQu 试题
+     * @return 结果
+     */
+    public int insertTElQu(TElQu tElQu);
+
+    /**
+     * 修改试题
+     * 
+     * @param tElQu 试题
+     * @return 结果
+     */
+    public int updateTElQu(TElQu tElQu);
+
+    /**
+     * 批量删除试题
+     * 
+     * @param quIds 需要删除的试题ID
+     * @return 结果
+     */
+    public int deleteTElQuByIds(Long[] quIds);
+
+    /**
+     * 删除试题信息
+     * 
+     * @param quId 试题ID
+     * @return 结果
+     */
+    public int deleteTElQuById(Long quId);
+}

+ 61 - 0
master/src/main/java/com/ruoyi/project/training/elearn/service/ITElRepoService.java

@@ -0,0 +1,61 @@
+package com.ruoyi.project.training.elearn.service;
+
+import java.util.List;
+import com.ruoyi.project.training.elearn.domain.TElRepo;
+
+/**
+ * 题库Service接口
+ * 
+ * @author ssy
+ * @date 2024-05-27
+ */
+public interface ITElRepoService 
+{
+    /**
+     * 查询题库
+     * 
+     * @param repoId 题库ID
+     * @return 题库
+     */
+    public TElRepo selectTElRepoById(Long repoId);
+
+    /**
+     * 查询题库列表
+     * 
+     * @param tElRepo 题库
+     * @return 题库集合
+     */
+    public List<TElRepo> selectTElRepoList(TElRepo tElRepo);
+
+    /**
+     * 新增题库
+     * 
+     * @param tElRepo 题库
+     * @return 结果
+     */
+    public int insertTElRepo(TElRepo tElRepo);
+
+    /**
+     * 修改题库
+     * 
+     * @param tElRepo 题库
+     * @return 结果
+     */
+    public int updateTElRepo(TElRepo tElRepo);
+
+    /**
+     * 批量删除题库
+     * 
+     * @param repoIds 需要删除的题库ID
+     * @return 结果
+     */
+    public int deleteTElRepoByIds(Long[] repoIds);
+
+    /**
+     * 删除题库信息
+     * 
+     * @param repoId 题库ID
+     * @return 结果
+     */
+    public int deleteTElRepoById(Long repoId);
+}

+ 126 - 0
master/src/main/java/com/ruoyi/project/training/elearn/service/impl/TElExamServiceImpl.java

@@ -0,0 +1,126 @@
+package com.ruoyi.project.training.elearn.service.impl;
+
+import java.util.List;
+
+import com.ruoyi.project.training.elearn.domain.TElExamRepo;
+import com.ruoyi.project.training.elearn.mapper.TElExamRepoMapper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.ruoyi.project.training.elearn.mapper.TElExamMapper;
+import com.ruoyi.project.training.elearn.domain.TElExam;
+import com.ruoyi.project.training.elearn.service.ITElExamService;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.Resource;
+
+/**
+ * 考试Service业务层处理
+ *
+ * @author ssy
+ * @date 2024-05-29
+ */
+@Service
+public class TElExamServiceImpl implements ITElExamService
+{
+    @Resource
+    private TElExamMapper tElExamMapper;
+    @Resource
+    private TElExamRepoMapper tElExamRepoMapper;
+    /**
+     * 查询考试
+     *
+     * @param examId 考试ID
+     * @return 考试
+     */
+    @Override
+    public TElExam selectTElExamById(Long examId)
+    {
+        TElExam tElExam = tElExamMapper.selectTElExamById(examId);
+        TElExamRepo quey = new TElExamRepo();
+        quey.setExamId(examId);
+        List<TElExamRepo> list = tElExamRepoMapper.selectTElExamRepoList(quey);
+        tElExam.setRepoList(list);
+        return tElExam;
+    }
+
+    /**
+     * 查询考试列表
+     *
+     * @param tElExam 考试
+     * @return 考试
+     */
+    @Override
+    public List<TElExam> selectTElExamList(TElExam tElExam)
+    {
+        return tElExamMapper.selectTElExamList(tElExam);
+    }
+
+    /**
+     * 新增考试
+     *
+     * @param tElExam 考试
+     * @return 结果
+     */
+    @Override
+    @Transactional
+    public int insertTElExam(TElExam tElExam)
+    {
+        tElExamMapper.insertTElExam(tElExam);
+        List<TElExamRepo> list = tElExam.getRepoList();
+        for (TElExamRepo t: list
+             ) {
+            t.setExamId(tElExam.getExamId());
+            tElExamRepoMapper.insertTElExamRepo(t);
+        }
+        return 1;
+    }
+
+    /**
+     * 修改考试
+     *
+     * @param tElExam 考试
+     * @return 结果
+     */
+    @Override
+    @Transactional
+    public int updateTElExam(TElExam tElExam)
+    {
+        tElExamMapper.updateTElExam(tElExam);
+        //删除库
+
+        tElExamRepoMapper.deleteTElExamRepoByExamId(tElExam.getExamId());
+
+        List<TElExamRepo> list = tElExam.getRepoList();
+        for (TElExamRepo t: list
+        ) {
+            t.setExamId(tElExam.getExamId());
+            tElExamRepoMapper.insertTElExamRepo(t);
+        }
+
+        return 1;
+    }
+
+    /**
+     * 批量删除考试
+     *
+     * @param examIds 需要删除的考试ID
+     * @return 结果
+     */
+    @Override
+    public int deleteTElExamByIds(Long[] examIds)
+    {
+        return tElExamMapper.deleteTElExamByIds(examIds);
+    }
+
+    /**
+     * 删除考试信息
+     *
+     * @param examId 考试ID
+     * @return 结果
+     */
+    @Override
+    public int deleteTElExamById(Long examId)
+    {
+        return tElExamMapper.deleteTElExamById(examId);
+    }
+}

+ 297 - 0
master/src/main/java/com/ruoyi/project/training/elearn/service/impl/TElPaperServiceImpl.java

@@ -0,0 +1,297 @@
+package com.ruoyi.project.training.elearn.service.impl;
+
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+import com.ruoyi.framework.job.service.JobService;
+import com.ruoyi.project.training.elearn.domain.*;
+import com.ruoyi.project.training.elearn.mapper.*;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.ruoyi.project.training.elearn.service.ITElPaperService;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+
+import javax.annotation.Resource;
+
+/**
+ * 在线考试Service业务层处理
+ *
+ * @author ssy
+ * @date 2024-05-29
+ */
+@Service
+public class TElPaperServiceImpl implements ITElPaperService
+{
+    /**
+     * 展示的选项,ABC这样
+     */
+    private static List<String> ABC = Arrays.asList(new String[]{
+            "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K","L","M","N","O","P","Q","R","S","T","U","V","W","X"
+            ,"Y","Z"
+    });
+
+    @Resource
+    private TElPaperMapper tElPaperMapper;
+    @Resource
+    private TElPaperQuMapper tElPaperQuMapper;
+    @Resource
+    private TElPaperQuAnswerMapper tElPaperQuAnswerMapper;
+    @Autowired
+    private JobService jobService;
+    @Resource
+    private TElExamMapper tElExamMapper;
+    @Resource
+    private TElQuMapper tElQuMapper;
+    @Resource
+    private TElQuAnswerMapper tElQuAnswerMapper;
+    @Resource
+    private TElExamRepoMapper tElExamRepoMapper;
+    /**
+     * 查询在线考试
+     *
+     * @param paperId 在线考试ID
+     * @return 在线考试
+     */
+    @Override
+    public TElPaper selectTElPaperById(Long paperId)
+    {
+        return tElPaperMapper.selectTElPaperById(paperId);
+    }
+
+    /**
+     * 查询在线考试列表
+     *
+     * @param tElPaper 在线考试
+     * @return 在线考试
+     */
+    @Override
+    public List<TElPaper> selectTElPaperList(TElPaper tElPaper)
+    {
+        return tElPaperMapper.selectTElPaperList(tElPaper);
+    }
+
+    /**
+     * 新增在线考试
+     *
+     * @param tElPaper 在线考试
+     * @return 结果
+     */
+    @Override
+    public int insertTElPaper(TElPaper tElPaper)
+    {
+        return tElPaperMapper.insertTElPaper(tElPaper);
+    }
+
+    /**
+     * 修改在线考试
+     *
+     * @param tElPaper 在线考试
+     * @return 结果
+     */
+    @Override
+    public int updateTElPaper(TElPaper tElPaper)
+    {
+        return tElPaperMapper.updateTElPaper(tElPaper);
+    }
+
+    /**
+     * 批量删除在线考试
+     *
+     * @param paperIds 需要删除的在线考试ID
+     * @return 结果
+     */
+    @Override
+    public int deleteTElPaperByIds(Long[] paperIds)
+    {
+        return tElPaperMapper.deleteTElPaperByIds(paperIds);
+    }
+
+    /**
+     * 删除在线考试信息
+     *
+     * @param paperId 在线考试ID
+     * @return 结果
+     */
+    @Override
+    public int deleteTElPaperById(Long paperId)
+    {
+        return tElPaperMapper.deleteTElPaperById(paperId);
+    }
+
+    @Override
+    @Transactional
+    public TElPaper createPaper(TElPaper tElPaper, Long userId) {
+        // 查找考试
+         TElExam exam = tElExamMapper.selectTElExamById(tElPaper.getExamId());
+
+        // 考试题目列表
+        List<TElPaperQu> paperQuList = new ArrayList<>();
+        TElExamRepo tElExamRepo = new TElExamRepo();
+        tElExamRepo.setExamId(tElPaper.getExamId());
+        List<TElExamRepo> examRepoList = tElExamRepoMapper.selectTElExamRepoList(tElExamRepo);
+        for (TElExamRepo item: examRepoList
+             ) {
+            // 单选题
+            if(item.getRadioCount() > 0){
+                item.setQuType(1);
+                List<TElQu> radioListAll = tElQuMapper.selectTElQuListByRepo(item);
+                Collections.shuffle(radioListAll);
+                List<TElQu> radioList = radioListAll.subList(0,Integer.parseInt(String.valueOf(item.getRadioCount())) );
+                for (TElQu qu: radioList
+                     ) {
+                    TElPaperQu paperQu = this.processPaperQu(item,qu);
+                    paperQuList.add(paperQu);
+                }
+            }
+            // 多选题
+            if(item.getMultiCount() > 0){
+                item.setQuType(2);
+                List<TElQu> multiListAll = tElQuMapper.selectTElQuListByRepo(item);
+                Collections.shuffle(multiListAll);
+                List<TElQu> multiList = multiListAll.subList(0,Integer.parseInt(String.valueOf(item.getRadioCount())) );
+                for (TElQu qu: multiList
+                ) {
+                    TElPaperQu paperQu = this.processPaperQu(item,qu);
+                    paperQuList.add(paperQu);
+                }
+            }
+            // 判断题
+            if(item.getJudgeCount() > 0){
+                item.setQuType(3);
+                List<TElQu> judgeListAll = tElQuMapper.selectTElQuListByRepo(item);
+                Collections.shuffle(judgeListAll);
+                List<TElQu> judgeLis = judgeListAll.subList(0,Integer.parseInt(String.valueOf(item.getRadioCount())) );
+                for (TElQu qu: judgeLis
+                ) {
+                    TElPaperQu paperQu = this.processPaperQu(item,qu);
+                    paperQuList.add(paperQu);
+                }
+            }
+        }
+
+        //保存试卷基本信息
+        TElPaper paper = new TElPaper();
+        paper.setExamId(exam.getExamId());
+        paper.setTitle(exam.getTitle());
+        paper.setTotalScore(exam.getTotalScore());
+        paper.setTotalTime(exam.getTotalTime());
+        paper.setUserScore(0l);
+        paper.setUserId(userId);
+        paper.setCreateTime(new Date());
+        paper.setUpdateTime(new Date());
+        paper.setQualifyScore(exam.getQualifyScore());
+        paper.setState(0l);
+        paper.setHasSaq(0l);
+
+        // 截止时间
+        Calendar cl = Calendar.getInstance();
+        cl.setTimeInMillis(System.currentTimeMillis());
+        cl.add(Calendar.MINUTE, exam.getTotalTime().intValue());
+        paper.setLimitTime(cl.getTime());
+        tElPaperMapper.insertTElPaper(paper);
+        // 保存试卷试题列表
+        this.savePaperQu(paper.getPaperId(), paperQuList);
+
+
+        String jobName = "break_exam_" + tElPaper.getPaperId();
+//        jobService.addCronJob(BreakExamJob.class, jobName, this.dateToCron(tElPaper.getLimitTime()),String.valueOf(tElPaper.getPaperId()));
+
+        return paper;
+    }
+
+    /**
+     * 保存试卷试题列表
+     * @param paperId
+     * @param quList
+     */
+    private void savePaperQu(Long paperId, List<TElPaperQu> quList){
+        List<TElPaperQu> batchQuList = new ArrayList<>();
+        List<TElPaperQuAnswer> batchAnswerList = new ArrayList<>();
+        long sort = 0;
+        TElQuAnswer qury = new TElQuAnswer();
+        for (TElPaperQu item : quList) {
+            item.setPaperId(paperId);
+            item.setSort(sort);
+            qury.setQuId(item.getQuId());
+            //回答列表
+            List<TElQuAnswer> answerList =tElQuAnswerMapper.selectTElQuAnswerList(qury);
+            Collections.shuffle(answerList);
+            if (!CollectionUtils.isEmpty(answerList)) {
+
+                long ii = 0;
+                for (TElQuAnswer answer : answerList) {
+                    TElPaperQuAnswer paperQuAnswer = new TElPaperQuAnswer();
+                    paperQuAnswer.setPaperId(paperId);
+                    paperQuAnswer.setQuId(answer.getQuId());
+                    paperQuAnswer.setAnswerId(answer.getAnswerId());
+                    paperQuAnswer.setChecked(0l);
+                    paperQuAnswer.setSort(ii);
+                    paperQuAnswer.setAbc(ABC.get((int)ii));
+                    paperQuAnswer.setIsRight(answer.getIsRight());
+                    ii++;
+                    batchAnswerList.add(paperQuAnswer);
+                }
+            }
+            batchQuList.add(item);
+            sort++;
+        }
+        //添加问题
+        for (TElPaperQu q:batchQuList
+             ) {
+            tElPaperQuMapper.insertTElPaperQu(q);
+        }
+
+        //批量添加问题答案
+        for (TElPaperQuAnswer answer:batchAnswerList
+             ) {
+            tElPaperQuAnswerMapper.insertTElPaperQuAnswer(answer);
+        }
+    }
+    /**
+     * 填充试题题目信息
+     * @param repo
+     * @param qu
+     * @return
+     */
+    private TElPaperQu processPaperQu(TElExamRepo repo, TElQu qu) {
+
+        //保存试题信息
+        TElPaperQu paperQu = new TElPaperQu();
+        paperQu.setQuId(qu.getQuId());
+        paperQu.setAnswered(0l);
+        paperQu.setIsRight(0l);
+        paperQu.setQuType(qu.getQuType());
+
+        if ("1".equals(qu.getQuType())) {
+            paperQu.setScore(repo.getRadioScore());
+            paperQu.setActualScore(repo.getRadioScore());
+        }
+
+        if ("2".equals(qu.getQuType())) {
+            paperQu.setScore(repo.getMultiScore());
+            paperQu.setActualScore(repo.getMultiScore());
+        }
+
+        if ("3".equals(qu.getQuType())) {
+            paperQu.setScore(repo.getJudgeScore());
+            paperQu.setActualScore(repo.getJudgeScore());
+        }
+
+        return paperQu;
+    }
+
+    /**
+     * 准确的时间点到表达式
+     * @param date
+     * @return
+     */
+    public static String dateToCron(final Date date){
+        SimpleDateFormat fmt = new SimpleDateFormat("ss mm HH dd MM ? yyyy");
+        String formatTimeStr = "";
+        if (date != null) {
+            formatTimeStr = fmt.format(date);
+        }
+        return formatTimeStr;
+    }
+}

+ 93 - 0
master/src/main/java/com/ruoyi/project/training/elearn/service/impl/TElQuAnswerServiceImpl.java

@@ -0,0 +1,93 @@
+package com.ruoyi.project.training.elearn.service.impl;
+
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.ruoyi.project.training.elearn.mapper.TElQuAnswerMapper;
+import com.ruoyi.project.training.elearn.domain.TElQuAnswer;
+import com.ruoyi.project.training.elearn.service.ITElQuAnswerService;
+
+/**
+ * 试题选项答案Service业务层处理
+ *
+ * @author ssy
+ * @date 2024-05-28
+ */
+@Service
+public class TElQuAnswerServiceImpl implements ITElQuAnswerService
+{
+    @Autowired
+    private TElQuAnswerMapper tElQuAnswerMapper;
+
+    /**
+     * 查询试题选项答案
+     *
+     * @param answerId 试题选项答案ID
+     * @return 试题选项答案
+     */
+    @Override
+    public TElQuAnswer selectTElQuAnswerById(Long answerId)
+    {
+        return tElQuAnswerMapper.selectTElQuAnswerById(answerId);
+    }
+
+    /**
+     * 查询试题选项答案列表
+     *
+     * @param tElQuAnswer 试题选项答案
+     * @return 试题选项答案
+     */
+    @Override
+    public List<TElQuAnswer> selectTElQuAnswerList(TElQuAnswer tElQuAnswer)
+    {
+        return tElQuAnswerMapper.selectTElQuAnswerList(tElQuAnswer);
+    }
+
+    /**
+     * 新增试题选项答案
+     *
+     * @param tElQuAnswer 试题选项答案
+     * @return 结果
+     */
+    @Override
+    public int insertTElQuAnswer(TElQuAnswer tElQuAnswer)
+    {
+        return tElQuAnswerMapper.insertTElQuAnswer(tElQuAnswer);
+    }
+
+    /**
+     * 修改试题选项答案
+     *
+     * @param tElQuAnswer 试题选项答案
+     * @return 结果
+     */
+    @Override
+    public int updateTElQuAnswer(TElQuAnswer tElQuAnswer)
+    {
+        return tElQuAnswerMapper.updateTElQuAnswer(tElQuAnswer);
+    }
+
+    /**
+     * 批量删除试题选项答案
+     *
+     * @param answerIds 需要删除的试题选项答案ID
+     * @return 结果
+     */
+    @Override
+    public int deleteTElQuAnswerByIds(Long[] answerIds)
+    {
+        return tElQuAnswerMapper.deleteTElQuAnswerByIds(answerIds);
+    }
+
+    /**
+     * 删除试题选项答案信息
+     *
+     * @param answerId 试题选项答案ID
+     * @return 结果
+     */
+    @Override
+    public int deleteTElQuAnswerById(Long answerId)
+    {
+        return tElQuAnswerMapper.deleteTElQuAnswerById(answerId);
+    }
+}

+ 251 - 0
master/src/main/java/com/ruoyi/project/training/elearn/service/impl/TElQuServiceImpl.java

@@ -0,0 +1,251 @@
+package com.ruoyi.project.training.elearn.service.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.ruoyi.common.exception.BaseException;
+import com.ruoyi.project.training.elearn.domain.TElQuAnswer;
+import com.ruoyi.project.training.elearn.domain.TElQuRepo;
+import com.ruoyi.project.training.elearn.mapper.TElQuAnswerMapper;
+import com.ruoyi.project.training.elearn.mapper.TElQuRepoMapper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.ruoyi.project.training.elearn.mapper.TElQuMapper;
+import com.ruoyi.project.training.elearn.domain.TElQu;
+import com.ruoyi.project.training.elearn.service.ITElQuService;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+import org.springframework.util.StringUtils;
+
+import javax.annotation.Resource;
+
+/**
+ * 试题Service业务层处理
+ *
+ * @author ssy
+ * @date 2024-05-28
+ */
+@Service
+public class TElQuServiceImpl implements ITElQuService
+{
+    @Resource
+    private TElQuMapper tElQuMapper;
+    @Resource
+    private TElQuAnswerMapper tElQuAnswerMapper;
+    @Resource
+    private TElQuRepoMapper tElQuRepoMapper;
+    /**
+     * 查询试题
+     *
+     * @param quId 试题ID
+     * @return 试题
+     */
+    @Override
+    public TElQu selectTElQuById(Long quId)
+    {
+        TElQu tElQu = tElQuMapper.selectTElQuById(quId);
+
+        //答案
+        TElQuAnswer queyAs = new TElQuAnswer();
+        queyAs.setQuId(tElQu.getQuId());
+        List<TElQuAnswer> asList = tElQuAnswerMapper.selectTElQuAnswerList(queyAs);
+        tElQu.setAnswerList(asList);
+
+        //题库
+        TElQuRepo queyRepo = new TElQuRepo();
+        queyRepo.setQuId(tElQu.getQuId());
+        List<TElQuRepo> repoList = tElQuRepoMapper.selectTElQuRepoList(queyRepo);
+        List<String> ids = new ArrayList<>();
+        for (TElQuRepo t: repoList
+        ) {
+            ids.add(String.valueOf(t.getRepoId()));
+        }
+        tElQu.setRepoIds(ids);
+
+        return tElQu;
+    }
+
+    /**
+     * 查询试题列表
+     *
+     * @param tElQu 试题
+     * @return 试题
+     */
+    @Override
+    public List<TElQu> selectTElQuList(TElQu tElQu)
+    {
+        return tElQuMapper.selectTElQuList(tElQu);
+    }
+
+    /**
+     * 新增试题
+     *
+     * @param tElQu 试题
+     * @return 结果
+     */
+    @Override
+    @Transactional
+    public int insertTElQu(TElQu tElQu)
+    {
+        checkData(tElQu,"");
+        //更新答案
+        tElQuMapper.insertTElQu(tElQu);
+        for (TElQuAnswer as: tElQu.getAnswerList()
+             ) {
+            as.setQuId(tElQu.getQuId());
+            tElQuAnswerMapper.insertTElQuAnswer(as);
+        }
+        //更新题库
+        for(String repoId: tElQu.getRepoIds()){
+            TElQuRepo ref = new TElQuRepo();
+            ref.setQuId(tElQu.getQuId());
+            ref.setRepoId(Long.parseLong(repoId));
+            ref.setQuType(tElQu.getQuType());
+            tElQuRepoMapper.insertTElQuRepo(ref);
+        }
+        return 1;
+    }
+
+    /**
+     * 修改试题
+     *
+     * @param tElQu 试题
+     * @return 结果
+     */
+    @Override
+    public int updateTElQu(TElQu tElQu)
+    {
+        checkData(tElQu,"");
+        tElQuMapper.updateTElQu(tElQu);
+        //更新答案
+        TElQuAnswer queyAs = new TElQuAnswer();
+        queyAs.setQuId(tElQu.getQuId());
+        List<TElQuAnswer> oldList = tElQuAnswerMapper.selectTElQuAnswerList(queyAs);
+
+        List<Long> ids = new ArrayList<>();
+        if (oldList.size() > 0) {
+            for (TElQuAnswer old: oldList
+                 ) {
+                ids.add(old.getAnswerId());
+            }
+        }
+
+        for (TElQuAnswer as: tElQu.getAnswerList()
+        ) {
+            //补全ID避免新增
+            if(ids.contains(as.getAnswerId())){
+                ids.remove(as.getAnswerId());
+            }
+            as.setQuId(tElQu.getQuId());
+            if (as.getAnswerId() == null) {
+                tElQuAnswerMapper.insertTElQuAnswer(as);
+            }else {
+                tElQuAnswerMapper.updateTElQuAnswer(as);
+            }
+
+        }
+        //删除答案
+        for (Long id : ids
+             ) {
+            tElQuAnswerMapper.deleteTElQuAnswerById(id);
+        }
+
+        //先删除题库
+        TElQuRepo queyRepo = new TElQuRepo();
+         queyRepo.setQuId(tElQu.getQuId());
+        List<TElQuRepo> repoList = tElQuRepoMapper.selectTElQuRepoList(queyRepo);
+        for (TElQuRepo t: repoList
+             ) {
+            tElQuRepoMapper.deleteTElQuRepoById(t.getId());
+        }
+
+        //更新题库
+        for(String repoId: tElQu.getRepoIds()){
+            TElQuRepo ref = new TElQuRepo();
+            ref.setQuId(tElQu.getQuId());
+            ref.setRepoId(Long.parseLong(repoId));
+            ref.setQuType(tElQu.getQuType());
+            tElQuRepoMapper.insertTElQuRepo(ref);
+        }
+
+        return 1;
+    }
+
+    /**
+     * 批量删除试题
+     *
+     * @param quIds 需要删除的试题ID
+     * @return 结果
+     */
+    @Override
+    public int deleteTElQuByIds(Long[] quIds)
+    {
+        return tElQuMapper.deleteTElQuByIds(quIds);
+    }
+
+    /**
+     * 删除试题信息
+     *
+     * @param quId 试题ID
+     * @return 结果
+     */
+    @Override
+    public int deleteTElQuById(Long quId)
+    {
+        return tElQuMapper.deleteTElQuById(quId);
+    }
+    /**
+     * 校验题目信息
+     *
+     * @param qu
+     * @param no
+     * @throws Exception
+     */
+    public void checkData(TElQu qu, String no) {
+
+
+        if (StringUtils.isEmpty(qu.getContent())) {
+            throw new BaseException("1", no + "题目内容不能为空!");
+        }
+
+
+        if (CollectionUtils.isEmpty(qu.getRepoIds())) {
+            throw new BaseException("1", no + "至少要选择一个题库!");
+        }
+
+        List<TElQuAnswer> answers = qu.getAnswerList();
+
+
+        if (CollectionUtils.isEmpty(answers)) {
+            throw new BaseException("1", no + "客观题至少要包含一个备选答案!");
+        }
+
+
+        int trueCount = 0;
+        for (TElQuAnswer a : answers) {
+
+            if (a.getIsRight() == null) {
+                throw new BaseException("1", no + "必须定义选项是否正确项!");
+            }
+
+            if (StringUtils.isEmpty(a.getContent())) {
+                throw new BaseException("1", no + "选项内容不为空!");
+            }
+
+            if (a.getIsRight() == 1) {
+                trueCount += 1;
+            }
+        }
+
+        if (trueCount == 0) {
+            throw new BaseException("1", no + "至少要包含一个正确项!");
+        }
+
+
+        //单选题
+        if (qu.getQuType().equals("1") && trueCount > 1) {
+            throw new BaseException("1", no + "单选题不能包含多个正确项!");
+        }
+
+    }
+}

+ 93 - 0
master/src/main/java/com/ruoyi/project/training/elearn/service/impl/TElRepoServiceImpl.java

@@ -0,0 +1,93 @@
+package com.ruoyi.project.training.elearn.service.impl;
+
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.ruoyi.project.training.elearn.mapper.TElRepoMapper;
+import com.ruoyi.project.training.elearn.domain.TElRepo;
+import com.ruoyi.project.training.elearn.service.ITElRepoService;
+
+/**
+ * 题库Service业务层处理
+ *
+ * @author ssy
+ * @date 2024-05-27
+ */
+@Service
+public class TElRepoServiceImpl implements ITElRepoService
+{
+    @Autowired
+    private TElRepoMapper tElRepoMapper;
+
+    /**
+     * 查询题库
+     *
+     * @param repoId 题库ID
+     * @return 题库
+     */
+    @Override
+    public TElRepo selectTElRepoById(Long repoId)
+    {
+        return tElRepoMapper.selectTElRepoById(repoId);
+    }
+
+    /**
+     * 查询题库列表
+     *
+     * @param tElRepo 题库
+     * @return 题库
+     */
+    @Override
+    public List<TElRepo> selectTElRepoList(TElRepo tElRepo)
+    {
+        return tElRepoMapper.selectTElRepoList(tElRepo);
+    }
+
+    /**
+     * 新增题库
+     *
+     * @param tElRepo 题库
+     * @return 结果
+     */
+    @Override
+    public int insertTElRepo(TElRepo tElRepo)
+    {
+        return tElRepoMapper.insertTElRepo(tElRepo);
+    }
+
+    /**
+     * 修改题库
+     *
+     * @param tElRepo 题库
+     * @return 结果
+     */
+    @Override
+    public int updateTElRepo(TElRepo tElRepo)
+    {
+        return tElRepoMapper.updateTElRepo(tElRepo);
+    }
+
+    /**
+     * 批量删除题库
+     *
+     * @param repoIds 需要删除的题库ID
+     * @return 结果
+     */
+    @Override
+    public int deleteTElRepoByIds(Long[] repoIds)
+    {
+        return tElRepoMapper.deleteTElRepoByIds(repoIds);
+    }
+
+    /**
+     * 删除题库信息
+     *
+     * @param repoId 题库ID
+     * @return 结果
+     */
+    @Override
+    public int deleteTElRepoById(Long repoId)
+    {
+        return tElRepoMapper.deleteTElRepoById(repoId);
+    }
+}

+ 1 - 1
master/src/main/resources/application.yml

@@ -193,7 +193,7 @@ gen:
   # 作者
   author: ssy
   # 默认生成包路径 system 需改成自己的模块名称 如 system monitor tool
-  packageName: com.ruoyi.project.plant # 自动去除表前缀,默认是true
+  packageName: com.ruoyi.project.training.elearn # 自动去除表前缀,默认是true
   autoRemovePre: false
   # 表前缀(生成类名不会包含表前缀,多个用逗号分隔)
   tablePrefix: sys_

+ 1 - 0
master/src/main/resources/mybatis/plant/TMtActionlistMapper.xml

@@ -46,6 +46,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         </where>
         <!-- 数据范围过滤 -->
         ${params.dataScope}
+        order by responsible
     </select>
 
     <select id="selectList" parameterType="TMtActionlist" resultMap="TMtActionlistResult">

+ 1 - 0
master/src/main/resources/mybatis/plant/TMtEhsopenitemMapper.xml

@@ -43,6 +43,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         </where>
         <!-- 数据范围过滤 -->
         ${params.dataScope}
+        order by d.createdate desc
     </select>
 
     <select id="selectTMtEhsopenitemById" parameterType="Long" resultMap="TMtEhsopenitemResult">

+ 1 - 0
master/src/main/resources/mybatis/plant/TMtInterlockMapper.xml

@@ -36,6 +36,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         </where>
         <!-- 数据范围过滤 -->
         ${params.dataScope}
+        order by d.createdate desc
     </select>
 
     <select id="selectTMtInterlockById" parameterType="Long" resultMap="TMtInterlockResult">

+ 1 - 0
master/src/main/resources/mybatis/plant/TMtKeymaintenanceMapper.xml

@@ -45,6 +45,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         </where>
         <!-- 数据范围过滤 -->
         ${params.dataScope}
+        order by d.responsible
     </select>
 
     <select id="selectTMtKeymaintenanceById" parameterType="Long" resultMap="TMtKeymaintenanceResult">

+ 1 - 0
master/src/main/resources/mybatis/plant/TMtMessageattentionMapper.xml

@@ -45,6 +45,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         </where>
         <!-- 数据范围过滤 -->
         ${params.dataScope}
+        order by d.responsible
     </select>
 
     <select id="selectTMtMessageattentionById" parameterType="Long" resultMap="TMtMessageattentionResult">

+ 1 - 0
master/src/main/resources/mybatis/plant/TMtOpextrackMapper.xml

@@ -42,6 +42,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         </where>
         <!-- 数据范围过滤 -->
         ${params.dataScope}
+        order by d.createdate desc
     </select>
 
     <select id="selectTMtOpextrackById" parameterType="Long" resultMap="TMtOpextrackResult">

+ 1 - 0
master/src/main/resources/mybatis/plant/TMtRiskreminderMapper.xml

@@ -40,6 +40,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         </where>
         <!-- 数据范围过滤 -->
         ${params.dataScope}
+        order by d.createdate desc
     </select>
 
     <select id="selectTMtRiskreminderById" parameterType="Long" resultMap="TMtRiskreminderResult">

+ 146 - 0
master/src/main/resources/mybatis/training/bccnew/TTsFirstplanTmplMapper.xml

@@ -0,0 +1,146 @@
+<?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.ruoyi.project.training.bccnew.mapper.TTsFirstplanTmplMapper">
+
+    <resultMap type="TTsFirstplanTmpl" id="TTsFirstplanTmplResult">
+        <result property="id"    column="id"    />
+        <result property="newId"    column="new_id"    />
+        <result property="courseCode"    column="course_code"    />
+        <result property="topic"    column="topic"    />
+        <result property="content"    column="content"    />
+        <result property="courseDay"    column="course_day"    />
+        <result property="courseHour"    column="course_hour"    />
+        <result property="courseType"    column="course_type"    />
+        <result property="trainer"    column="trainer"    />
+        <result property="courseDate"    column="course_date"    />
+        <result property="assess"    column="assess"    />
+        <result property="delFlag"    column="del_flag"    />
+        <result property="createrCode"    column="creater_code"    />
+        <result property="createdate"    column="createdate"    />
+        <result property="updaterCode"    column="updater_code"    />
+        <result property="updatedate"    column="updatedate"    />
+        <result property="deptId"    column="dept_id"    />
+        <result property="remarks"    column="remarks"    />
+        <result property="deptName" column="dept_name" />
+    </resultMap>
+
+    <sql id="selectTTsFirstplanTmplVo">
+        select d.id, d.new_id, d.course_code, d.topic, d.content, d.course_day, d.course_hour, d.course_type, d.trainer, d.course_date, d.assess, d.del_flag, d.creater_code, d.createdate, d.updater_code, d.updatedate, d.dept_id, d.remarks ,s.dept_name from t_ts_firstplan_tmpl d
+      left join sys_dept s on s.dept_id = d.dept_id
+    </sql>
+
+    <select id="selectTTsFirstplanTmplList" parameterType="TTsFirstplanTmpl" resultMap="TTsFirstplanTmplResult">
+        <include refid="selectTTsFirstplanTmplVo"/>
+        <where>
+            <if test="newId != null "> and new_id = #{newId}</if>
+            <if test="courseCode != null  and courseCode != ''"> and course_code = #{courseCode}</if>
+            <if test="topic != null  and topic != ''"> and topic = #{topic}</if>
+            <if test="content != null  and content != ''"> and content = #{content}</if>
+            <if test="courseDay != null "> and course_day = #{courseDay}</if>
+            <if test="courseHour != null "> and course_hour = #{courseHour}</if>
+            <if test="courseType != null  and courseType != ''"> and course_type = #{courseType}</if>
+            <if test="trainer != null  and trainer != ''"> and trainer = #{trainer}</if>
+            <if test="courseDate != null "> and course_date = #{courseDate}</if>
+            <if test="assess != null  and assess != ''"> and assess = #{assess}</if>
+            <if test="createrCode != null  and createrCode != ''"> and creater_code = #{createrCode}</if>
+            <if test="createdate != null "> and createdate = #{createdate}</if>
+            <if test="updaterCode != null  and updaterCode != ''"> and updater_code = #{updaterCode}</if>
+            <if test="updatedate != null "> and updatedate = #{updatedate}</if>
+            <if test="deptId != null "> and dept_id = #{deptId}</if>
+            <if test="remarks != null  and remarks != ''"> and remarks = #{remarks}</if>
+            and d.del_flag = 0
+        </where>
+        <!-- 数据范围过滤 -->
+        ${params.dataScope}
+    </select>
+
+    <select id="selectTTsFirstplanTmplById" parameterType="Long" resultMap="TTsFirstplanTmplResult">
+        <include refid="selectTTsFirstplanTmplVo"/>
+        where id = #{id}
+    </select>
+
+    <insert id="insertTTsFirstplanTmpl" parameterType="TTsFirstplanTmpl">
+        <selectKey keyProperty="id" resultType="long" order="BEFORE">
+            SELECT seq_t_ts_firstplan_tmpl.NEXTVAL as id FROM DUAL
+        </selectKey>
+        insert into t_ts_firstplan_tmpl
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="id != null">id,</if>
+            <if test="newId != null">new_id,</if>
+            <if test="courseCode != null">course_code,</if>
+            <if test="topic != null">topic,</if>
+            <if test="content != null">content,</if>
+            <if test="courseDay != null">course_day,</if>
+            <if test="courseHour != null">course_hour,</if>
+            <if test="courseType != null">course_type,</if>
+            <if test="trainer != null">trainer,</if>
+            <if test="courseDate != null">course_date,</if>
+            <if test="assess != null">assess,</if>
+            <if test="delFlag != null">del_flag,</if>
+            <if test="createrCode != null">creater_code,</if>
+            <if test="createdate != null">createdate,</if>
+            <if test="updaterCode != null">updater_code,</if>
+            <if test="updatedate != null">updatedate,</if>
+            <if test="deptId != null">dept_id,</if>
+            <if test="remarks != null">remarks,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="id != null">#{id},</if>
+            <if test="newId != null">#{newId},</if>
+            <if test="courseCode != null">#{courseCode},</if>
+            <if test="topic != null">#{topic},</if>
+            <if test="content != null">#{content},</if>
+            <if test="courseDay != null">#{courseDay},</if>
+            <if test="courseHour != null">#{courseHour},</if>
+            <if test="courseType != null">#{courseType},</if>
+            <if test="trainer != null">#{trainer},</if>
+            <if test="courseDate != null">#{courseDate},</if>
+            <if test="assess != null">#{assess},</if>
+            <if test="delFlag != null">#{delFlag},</if>
+            <if test="createrCode != null">#{createrCode},</if>
+            <if test="createdate != null">#{createdate},</if>
+            <if test="updaterCode != null">#{updaterCode},</if>
+            <if test="updatedate != null">#{updatedate},</if>
+            <if test="deptId != null">#{deptId},</if>
+            <if test="remarks != null">#{remarks},</if>
+         </trim>
+    </insert>
+
+    <update id="updateTTsFirstplanTmpl" parameterType="TTsFirstplanTmpl">
+        update t_ts_firstplan_tmpl
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="newId != null">new_id = #{newId},</if>
+            <if test="courseCode != null">course_code = #{courseCode},</if>
+            <if test="topic != null">topic = #{topic},</if>
+            <if test="content != null">content = #{content},</if>
+            <if test="courseDay != null">course_day = #{courseDay},</if>
+            <if test="courseHour != null">course_hour = #{courseHour},</if>
+            <if test="courseType != null">course_type = #{courseType},</if>
+            <if test="trainer != null">trainer = #{trainer},</if>
+            <if test="courseDate != null">course_date = #{courseDate},</if>
+            <if test="assess != null">assess = #{assess},</if>
+            <if test="delFlag != null">del_flag = #{delFlag},</if>
+            <if test="createrCode != null">creater_code = #{createrCode},</if>
+            <if test="createdate != null">createdate = #{createdate},</if>
+            <if test="updaterCode != null">updater_code = #{updaterCode},</if>
+            <if test="updatedate != null">updatedate = #{updatedate},</if>
+            <if test="deptId != null">dept_id = #{deptId},</if>
+            <if test="remarks != null">remarks = #{remarks},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <update id="deleteTTsFirstplanTmplById" parameterType="Long">
+        update t_ts_firstplan_tmpl set del_flag = 2 where id = #{id}
+    </update>
+
+    <update id="deleteTTsFirstplanTmplByIds" parameterType="String">
+        update t_ts_firstplan_tmpl set del_flag = 2 where id in
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </update>
+
+</mapper>

+ 136 - 0
master/src/main/resources/mybatis/training/bccnew/TTsNewMapper.xml

@@ -0,0 +1,136 @@
+<?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.ruoyi.project.training.bccnew.mapper.TTsNewMapper">
+
+    <resultMap type="TTsNew" id="TTsNewResult">
+        <result property="newId"    column="new_id"    />
+        <result property="staffId"    column="staff_id"    />
+        <result property="name"    column="name"    />
+        <result property="delFlag"    column="del_flag"    />
+        <result property="createrCode"    column="creater_code"    />
+        <result property="createdate"    column="createdate"    />
+        <result property="updaterCode"    column="updater_code"    />
+        <result property="updatedate"    column="updatedate"    />
+        <result property="deptId"    column="dept_id"    />
+        <result property="planStatus"    column="plan_status"    />
+        <result property="planYear"    column="plan_year"    />
+        <result property="startdate"    column="startdate"    />
+        <result property="enddate"    column="enddate"    />
+        <result property="mentorStaffId"    column="mentor_staff_id"    />
+        <result property="planType"    column="plan_type"    />
+        <result property="remarks"    column="remarks"    />
+        <result property="deptName" column="dept_name" />
+    </resultMap>
+
+    <sql id="selectTTsNewVo">
+        select d.new_id, d.staff_id, d.name, d.del_flag, d.creater_code, d.createdate, d.updater_code, d.updatedate, d.dept_id, d.plan_status, d.plan_year, d.startdate, d.enddate, d.mentor_staff_id, d.plan_type, d.remarks ,s.dept_name from t_ts_new d
+      left join sys_dept s on s.dept_id = d.dept_id
+    </sql>
+
+    <select id="selectTTsNewList" parameterType="TTsNew" resultMap="TTsNewResult">
+        <include refid="selectTTsNewVo"/>
+        <where>
+            <if test="staffId != null  and staffId != ''"> and staff_id = #{staffId}</if>
+            <if test="name != null  and name != ''"> and name like concat(concat('%', #{name}), '%')</if>
+            <if test="createrCode != null  and createrCode != ''"> and creater_code = #{createrCode}</if>
+            <if test="createdate != null "> and createdate = #{createdate}</if>
+            <if test="updaterCode != null  and updaterCode != ''"> and updater_code = #{updaterCode}</if>
+            <if test="updatedate != null "> and updatedate = #{updatedate}</if>
+            <if test="deptId != null "> and dept_id = #{deptId}</if>
+            <if test="planStatus != null "> and plan_status = #{planStatus}</if>
+            <if test="planYear != null "> and plan_year = #{planYear}</if>
+            <if test="startdate != null "> and startdate = #{startdate}</if>
+            <if test="enddate != null "> and enddate = #{enddate}</if>
+            <if test="mentorStaffId != null  and mentorStaffId != ''"> and mentor_staff_id = #{mentorStaffId}</if>
+            <if test="planType != null "> and plan_type = #{planType}</if>
+            <if test="remarks != null  and remarks != ''"> and remarks = #{remarks}</if>
+            and d.del_flag = 0
+        </where>
+        <!-- 数据范围过滤 -->
+        ${params.dataScope}
+    </select>
+
+    <select id="selectTTsNewById" parameterType="Long" resultMap="TTsNewResult">
+        <include refid="selectTTsNewVo"/>
+        where new_id = #{newId}
+    </select>
+
+    <insert id="insertTTsNew" parameterType="TTsNew">
+        <selectKey keyProperty="newId" resultType="long" order="BEFORE">
+            SELECT seq_t_ts_new.NEXTVAL as newId FROM DUAL
+        </selectKey>
+        insert into t_ts_new
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="newId != null">new_id,</if>
+            <if test="staffId != null">staff_id,</if>
+            <if test="name != null">name,</if>
+            <if test="delFlag != null">del_flag,</if>
+            <if test="createrCode != null">creater_code,</if>
+            <if test="createdate != null">createdate,</if>
+            <if test="updaterCode != null">updater_code,</if>
+            <if test="updatedate != null">updatedate,</if>
+            <if test="deptId != null">dept_id,</if>
+            <if test="planStatus != null">plan_status,</if>
+            <if test="planYear != null">plan_year,</if>
+            <if test="startdate != null">startdate,</if>
+            <if test="enddate != null">enddate,</if>
+            <if test="mentorStaffId != null">mentor_staff_id,</if>
+            <if test="planType != null">plan_type,</if>
+            <if test="remarks != null">remarks,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="newId != null">#{newId},</if>
+            <if test="staffId != null">#{staffId},</if>
+            <if test="name != null">#{name},</if>
+            <if test="delFlag != null">#{delFlag},</if>
+            <if test="createrCode != null">#{createrCode},</if>
+            <if test="createdate != null">#{createdate},</if>
+            <if test="updaterCode != null">#{updaterCode},</if>
+            <if test="updatedate != null">#{updatedate},</if>
+            <if test="deptId != null">#{deptId},</if>
+            <if test="planStatus != null">#{planStatus},</if>
+            <if test="planYear != null">#{planYear},</if>
+            <if test="startdate != null">#{startdate},</if>
+            <if test="enddate != null">#{enddate},</if>
+            <if test="mentorStaffId != null">#{mentorStaffId},</if>
+            <if test="planType != null">#{planType},</if>
+            <if test="remarks != null">#{remarks},</if>
+         </trim>
+    </insert>
+
+    <update id="updateTTsNew" parameterType="TTsNew">
+        update t_ts_new
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="staffId != null">staff_id = #{staffId},</if>
+            <if test="name != null">name = #{name},</if>
+            <if test="delFlag != null">del_flag = #{delFlag},</if>
+            <if test="createrCode != null">creater_code = #{createrCode},</if>
+            <if test="createdate != null">createdate = #{createdate},</if>
+            <if test="updaterCode != null">updater_code = #{updaterCode},</if>
+            <if test="updatedate != null">updatedate = #{updatedate},</if>
+            <if test="deptId != null">dept_id = #{deptId},</if>
+            <if test="planStatus != null">plan_status = #{planStatus},</if>
+            <if test="planYear != null">plan_year = #{planYear},</if>
+            <if test="startdate != null">startdate = #{startdate},</if>
+            <if test="enddate != null">enddate = #{enddate},</if>
+            <if test="mentorStaffId != null">mentor_staff_id = #{mentorStaffId},</if>
+            <if test="planType != null">plan_type = #{planType},</if>
+            <if test="remarks != null">remarks = #{remarks},</if>
+        </trim>
+        where new_id = #{newId}
+    </update>
+
+    <update id="deleteTTsNewById" parameterType="Long">
+        update t_ts_new set del_flag = 2 where new_id = #{newId}
+    </update>
+
+    <update id="deleteTTsNewByIds" parameterType="String">
+        update t_ts_new set del_flag = 2 where new_id in
+        <foreach item="newId" collection="array" open="(" separator="," close=")">
+            #{newId}
+        </foreach>
+    </update>
+
+</mapper>

+ 146 - 0
master/src/main/resources/mybatis/training/elearn/TElExamMapper.xml

@@ -0,0 +1,146 @@
+<?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.ruoyi.project.training.elearn.mapper.TElExamMapper">
+
+    <resultMap type="TElExam" id="TElExamResult">
+        <result property="examId"    column="exam_id"    />
+        <result property="title"    column="title"    />
+        <result property="content"    column="content"    />
+        <result property="openType"    column="open_type"    />
+        <result property="state"    column="state"    />
+        <result property="timeLimit"    column="time_limit"    />
+        <result property="examStartTime"    column="exam_start_time"    />
+        <result property="examEndTime"    column="exam_end_time"    />
+        <result property="totalScore"    column="total_score"    />
+        <result property="totalTime"    column="total_time"    />
+        <result property="qualifyScore"    column="qualify_score"    />
+        <result property="delFlag"    column="del_flag"    />
+        <result property="createrCode"    column="creater_code"    />
+        <result property="createdate"    column="createdate"    />
+        <result property="updaterCode"    column="updater_code"    />
+        <result property="updatedate"    column="updatedate"    />
+        <result property="deptId"    column="dept_id"    />
+        <result property="remarks"    column="remarks"    />
+        <result property="deptName" column="dept_name" />
+    </resultMap>
+
+    <sql id="selectTElExamVo">
+        select d.exam_id, d.title, d.content, d.open_type, d.state, d.time_limit, d.exam_start_time, d.exam_end_time, d.total_score, d.total_time, d.qualify_score, d.del_flag, d.creater_code, d.createdate, d.updater_code, d.updatedate, d.dept_id, d.remarks ,s.dept_name from t_el_exam d
+      left join sys_dept s on s.dept_id = d.dept_id
+    </sql>
+
+    <select id="selectTElExamList" parameterType="TElExam" resultMap="TElExamResult">
+        <include refid="selectTElExamVo"/>
+        <where>
+            <if test="title != null  and title != ''"> and title = #{title}</if>
+            <if test="content != null  and content != ''"> and content = #{content}</if>
+            <if test="openType != null "> and open_type = #{openType}</if>
+            <if test="state != null "> and state = #{state}</if>
+            <if test="timeLimit != null "> and time_limit = #{timeLimit}</if>
+            <if test="examStartTime != null "> and exam_start_time = #{examStartTime}</if>
+            <if test="examEndTime != null "> and exam_end_time = #{examEndTime}</if>
+            <if test="totalScore != null "> and total_score = #{totalScore}</if>
+            <if test="totalTime != null "> and total_time = #{totalTime}</if>
+            <if test="qualifyScore != null "> and qualify_score = #{qualifyScore}</if>
+            <if test="createrCode != null  and createrCode != ''"> and creater_code = #{createrCode}</if>
+            <if test="createdate != null "> and createdate = #{createdate}</if>
+            <if test="updaterCode != null  and updaterCode != ''"> and updater_code = #{updaterCode}</if>
+            <if test="updatedate != null "> and updatedate = #{updatedate}</if>
+            <if test="deptId != null "> and dept_id = #{deptId}</if>
+            <if test="remarks != null  and remarks != ''"> and remarks = #{remarks}</if>
+            and d.del_flag = 0
+        </where>
+        <!-- 数据范围过滤 -->
+        ${params.dataScope}
+    </select>
+
+    <select id="selectTElExamById" parameterType="Long" resultMap="TElExamResult">
+        <include refid="selectTElExamVo"/>
+        where exam_id = #{examId}
+    </select>
+
+    <insert id="insertTElExam" parameterType="TElExam">
+        <selectKey keyProperty="examId" resultType="long" order="BEFORE">
+            SELECT seq_t_el_exam.NEXTVAL as examId FROM DUAL
+        </selectKey>
+        insert into t_el_exam
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="examId != null">exam_id,</if>
+            <if test="title != null">title,</if>
+            <if test="content != null">content,</if>
+            <if test="openType != null">open_type,</if>
+            <if test="state != null">state,</if>
+            <if test="timeLimit != null">time_limit,</if>
+            <if test="examStartTime != null">exam_start_time,</if>
+            <if test="examEndTime != null">exam_end_time,</if>
+            <if test="totalScore != null">total_score,</if>
+            <if test="totalTime != null">total_time,</if>
+            <if test="qualifyScore != null">qualify_score,</if>
+            <if test="delFlag != null">del_flag,</if>
+            <if test="createrCode != null">creater_code,</if>
+            <if test="createdate != null">createdate,</if>
+            <if test="updaterCode != null">updater_code,</if>
+            <if test="updatedate != null">updatedate,</if>
+            <if test="deptId != null">dept_id,</if>
+            <if test="remarks != null">remarks,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="examId != null">#{examId},</if>
+            <if test="title != null">#{title},</if>
+            <if test="content != null">#{content},</if>
+            <if test="openType != null">#{openType},</if>
+            <if test="state != null">#{state},</if>
+            <if test="timeLimit != null">#{timeLimit},</if>
+            <if test="examStartTime != null">#{examStartTime},</if>
+            <if test="examEndTime != null">#{examEndTime},</if>
+            <if test="totalScore != null">#{totalScore},</if>
+            <if test="totalTime != null">#{totalTime},</if>
+            <if test="qualifyScore != null">#{qualifyScore},</if>
+            <if test="delFlag != null">#{delFlag},</if>
+            <if test="createrCode != null">#{createrCode},</if>
+            <if test="createdate != null">#{createdate},</if>
+            <if test="updaterCode != null">#{updaterCode},</if>
+            <if test="updatedate != null">#{updatedate},</if>
+            <if test="deptId != null">#{deptId},</if>
+            <if test="remarks != null">#{remarks},</if>
+         </trim>
+    </insert>
+
+    <update id="updateTElExam" parameterType="TElExam">
+        update t_el_exam
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="title != null">title = #{title},</if>
+            <if test="content != null">content = #{content},</if>
+            <if test="openType != null">open_type = #{openType},</if>
+            <if test="state != null">state = #{state},</if>
+            <if test="timeLimit != null">time_limit = #{timeLimit},</if>
+            <if test="examStartTime != null">exam_start_time = #{examStartTime},</if>
+            <if test="examEndTime != null">exam_end_time = #{examEndTime},</if>
+            <if test="totalScore != null">total_score = #{totalScore},</if>
+            <if test="totalTime != null">total_time = #{totalTime},</if>
+            <if test="qualifyScore != null">qualify_score = #{qualifyScore},</if>
+            <if test="delFlag != null">del_flag = #{delFlag},</if>
+            <if test="createrCode != null">creater_code = #{createrCode},</if>
+            <if test="createdate != null">createdate = #{createdate},</if>
+            <if test="updaterCode != null">updater_code = #{updaterCode},</if>
+            <if test="updatedate != null">updatedate = #{updatedate},</if>
+            <if test="deptId != null">dept_id = #{deptId},</if>
+            <if test="remarks != null">remarks = #{remarks},</if>
+        </trim>
+        where exam_id = #{examId}
+    </update>
+
+    <update id="deleteTElExamById" parameterType="Long">
+        update t_el_exam set del_flag = 2 where exam_id = #{examId}
+    </update>
+
+    <update id="deleteTElExamByIds" parameterType="String">
+        update t_el_exam set del_flag = 2 where exam_id in
+        <foreach item="examId" collection="array" open="(" separator="," close=")">
+            #{examId}
+        </foreach>
+    </update>
+
+</mapper>

+ 117 - 0
master/src/main/resources/mybatis/training/elearn/TElExamRepoMapper.xml

@@ -0,0 +1,117 @@
+<?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.ruoyi.project.training.elearn.mapper.TElExamRepoMapper">
+
+    <resultMap type="TElExamRepo" id="TElExamRepoResult">
+        <result property="id"    column="id"    />
+        <result property="examId"    column="exam_id"    />
+        <result property="repoId"    column="repo_id"    />
+        <result property="radioCount"    column="radio_count"    />
+        <result property="radioScore"    column="radio_score"    />
+        <result property="multiCount"    column="multi_count"    />
+        <result property="multiScore"    column="multi_score"    />
+        <result property="judgeCount"    column="judge_count"    />
+        <result property="judgeScore"    column="judge_score"    />
+        <result property="saqCount"    column="saq_count"    />
+        <result property="saqScore"    column="saq_score"    />
+    </resultMap>
+
+    <sql id="selectTElExamRepoVo">
+        select d.id, d.exam_id, d.repo_id, d.radio_count, d.radio_score, d.multi_count, d.multi_score, d.judge_count, d.judge_score, d.saq_count, d.saq_score
+            ,(SELECT COUNT(0) FROM t_el_qu_repo WHERE repo_id=d.repo_id AND qu_type=1) AS totalRadio,
+               (SELECT COUNT(0) FROM t_el_qu_repo WHERE repo_id=d.repo_id AND qu_type=2) AS totalMulti,
+               (SELECT COUNT(0) FROM t_el_qu_repo WHERE repo_id=d.repo_id AND qu_type=3) AS totalJudge
+        from t_el_exam_repo d
+    </sql>
+
+    <select id="selectTElExamRepoList" parameterType="TElExamRepo" resultMap="TElExamRepoResult">
+        <include refid="selectTElExamRepoVo"/>
+        <where>
+            <if test="examId != null "> and exam_id = #{examId}</if>
+            <if test="repoId != null "> and repo_id = #{repoId}</if>
+            <if test="radioCount != null "> and radio_count = #{radioCount}</if>
+            <if test="radioScore != null "> and radio_score = #{radioScore}</if>
+            <if test="multiCount != null "> and multi_count = #{multiCount}</if>
+            <if test="multiScore != null "> and multi_score = #{multiScore}</if>
+            <if test="judgeCount != null "> and judge_count = #{judgeCount}</if>
+            <if test="judgeScore != null "> and judge_score = #{judgeScore}</if>
+            <if test="saqCount != null "> and saq_count = #{saqCount}</if>
+            <if test="saqScore != null "> and saq_score = #{saqScore}</if>
+        </where>
+        <!-- 数据范围过滤 -->
+    </select>
+
+    <select id="selectTElExamRepoById" parameterType="Long" resultMap="TElExamRepoResult">
+        <include refid="selectTElExamRepoVo"/>
+        where id = #{id}
+    </select>
+
+    <insert id="insertTElExamRepo" parameterType="TElExamRepo">
+        <selectKey keyProperty="id" resultType="long" order="BEFORE">
+            SELECT seq_t_el_exam_repo.NEXTVAL as id FROM DUAL
+        </selectKey>
+        insert into t_el_exam_repo
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="id != null">id,</if>
+            <if test="examId != null">exam_id,</if>
+            <if test="repoId != null">repo_id,</if>
+            <if test="radioCount != null">radio_count,</if>
+            <if test="radioScore != null">radio_score,</if>
+            <if test="multiCount != null">multi_count,</if>
+            <if test="multiScore != null">multi_score,</if>
+            <if test="judgeCount != null">judge_count,</if>
+            <if test="judgeScore != null">judge_score,</if>
+            <if test="saqCount != null">saq_count,</if>
+            <if test="saqScore != null">saq_score,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="id != null">#{id},</if>
+            <if test="examId != null">#{examId},</if>
+            <if test="repoId != null">#{repoId},</if>
+            <if test="radioCount != null">#{radioCount},</if>
+            <if test="radioScore != null">#{radioScore},</if>
+            <if test="multiCount != null">#{multiCount},</if>
+            <if test="multiScore != null">#{multiScore},</if>
+            <if test="judgeCount != null">#{judgeCount},</if>
+            <if test="judgeScore != null">#{judgeScore},</if>
+            <if test="saqCount != null">#{saqCount},</if>
+            <if test="saqScore != null">#{saqScore},</if>
+         </trim>
+    </insert>
+
+    <update id="updateTElExamRepo" parameterType="TElExamRepo">
+        update t_el_exam_repo
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="examId != null">exam_id = #{examId},</if>
+            <if test="repoId != null">repo_id = #{repoId},</if>
+            <if test="radioCount != null">radio_count = #{radioCount},</if>
+            <if test="radioScore != null">radio_score = #{radioScore},</if>
+            <if test="multiCount != null">multi_count = #{multiCount},</if>
+            <if test="multiScore != null">multi_score = #{multiScore},</if>
+            <if test="judgeCount != null">judge_count = #{judgeCount},</if>
+            <if test="judgeScore != null">judge_score = #{judgeScore},</if>
+            <if test="saqCount != null">saq_count = #{saqCount},</if>
+            <if test="saqScore != null">saq_score = #{saqScore},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteTElExamRepoById" parameterType="Long">
+        delete from t_el_exam_repo  where id = #{id}
+    </delete>
+
+
+    <delete id="deleteTElExamRepoByExamId" parameterType="Long">
+        delete from t_el_exam_repo  where exam_id = #{examId}
+    </delete>
+
+    <delete id="deleteTElExamRepoByIds" parameterType="String">
+        delete from t_el_exam_repo where id in
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+
+</mapper>

+ 166 - 0
master/src/main/resources/mybatis/training/elearn/TElPaperMapper.xml

@@ -0,0 +1,166 @@
+<?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.ruoyi.project.training.elearn.mapper.TElPaperMapper">
+
+    <resultMap type="TElPaper" id="TElPaperResult">
+        <result property="paperId"    column="paper_id"    />
+        <result property="userId"    column="user_id"    />
+        <result property="staffId"    column="staff_id"    />
+        <result property="examId"    column="exam_id"    />
+        <result property="title"    column="title"    />
+        <result property="totalTime"    column="total_time"    />
+        <result property="userTime"    column="user_time"    />
+        <result property="totalScore"    column="total_score"    />
+        <result property="qualifyScore"    column="qualify_score"    />
+        <result property="objScore"    column="obj_score"    />
+        <result property="subjScore"    column="subj_score"    />
+        <result property="userScore"    column="user_score"    />
+        <result property="hasSaq"    column="has_saq"    />
+        <result property="state"    column="state"    />
+        <result property="limitTime"    column="limit_time"    />
+        <result property="delFlag"    column="del_flag"    />
+        <result property="createrCode"    column="creater_code"    />
+        <result property="createdate"    column="createdate"    />
+        <result property="updaterCode"    column="updater_code"    />
+        <result property="updatedate"    column="updatedate"    />
+        <result property="deptId"    column="dept_id"    />
+        <result property="remarks"    column="remarks"    />
+        <result property="deptName" column="dept_name" />
+    </resultMap>
+
+    <sql id="selectTElPaperVo">
+        select d.paper_id, d.user_id, d.staff_id, d.exam_id, d.title, d.total_time, d.user_time, d.total_score, d.qualify_score, d.obj_score, d.subj_score, d.user_score, d.has_saq, d.state, d.limit_time, d.del_flag, d.creater_code, d.createdate, d.updater_code, d.updatedate, d.dept_id, d.remarks ,s.dept_name from t_el_paper d
+      left join sys_dept s on s.dept_id = d.dept_id
+    </sql>
+
+    <select id="selectTElPaperList" parameterType="TElPaper" resultMap="TElPaperResult">
+        <include refid="selectTElPaperVo"/>
+        <where>
+            <if test="userId != null "> and user_id = #{userId}</if>
+            <if test="staffId != null "> and staff_id = #{staffId}</if>
+            <if test="examId != null "> and exam_id = #{examId}</if>
+            <if test="title != null  and title != ''"> and title like concat(concat('%', #{title}), '%')</if>
+            <if test="totalTime != null "> and total_time = #{totalTime}</if>
+            <if test="userTime != null "> and user_time = #{userTime}</if>
+            <if test="totalScore != null "> and total_score = #{totalScore}</if>
+            <if test="qualifyScore != null "> and qualify_score = #{qualifyScore}</if>
+            <if test="objScore != null "> and obj_score = #{objScore}</if>
+            <if test="subjScore != null "> and subj_score = #{subjScore}</if>
+            <if test="userScore != null "> and user_score = #{userScore}</if>
+            <if test="hasSaq != null "> and has_saq = #{hasSaq}</if>
+            <if test="state != null "> and state = #{state}</if>
+            <if test="limitTime != null "> and limit_time = #{limitTime}</if>
+            <if test="createrCode != null  and createrCode != ''"> and creater_code = #{createrCode}</if>
+            <if test="createdate != null "> and createdate = #{createdate}</if>
+            <if test="updaterCode != null  and updaterCode != ''"> and updater_code = #{updaterCode}</if>
+            <if test="updatedate != null "> and updatedate = #{updatedate}</if>
+            <if test="deptId != null "> and dept_id = #{deptId}</if>
+            <if test="remarks != null  and remarks != ''"> and remarks = #{remarks}</if>
+            and d.del_flag = 0
+        </where>
+        <!-- 数据范围过滤 -->
+        ${params.dataScope}
+    </select>
+
+    <select id="selectTElPaperById" parameterType="Long" resultMap="TElPaperResult">
+        <include refid="selectTElPaperVo"/>
+        where paper_id = #{paperId}
+    </select>
+
+    <insert id="insertTElPaper" parameterType="TElPaper">
+        <selectKey keyProperty="paperId" resultType="long" order="BEFORE">
+            SELECT seq_t_el_paper.NEXTVAL as paperId FROM DUAL
+        </selectKey>
+        insert into t_el_paper
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="paperId != null">paper_id,</if>
+            <if test="userId != null">user_id,</if>
+            <if test="staffId != null">staff_id,</if>
+            <if test="examId != null">exam_id,</if>
+            <if test="title != null">title,</if>
+            <if test="totalTime != null">total_time,</if>
+            <if test="userTime != null">user_time,</if>
+            <if test="totalScore != null">total_score,</if>
+            <if test="qualifyScore != null">qualify_score,</if>
+            <if test="objScore != null">obj_score,</if>
+            <if test="subjScore != null">subj_score,</if>
+            <if test="userScore != null">user_score,</if>
+            <if test="hasSaq != null">has_saq,</if>
+            <if test="state != null">state,</if>
+            <if test="limitTime != null">limit_time,</if>
+            <if test="delFlag != null">del_flag,</if>
+            <if test="createrCode != null">creater_code,</if>
+            <if test="createdate != null">createdate,</if>
+            <if test="updaterCode != null">updater_code,</if>
+            <if test="updatedate != null">updatedate,</if>
+            <if test="deptId != null">dept_id,</if>
+            <if test="remarks != null">remarks,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="paperId != null">#{paperId},</if>
+            <if test="userId != null">#{userId},</if>
+            <if test="staffId != null">#{staffId},</if>
+            <if test="examId != null">#{examId},</if>
+            <if test="title != null">#{title},</if>
+            <if test="totalTime != null">#{totalTime},</if>
+            <if test="userTime != null">#{userTime},</if>
+            <if test="totalScore != null">#{totalScore},</if>
+            <if test="qualifyScore != null">#{qualifyScore},</if>
+            <if test="objScore != null">#{objScore},</if>
+            <if test="subjScore != null">#{subjScore},</if>
+            <if test="userScore != null">#{userScore},</if>
+            <if test="hasSaq != null">#{hasSaq},</if>
+            <if test="state != null">#{state},</if>
+            <if test="limitTime != null">#{limitTime},</if>
+            <if test="delFlag != null">#{delFlag},</if>
+            <if test="createrCode != null">#{createrCode},</if>
+            <if test="createdate != null">#{createdate},</if>
+            <if test="updaterCode != null">#{updaterCode},</if>
+            <if test="updatedate != null">#{updatedate},</if>
+            <if test="deptId != null">#{deptId},</if>
+            <if test="remarks != null">#{remarks},</if>
+         </trim>
+    </insert>
+
+    <update id="updateTElPaper" parameterType="TElPaper">
+        update t_el_paper
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="userId != null">user_id = #{userId},</if>
+            <if test="staffId != null">staff_id = #{staffId},</if>
+            <if test="examId != null">exam_id = #{examId},</if>
+            <if test="title != null">title = #{title},</if>
+            <if test="totalTime != null">total_time = #{totalTime},</if>
+            <if test="userTime != null">user_time = #{userTime},</if>
+            <if test="totalScore != null">total_score = #{totalScore},</if>
+            <if test="qualifyScore != null">qualify_score = #{qualifyScore},</if>
+            <if test="objScore != null">obj_score = #{objScore},</if>
+            <if test="subjScore != null">subj_score = #{subjScore},</if>
+            <if test="userScore != null">user_score = #{userScore},</if>
+            <if test="hasSaq != null">has_saq = #{hasSaq},</if>
+            <if test="state != null">state = #{state},</if>
+            <if test="limitTime != null">limit_time = #{limitTime},</if>
+            <if test="delFlag != null">del_flag = #{delFlag},</if>
+            <if test="createrCode != null">creater_code = #{createrCode},</if>
+            <if test="createdate != null">createdate = #{createdate},</if>
+            <if test="updaterCode != null">updater_code = #{updaterCode},</if>
+            <if test="updatedate != null">updatedate = #{updatedate},</if>
+            <if test="deptId != null">dept_id = #{deptId},</if>
+            <if test="remarks != null">remarks = #{remarks},</if>
+        </trim>
+        where paper_id = #{paperId}
+    </update>
+
+    <update id="deleteTElPaperById" parameterType="Long">
+        update t_el_paper set del_flag = 2 where paper_id = #{paperId}
+    </update>
+
+    <update id="deleteTElPaperByIds" parameterType="String">
+        update t_el_paper set del_flag = 2 where paper_id in
+        <foreach item="paperId" collection="array" open="(" separator="," close=")">
+            #{paperId}
+        </foreach>
+    </update>
+
+</mapper>

+ 95 - 0
master/src/main/resources/mybatis/training/elearn/TElPaperQuAnswerMapper.xml

@@ -0,0 +1,95 @@
+<?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.ruoyi.project.training.elearn.mapper.TElPaperQuAnswerMapper">
+
+    <resultMap type="TElPaperQuAnswer" id="TElPaperQuAnswerResult">
+        <result property="id"    column="id"    />
+        <result property="paperId"    column="paper_id"    />
+        <result property="quId"    column="qu_id"    />
+        <result property="answerId"    column="answer_id"    />
+        <result property="isRight"    column="is_right"    />
+        <result property="checked"    column="checked"    />
+        <result property="sort"    column="sort"    />
+        <result property="abc"    column="abc"    />
+    </resultMap>
+
+    <sql id="selectTElPaperQuAnswerVo">
+        select d.id, d.paper_id, d.qu_id, d.answer_id, d.is_right, d.checked, d.sort, d.abc  from t_el_paper_qu_answer d
+    </sql>
+
+    <select id="selectTElPaperQuAnswerList" parameterType="TElPaperQuAnswer" resultMap="TElPaperQuAnswerResult">
+        <include refid="selectTElPaperQuAnswerVo"/>
+        <where>
+            <if test="paperId != null "> and paper_id = #{paperId}</if>
+            <if test="quId != null "> and qu_id = #{quId}</if>
+            <if test="answerId != null "> and answer_id = #{answerId}</if>
+            <if test="isRight != null "> and is_right = #{isRight}</if>
+            <if test="checked != null "> and checked = #{checked}</if>
+            <if test="sort != null "> and sort = #{sort}</if>
+            <if test="abc != null  and abc != ''"> and abc = #{abc}</if>
+            and d.del_flag = 0
+        </where>
+        <!-- 数据范围过滤 -->
+        ${params.dataScope}
+    </select>
+
+    <select id="selectTElPaperQuAnswerById" parameterType="Long" resultMap="TElPaperQuAnswerResult">
+        <include refid="selectTElPaperQuAnswerVo"/>
+        where id = #{id}
+    </select>
+
+    <insert id="insertTElPaperQuAnswer" parameterType="TElPaperQuAnswer">
+        <selectKey keyProperty="id" resultType="long" order="BEFORE">
+            SELECT seq_t_el_paper_qu_answer.NEXTVAL as id FROM DUAL
+        </selectKey>
+        insert into t_el_paper_qu_answer
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="id != null">id,</if>
+            <if test="paperId != null">paper_id,</if>
+            <if test="quId != null">qu_id,</if>
+            <if test="answerId != null">answer_id,</if>
+            <if test="isRight != null">is_right,</if>
+            <if test="checked != null">checked,</if>
+            <if test="sort != null">sort,</if>
+            <if test="abc != null">abc,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="id != null">#{id},</if>
+            <if test="paperId != null">#{paperId},</if>
+            <if test="quId != null">#{quId},</if>
+            <if test="answerId != null">#{answerId},</if>
+            <if test="isRight != null">#{isRight},</if>
+            <if test="checked != null">#{checked},</if>
+            <if test="sort != null">#{sort},</if>
+            <if test="abc != null">#{abc},</if>
+         </trim>
+    </insert>
+
+    <update id="updateTElPaperQuAnswer" parameterType="TElPaperQuAnswer">
+        update t_el_paper_qu_answer
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="paperId != null">paper_id = #{paperId},</if>
+            <if test="quId != null">qu_id = #{quId},</if>
+            <if test="answerId != null">answer_id = #{answerId},</if>
+            <if test="isRight != null">is_right = #{isRight},</if>
+            <if test="checked != null">checked = #{checked},</if>
+            <if test="sort != null">sort = #{sort},</if>
+            <if test="abc != null">abc = #{abc},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <update id="deleteTElPaperQuAnswerById" parameterType="Long">
+        update t_el_paper_qu_answer set del_flag = 2 where id = #{id}
+    </update>
+
+    <update id="deleteTElPaperQuAnswerByIds" parameterType="String">
+        update t_el_paper_qu_answer set del_flag = 2 where id in
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </update>
+
+</mapper>

+ 105 - 0
master/src/main/resources/mybatis/training/elearn/TElPaperQuMapper.xml

@@ -0,0 +1,105 @@
+<?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.ruoyi.project.training.elearn.mapper.TElPaperQuMapper">
+
+    <resultMap type="TElPaperQu" id="TElPaperQuResult">
+        <result property="id"    column="id"    />
+        <result property="paperId"    column="paper_id"    />
+        <result property="quId"    column="qu_id"    />
+        <result property="quType"    column="qu_type"    />
+        <result property="answered"    column="answered"    />
+        <result property="answer"    column="answer"    />
+        <result property="sort"    column="sort"    />
+        <result property="score"    column="score"    />
+        <result property="actualScore"    column="actual_score"    />
+        <result property="isRight"    column="is_right"    />
+    </resultMap>
+
+    <sql id="selectTElPaperQuVo">
+        select d.id, d.paper_id, d.qu_id, d.qu_type, d.answered, d.answer, d.sort, d.score, d.actual_score, d.is_right from t_el_paper_qu d
+    </sql>
+
+    <select id="selectTElPaperQuList" parameterType="TElPaperQu" resultMap="TElPaperQuResult">
+        <include refid="selectTElPaperQuVo"/>
+        <where>
+            <if test="paperId != null "> and paper_id = #{paperId}</if>
+            <if test="quId != null "> and qu_id = #{quId}</if>
+            <if test="quType != null "> and qu_type = #{quType}</if>
+            <if test="answered != null "> and answered = #{answered}</if>
+            <if test="answer != null  and answer != ''"> and answer = #{answer}</if>
+            <if test="sort != null "> and sort = #{sort}</if>
+            <if test="score != null "> and score = #{score}</if>
+            <if test="actualScore != null "> and actual_score = #{actualScore}</if>
+            <if test="isRight != null "> and is_right = #{isRight}</if>
+            and d.del_flag = 0
+        </where>
+        <!-- 数据范围过滤 -->
+        ${params.dataScope}
+    </select>
+
+    <select id="selectTElPaperQuById" parameterType="Long" resultMap="TElPaperQuResult">
+        <include refid="selectTElPaperQuVo"/>
+        where id = #{id}
+    </select>
+
+    <insert id="insertTElPaperQu" parameterType="TElPaperQu">
+        <selectKey keyProperty="id" resultType="long" order="BEFORE">
+            SELECT seq_t_el_paper_qu.NEXTVAL as id FROM DUAL
+        </selectKey>
+        insert into t_el_paper_qu
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="id != null">id,</if>
+            <if test="paperId != null">paper_id,</if>
+            <if test="quId != null">qu_id,</if>
+            <if test="quType != null">qu_type,</if>
+            <if test="answered != null">answered,</if>
+            <if test="answer != null">answer,</if>
+            <if test="sort != null">sort,</if>
+            <if test="score != null">score,</if>
+            <if test="actualScore != null">actual_score,</if>
+            <if test="isRight != null">is_right,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="id != null">#{id},</if>
+            <if test="paperId != null">#{paperId},</if>
+            <if test="quId != null">#{quId},</if>
+            <if test="quType != null">#{quType},</if>
+            <if test="answered != null">#{answered},</if>
+            <if test="answer != null">#{answer},</if>
+            <if test="sort != null">#{sort},</if>
+            <if test="score != null">#{score},</if>
+            <if test="actualScore != null">#{actualScore},</if>
+            <if test="isRight != null">#{isRight},</if>
+         </trim>
+    </insert>
+
+    <update id="updateTElPaperQu" parameterType="TElPaperQu">
+        update t_el_paper_qu
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="paperId != null">paper_id = #{paperId},</if>
+            <if test="quId != null">qu_id = #{quId},</if>
+            <if test="quType != null">qu_type = #{quType},</if>
+            <if test="answered != null">answered = #{answered},</if>
+            <if test="answer != null">answer = #{answer},</if>
+            <if test="sort != null">sort = #{sort},</if>
+            <if test="score != null">score = #{score},</if>
+            <if test="actualScore != null">actual_score = #{actualScore},</if>
+            <if test="isRight != null">is_right = #{isRight},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <update id="deleteTElPaperQuById" parameterType="Long">
+        update t_el_paper_qu set del_flag = 2 where id = #{id}
+    </update>
+
+    <update id="deleteTElPaperQuByIds" parameterType="String">
+        update t_el_paper_qu set del_flag = 2 where id in
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </update>
+
+</mapper>

+ 116 - 0
master/src/main/resources/mybatis/training/elearn/TElQuAnswerMapper.xml

@@ -0,0 +1,116 @@
+<?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.ruoyi.project.training.elearn.mapper.TElQuAnswerMapper">
+
+    <resultMap type="TElQuAnswer" id="TElQuAnswerResult">
+        <result property="answerId"    column="answer_id"    />
+        <result property="quId"    column="qu_id"    />
+        <result property="isRight"    column="is_right"    />
+        <result property="content"    column="content"    />
+        <result property="image"    column="image"    />
+        <result property="analysis"    column="analysis"    />
+        <result property="delFlag"    column="del_flag"    />
+        <result property="createrCode"    column="creater_code"    />
+        <result property="createdate"    column="createdate"    />
+        <result property="updaterCode"    column="updater_code"    />
+        <result property="updatedate"    column="updatedate"    />
+        <result property="deptId"    column="dept_id"    />
+        <result property="remarks"    column="remarks"    />
+        <result property="deptName" column="dept_name" />
+    </resultMap>
+
+    <sql id="selectTElQuAnswerVo">
+        select d.answer_id, d.qu_id, d.is_right, d.content, d.image, d.analysis, d.del_flag, d.creater_code, d.createdate, d.updater_code, d.updatedate, d.dept_id, d.remarks ,s.dept_name from t_el_qu_answer d
+      left join sys_dept s on s.dept_id = d.dept_id
+    </sql>
+
+    <select id="selectTElQuAnswerList" parameterType="TElQuAnswer" resultMap="TElQuAnswerResult">
+        <include refid="selectTElQuAnswerVo"/>
+        <where>
+            <if test="isRight != null "> and is_right = #{isRight}</if>
+            <if test="content != null  and content != ''"> and content = #{content}</if>
+            <if test="image != null  and image != ''"> and image = #{image}</if>
+            <if test="analysis != null  and analysis != ''"> and analysis = #{analysis}</if>
+            <if test="remarks != null  and remarks != ''"> and remarks = #{remarks}</if>
+            <if test="quId != null  and quId != ''"> and qu_id = #{quId}</if>
+            and d.del_flag = 0
+        </where>
+        <!-- 数据范围过滤 -->
+        ${params.dataScope}
+    </select>
+
+    <select id="selectTElQuAnswerById" parameterType="Long" resultMap="TElQuAnswerResult">
+        <include refid="selectTElQuAnswerVo"/>
+        where answer_id = #{answerId}
+    </select>
+
+    <insert id="insertTElQuAnswer" parameterType="TElQuAnswer">
+        <selectKey keyProperty="answerId" resultType="long" order="BEFORE">
+            SELECT seq_t_el_qu_answer.NEXTVAL as answerId FROM DUAL
+        </selectKey>
+        insert into t_el_qu_answer
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="answerId != null">answer_id,</if>
+            <if test="quId != null">qu_id,</if>
+            <if test="isRight != null">is_right,</if>
+            <if test="content != null">content,</if>
+            <if test="image != null">image,</if>
+            <if test="analysis != null">analysis,</if>
+            <if test="delFlag != null">del_flag,</if>
+            <if test="createrCode != null">creater_code,</if>
+            <if test="createdate != null">createdate,</if>
+            <if test="updaterCode != null">updater_code,</if>
+            <if test="updatedate != null">updatedate,</if>
+            <if test="deptId != null">dept_id,</if>
+            <if test="remarks != null">remarks,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="answerId != null">#{answerId},</if>
+            <if test="quId != null">#{quId},</if>
+            <if test="isRight != null">#{isRight},</if>
+            <if test="content != null">#{content},</if>
+            <if test="image != null">#{image},</if>
+            <if test="analysis != null">#{analysis},</if>
+            <if test="delFlag != null">#{delFlag},</if>
+            <if test="createrCode != null">#{createrCode},</if>
+            <if test="createdate != null">#{createdate},</if>
+            <if test="updaterCode != null">#{updaterCode},</if>
+            <if test="updatedate != null">#{updatedate},</if>
+            <if test="deptId != null">#{deptId},</if>
+            <if test="remarks != null">#{remarks},</if>
+         </trim>
+    </insert>
+
+    <update id="updateTElQuAnswer" parameterType="TElQuAnswer">
+        update t_el_qu_answer
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="quId != null">qu_id = #{quId},</if>
+            <if test="isRight != null">is_right = #{isRight},</if>
+            <if test="content != null">content = #{content},</if>
+            <if test="image != null">image = #{image},</if>
+            <if test="analysis != null">analysis = #{analysis},</if>
+            <if test="delFlag != null">del_flag = #{delFlag},</if>
+            <if test="createrCode != null">creater_code = #{createrCode},</if>
+            <if test="createdate != null">createdate = #{createdate},</if>
+            <if test="updaterCode != null">updater_code = #{updaterCode},</if>
+            <if test="updatedate != null">updatedate = #{updatedate},</if>
+            <if test="deptId != null">dept_id = #{deptId},</if>
+            <if test="remarks != null">remarks = #{remarks},</if>
+        </trim>
+        where answer_id = #{answerId}
+    </update>
+
+    <update id="deleteTElQuAnswerById" parameterType="Long">
+        update t_el_qu_answer set del_flag = 2 where answer_id = #{answerId}
+    </update>
+
+    <update id="deleteTElQuAnswerByIds" parameterType="String">
+        update t_el_qu_answer set del_flag = 2 where answer_id in
+        <foreach item="answerId" collection="array" open="(" separator="," close=")">
+            #{answerId}
+        </foreach>
+    </update>
+
+</mapper>

+ 126 - 0
master/src/main/resources/mybatis/training/elearn/TElQuMapper.xml

@@ -0,0 +1,126 @@
+<?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.ruoyi.project.training.elearn.mapper.TElQuMapper">
+
+    <resultMap type="TElQu" id="TElQuResult">
+        <result property="quId"    column="qu_id"    />
+        <result property="quType"    column="qu_type"    />
+        <result property="qlevel"    column="qlevel"    />
+        <result property="content"    column="content"    />
+        <result property="image"    column="image"    />
+        <result property="analysis"    column="analysis"    />
+        <result property="delFlag"    column="del_flag"    />
+        <result property="createrCode"    column="creater_code"    />
+        <result property="createdate"    column="createdate"    />
+        <result property="updaterCode"    column="updater_code"    />
+        <result property="updatedate"    column="updatedate"    />
+        <result property="deptId"    column="dept_id"    />
+        <result property="remarks"    column="remarks"    />
+        <result property="deptName" column="dept_name" />
+    </resultMap>
+
+    <sql id="selectTElQuVo">
+        select d.qu_id, d.qu_type, d.qlevel, d.content, d.image, d.analysis, d.del_flag, d.creater_code, d.createdate, d.updater_code, d.updatedate, d.dept_id, d.remarks from t_el_qu d
+    </sql>
+
+    <select id="selectTElQuList" parameterType="TElQu" resultMap="TElQuResult">
+        <include refid="selectTElQuVo"/>
+        <where>
+            <if test="quType != null "> and qu_type = #{quType}</if>
+            <if test="qlevel != null "> and qlevel = #{qlevel}</if>
+            <if test="content != null  and content != ''"> and content = #{content}</if>
+            <if test="image != null  and image != ''"> and image = #{image}</if>
+            <if test="analysis != null  and analysis != ''"> and analysis = #{analysis}</if>
+            <if test="createrCode != null  and createrCode != ''"> and creater_code = #{createrCode}</if>
+            <if test="createdate != null "> and createdate = #{createdate}</if>
+            <if test="updaterCode != null  and updaterCode != ''"> and updater_code = #{updaterCode}</if>
+            <if test="updatedate != null "> and updatedate = #{updatedate}</if>
+            <if test="deptId != null "> and dept_id = #{deptId}</if>
+            <if test="remarks != null  and remarks != ''"> and remarks = #{remarks}</if>
+            and d.del_flag = 0
+        </where>
+        <!-- 数据范围过滤 -->
+    </select>
+
+    <select id="selectTElQuListByRepo" parameterType="TElExamRepo" resultMap="TElQuResult">
+        select d.qu_id, d.qu_type, d.qlevel, d.content, d.image, d.analysis, d.del_flag, d.creater_code, d.createdate, d.updater_code, d.updatedate, d.dept_id, d.remarks from t_el_qu d
+        LEFT JOIN t_el_qu_repo b ON d.qu_id=b.qu_id
+        WHERE b.repo_id=#{repoId} AND d.qu_type=#{quType} and d.del_flag = 0
+
+    </select>
+
+    <select id="selectTElQuById" parameterType="Long" resultMap="TElQuResult">
+        <include refid="selectTElQuVo"/>
+        where qu_id = #{quId}
+    </select>
+
+    <insert id="insertTElQu" parameterType="TElQu">
+        <selectKey keyProperty="quId" resultType="long" order="BEFORE">
+            SELECT seq_t_el_qu.NEXTVAL as quId FROM DUAL
+        </selectKey>
+        insert into t_el_qu
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="quId != null">qu_id,</if>
+            <if test="quType != null">qu_type,</if>
+            <if test="qlevel != null">qlevel,</if>
+            <if test="content != null">content,</if>
+            <if test="image != null">image,</if>
+            <if test="analysis != null">analysis,</if>
+            <if test="delFlag != null">del_flag,</if>
+            <if test="createrCode != null">creater_code,</if>
+            <if test="createdate != null">createdate,</if>
+            <if test="updaterCode != null">updater_code,</if>
+            <if test="updatedate != null">updatedate,</if>
+            <if test="deptId != null">dept_id,</if>
+            <if test="remarks != null">remarks,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="quId != null">#{quId},</if>
+            <if test="quType != null">#{quType},</if>
+            <if test="qlevel != null">#{qlevel},</if>
+            <if test="content != null">#{content},</if>
+            <if test="image != null">#{image},</if>
+            <if test="analysis != null">#{analysis},</if>
+            <if test="delFlag != null">#{delFlag},</if>
+            <if test="createrCode != null">#{createrCode},</if>
+            <if test="createdate != null">#{createdate},</if>
+            <if test="updaterCode != null">#{updaterCode},</if>
+            <if test="updatedate != null">#{updatedate},</if>
+            <if test="deptId != null">#{deptId},</if>
+            <if test="remarks != null">#{remarks},</if>
+         </trim>
+    </insert>
+
+    <update id="updateTElQu" parameterType="TElQu">
+        update t_el_qu
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="quType != null">qu_type = #{quType},</if>
+            <if test="qlevel != null">qlevel = #{qlevel},</if>
+            <if test="content != null">content = #{content},</if>
+            <if test="image != null">image = #{image},</if>
+            <if test="analysis != null">analysis = #{analysis},</if>
+            <if test="delFlag != null">del_flag = #{delFlag},</if>
+            <if test="createrCode != null">creater_code = #{createrCode},</if>
+            <if test="createdate != null">createdate = #{createdate},</if>
+            <if test="updaterCode != null">updater_code = #{updaterCode},</if>
+            <if test="updatedate != null">updatedate = #{updatedate},</if>
+            <if test="deptId != null">dept_id = #{deptId},</if>
+            <if test="remarks != null">remarks = #{remarks},</if>
+        </trim>
+        where qu_id = #{quId}
+    </update>
+
+    <update id="deleteTElQuById" parameterType="Long">
+        update t_el_qu set del_flag = 2 where qu_id = #{quId}
+    </update>
+
+    <update id="deleteTElQuByIds" parameterType="String">
+        update t_el_qu set del_flag = 2 where qu_id in
+        <foreach item="quId" collection="array" open="(" separator="," close=")">
+            #{quId}
+        </foreach>
+    </update>
+
+</mapper>

+ 78 - 0
master/src/main/resources/mybatis/training/elearn/TElQuRepoMapper.xml

@@ -0,0 +1,78 @@
+<?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.ruoyi.project.training.elearn.mapper.TElQuRepoMapper">
+
+    <resultMap type="TElQuRepo" id="TElQuRepoResult">
+        <result property="id"    column="id"    />
+        <result property="quId"    column="qu_id"    />
+        <result property="repoId"    column="repo_id"    />
+        <result property="quType"    column="qu_type"    />
+        <result property="sort"    column="sort"    />
+    </resultMap>
+
+    <sql id="selectTElQuRepoVo">
+        select d.id, d.qu_id, d.repo_id, d.qu_type, d.sort from t_el_qu_repo d
+    </sql>
+
+    <select id="selectTElQuRepoList" parameterType="TElQuRepo" resultMap="TElQuRepoResult">
+        <include refid="selectTElQuRepoVo"/>
+        <where>
+            <if test="quId != null "> and qu_id = #{quId}</if>
+            <if test="repoId != null "> and repo_id = #{repoId}</if>
+            <if test="quType != null "> and qu_type = #{quType}</if>
+            <if test="sort != null "> and sort = #{sort}</if>
+        </where>
+        <!-- 数据范围过滤 -->
+    </select>
+
+    <select id="selectTElQuRepoById" parameterType="Long" resultMap="TElQuRepoResult">
+        <include refid="selectTElQuRepoVo"/>
+        where id = #{id}
+    </select>
+
+    <insert id="insertTElQuRepo" parameterType="TElQuRepo">
+        <selectKey keyProperty="id" resultType="long" order="BEFORE">
+            SELECT seq_t_el_qu_repo.NEXTVAL as id FROM DUAL
+        </selectKey>
+        insert into t_el_qu_repo
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="id != null">id,</if>
+            <if test="quId != null">qu_id,</if>
+            <if test="repoId != null">repo_id,</if>
+            <if test="quType != null">qu_type,</if>
+            <if test="sort != null">sort,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="id != null">#{id},</if>
+            <if test="quId != null">#{quId},</if>
+            <if test="repoId != null">#{repoId},</if>
+            <if test="quType != null">#{quType},</if>
+            <if test="sort != null">#{sort},</if>
+         </trim>
+    </insert>
+
+    <update id="updateTElQuRepo" parameterType="TElQuRepo">
+        update t_el_qu_repo
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="quId != null">qu_id = #{quId},</if>
+            <if test="repoId != null">repo_id = #{repoId},</if>
+            <if test="quType != null">qu_type = #{quType},</if>
+            <if test="sort != null">sort = #{sort},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteTElQuRepoById" parameterType="Long">
+        delete from t_el_qu_repo where id = #{id}
+    </delete>
+
+    <delete id="deleteTElQuRepoByIds" parameterType="String">
+        delete from t_el_qu_repo where id in
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+
+</mapper>

+ 114 - 0
master/src/main/resources/mybatis/training/elearn/TElRepoMapper.xml

@@ -0,0 +1,114 @@
+<?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.ruoyi.project.training.elearn.mapper.TElRepoMapper">
+
+    <resultMap type="TElRepo" id="TElRepoResult">
+        <result property="repoId"    column="repo_id"    />
+        <result property="code"    column="code"    />
+        <result property="title"    column="title"    />
+        <result property="delFlag"    column="del_flag"    />
+        <result property="createrCode"    column="creater_code"    />
+        <result property="createdate"    column="createdate"    />
+        <result property="updaterCode"    column="updater_code"    />
+        <result property="updatedate"    column="updatedate"    />
+        <result property="deptId"    column="dept_id"    />
+        <result property="remarks"    column="remarks"    />
+        <result property="deptName" column="dept_name" />
+        <result property="radioCount" column="radio_count" />
+        <result property="multiCount" column="multi_count" />
+        <result property="judgeCount"  column="judge_count"/>
+    </resultMap>
+
+    <sql id="selectTElRepoVo">
+        select d.repo_id, d.code, d.title, d.del_flag, d.creater_code, d.createdate, d.updater_code, d.updatedate, d.dept_id, d.remarks ,s.dept_name,
+            (SELECT COUNT(0) FROM t_el_qu_repo WHERE repo_id=d.repo_id AND qu_type=1) AS radio_count,
+               (SELECT COUNT(0) FROM t_el_qu_repo WHERE repo_id=d.repo_id AND qu_type=2) AS multi_count,
+               (SELECT COUNT(0) FROM t_el_qu_repo WHERE repo_id=d.repo_id AND qu_type=3) AS judge_count
+        from t_el_repo d
+
+            left join sys_dept s on s.dept_id = d.dept_id
+    </sql>
+
+    <select id="selectTElRepoList" parameterType="TElRepo" resultMap="TElRepoResult">
+        <include refid="selectTElRepoVo"/>
+        <where>
+            <if test="code != null  and code != ''"> and code = #{code}</if>
+            <if test="title != null  and title != ''"> and title = #{title}</if>
+            <if test="createrCode != null  and createrCode != ''"> and creater_code = #{createrCode}</if>
+            <if test="createdate != null "> and createdate = #{createdate}</if>
+            <if test="updaterCode != null  and updaterCode != ''"> and updater_code = #{updaterCode}</if>
+            <if test="updatedate != null "> and updatedate = #{updatedate}</if>
+            <if test="deptId != null "> and dept_id = #{deptId}</if>
+            <if test="remarks != null  and remarks != ''"> and remarks = #{remarks}</if>
+            and d.del_flag = 0
+        </where>
+        <!-- 数据范围过滤 -->
+        ${params.dataScope}
+    </select>
+
+    <select id="selectTElRepoById" parameterType="Long" resultMap="TElRepoResult">
+        <include refid="selectTElRepoVo"/>
+        where repo_id = #{repoId}
+    </select>
+
+    <insert id="insertTElRepo" parameterType="TElRepo">
+        <selectKey keyProperty="repoId" resultType="long" order="BEFORE">
+            SELECT seq_t_el_repo.NEXTVAL as repoId FROM DUAL
+        </selectKey>
+        insert into t_el_repo
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="repoId != null">repo_id,</if>
+            <if test="code != null">code,</if>
+            <if test="title != null">title,</if>
+            <if test="delFlag != null">del_flag,</if>
+            <if test="createrCode != null">creater_code,</if>
+            <if test="createdate != null">createdate,</if>
+            <if test="updaterCode != null">updater_code,</if>
+            <if test="updatedate != null">updatedate,</if>
+            <if test="deptId != null">dept_id,</if>
+            <if test="remarks != null">remarks,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="repoId != null">#{repoId},</if>
+            <if test="code != null">#{code},</if>
+            <if test="title != null">#{title},</if>
+            <if test="delFlag != null">#{delFlag},</if>
+            <if test="createrCode != null">#{createrCode},</if>
+            <if test="createdate != null">#{createdate},</if>
+            <if test="updaterCode != null">#{updaterCode},</if>
+            <if test="updatedate != null">#{updatedate},</if>
+            <if test="deptId != null">#{deptId},</if>
+            <if test="remarks != null">#{remarks},</if>
+         </trim>
+    </insert>
+
+    <update id="updateTElRepo" parameterType="TElRepo">
+        update t_el_repo
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="code != null">code = #{code},</if>
+            <if test="title != null">title = #{title},</if>
+            <if test="delFlag != null">del_flag = #{delFlag},</if>
+            <if test="createrCode != null">creater_code = #{createrCode},</if>
+            <if test="createdate != null">createdate = #{createdate},</if>
+            <if test="updaterCode != null">updater_code = #{updaterCode},</if>
+            <if test="updatedate != null">updatedate = #{updatedate},</if>
+            <if test="deptId != null">dept_id = #{deptId},</if>
+            <if test="remarks != null">remarks = #{remarks},</if>
+        </trim>
+        where repo_id = #{repoId}
+    </update>
+
+    <update id="deleteTElRepoById" parameterType="Long">
+        update t_el_repo set del_flag = 2 where repo_id = #{repoId}
+    </update>
+
+    <update id="deleteTElRepoByIds" parameterType="String">
+        update t_el_repo set del_flag = 2 where repo_id in
+        <foreach item="repoId" collection="array" open="(" separator="," close=")">
+            #{repoId}
+        </foreach>
+    </update>
+
+</mapper>

+ 53 - 0
ui/src/api/training/bccnew/firstPlanTmpl.js

@@ -0,0 +1,53 @@
+import request from '@/utils/request'
+
+// 查询进组培训模版列表
+export function listFirstPlanTmpl(query) {
+  return request({
+    url: '/bccnew/firstPlanTmpl/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询进组培训模版详细
+export function getFirstPlanTmpl(id) {
+  return request({
+    url: '/bccnew/firstPlanTmpl/' + id,
+    method: 'get'
+  })
+}
+
+// 新增进组培训模版
+export function addFirstPlanTmpl(data) {
+  return request({
+    url: '/bccnew/firstPlanTmpl',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改进组培训模版
+export function updateFirstPlanTmpl(data) {
+  return request({
+    url: '/bccnew/firstPlanTmpl',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除进组培训模版
+export function delFirstPlanTmpl(id) {
+  return request({
+    url: '/bccnew/firstPlanTmpl/' + id,
+    method: 'delete'
+  })
+}
+
+// 导出进组培训模版
+export function exportFirstPlanTmpl(query) {
+  return request({
+    url: '/bccnew/firstPlanTmpl/export',
+    method: 'get',
+    params: query
+  })
+}

+ 53 - 0
ui/src/api/training/bccnew/tsnew.js

@@ -0,0 +1,53 @@
+import request from '@/utils/request'
+
+// 查询导师带徒列表
+export function listTsnew(query) {
+  return request({
+    url: '/bccnew/tsnew/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询导师带徒详细
+export function getTsnew(newId) {
+  return request({
+    url: '/bccnew/tsnew/' + newId,
+    method: 'get'
+  })
+}
+
+// 新增导师带徒
+export function addTsnew(data) {
+  return request({
+    url: '/bccnew/tsnew',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改导师带徒
+export function updateTsnew(data) {
+  return request({
+    url: '/bccnew/tsnew',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除导师带徒
+export function delTsnew(newId) {
+  return request({
+    url: '/bccnew/tsnew/' + newId,
+    method: 'delete'
+  })
+}
+
+// 导出导师带徒
+export function exportTsnew(query) {
+  return request({
+    url: '/bccnew/tsnew/export',
+    method: 'get',
+    params: query
+  })
+}

+ 53 - 0
ui/src/api/training/elearn/answer.js

@@ -0,0 +1,53 @@
+import request from '@/utils/request'
+
+// 查询试题选项答案列表
+export function listAnswer(query) {
+  return request({
+    url: '/elearn/answer/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询试题选项答案详细
+export function getAnswer(answerId) {
+  return request({
+    url: '/elearn/answer/' + answerId,
+    method: 'get'
+  })
+}
+
+// 新增试题选项答案
+export function addAnswer(data) {
+  return request({
+    url: '/elearn/answer',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改试题选项答案
+export function updateAnswer(data) {
+  return request({
+    url: '/elearn/answer',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除试题选项答案
+export function delAnswer(answerId) {
+  return request({
+    url: '/elearn/answer/' + answerId,
+    method: 'delete'
+  })
+}
+
+// 导出试题选项答案
+export function exportAnswer(query) {
+  return request({
+    url: '/elearn/answer/export',
+    method: 'get',
+    params: query
+  })
+}

+ 53 - 0
ui/src/api/training/elearn/exam.js

@@ -0,0 +1,53 @@
+import request from '@/utils/request'
+
+// 查询考试列表
+export function listExam(query) {
+  return request({
+    url: '/elearn/exam/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询考试详细
+export function getExam(examId) {
+  return request({
+    url: '/elearn/exam/' + examId,
+    method: 'get'
+  })
+}
+
+// 新增考试
+export function addExam(data) {
+  return request({
+    url: '/elearn/exam',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改考试
+export function updateExam(data) {
+  return request({
+    url: '/elearn/exam',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除考试
+export function delExam(examId) {
+  return request({
+    url: '/elearn/exam/' + examId,
+    method: 'delete'
+  })
+}
+
+// 导出考试
+export function exportExam(query) {
+  return request({
+    url: '/elearn/exam/export',
+    method: 'get',
+    params: query
+  })
+}

+ 63 - 0
ui/src/api/training/elearn/paper.js

@@ -0,0 +1,63 @@
+import request from '@/utils/request'
+
+// 查询在线考试列表
+export function listPaper(query) {
+  return request({
+    url: '/elearn/paper/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询在线考试详细
+export function getPaper(paperId) {
+  return request({
+    url: '/elearn/paper/' + paperId,
+    method: 'get'
+  })
+}
+
+// 新增在线考试
+export function addPaper(data) {
+  return request({
+    url: '/elearn/paper',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改在线考试
+export function updatePaper(data) {
+  return request({
+    url: '/elearn/paper',
+    method: 'put',
+    data: data
+  })
+}
+
+// 创建考试
+export function createPaper(data) {
+  return request({
+    url: '/elearn/paper/createPaper',
+    method: 'post',
+    data: data
+  })
+}
+
+
+// 删除在线考试
+export function delPaper(paperId) {
+  return request({
+    url: '/elearn/paper/' + paperId,
+    method: 'delete'
+  })
+}
+
+// 导出在线考试
+export function exportPaper(query) {
+  return request({
+    url: '/elearn/paper/export',
+    method: 'get',
+    params: query
+  })
+}

+ 53 - 0
ui/src/api/training/elearn/qu.js

@@ -0,0 +1,53 @@
+import request from '@/utils/request'
+
+// 查询试题列表
+export function listQu(query) {
+  return request({
+    url: '/elearn/qu/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询试题详细
+export function getQu(quId) {
+  return request({
+    url: '/elearn/qu/' + quId,
+    method: 'get'
+  })
+}
+
+// 新增试题
+export function addQu(data) {
+  return request({
+    url: '/elearn/qu',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改试题
+export function updateQu(data) {
+  return request({
+    url: '/elearn/qu',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除试题
+export function delQu(quId) {
+  return request({
+    url: '/elearn/qu/' + quId,
+    method: 'delete'
+  })
+}
+
+// 导出试题
+export function exportQu(query) {
+  return request({
+    url: '/elearn/qu/export',
+    method: 'get',
+    params: query
+  })
+}

+ 53 - 0
ui/src/api/training/elearn/repo.js

@@ -0,0 +1,53 @@
+import request from '@/utils/request'
+
+// 查询题库列表
+export function listRepo(query) {
+  return request({
+    url: '/elearn/repo/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询题库详细
+export function getRepo(repoId) {
+  return request({
+    url: '/elearn/repo/' + repoId,
+    method: 'get'
+  })
+}
+
+// 新增题库
+export function addRepo(data) {
+  return request({
+    url: '/elearn/repo',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改题库
+export function updateRepo(data) {
+  return request({
+    url: '/elearn/repo',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除题库
+export function delRepo(repoId) {
+  return request({
+    url: '/elearn/repo/' + repoId,
+    method: 'delete'
+  })
+}
+
+// 导出题库
+export function exportRepo(query) {
+  return request({
+    url: '/elearn/repo/export',
+    method: 'get',
+    params: query
+  })
+}

+ 76 - 0
ui/src/components/RepoSelect/index.vue

@@ -0,0 +1,76 @@
+<template>
+
+  <el-select
+    v-model="currentValue"
+    :multiple="multi"
+    :remote-method="fetchData"
+    filterable
+    remote
+    reserve-keyword
+    clearable
+    automatic-dropdown
+    placeholder="选择或搜索题库"
+    class="filter-item"
+    @change="handlerChange"
+  >
+    <el-option
+      v-for="item in dataList"
+      :key="item.repoId"
+      :label="item.title"
+      :value="item.repoId"
+    />
+  </el-select>
+
+</template>
+
+<script>
+
+import { listRepo } from '@/api/training/elearn/repo'
+
+export default {
+  name: 'RepoSelect',
+  props: {
+    multi: {
+      type: Boolean,
+      default: false
+    },
+    value: String | Array,
+    excludes: Array
+  },
+  data() {
+    return {
+      // 下拉选项值
+      dataList: [],
+      currentValue: []
+    }
+  },
+
+  watch: {
+    // 检测查询变化
+    value: {
+      handler() {
+        this.currentValue = this.value
+      }
+    }
+  },
+  created() {
+    this.currentValue = this.value
+    this.fetchData()
+  },
+  methods: {
+    fetchData(q) {
+      listRepo({ pageNum: 1, pageSize: 1000,  title: q, excludes: this.excludes }).then(res => {
+        this.dataList = res.rows;
+      })
+    },
+    handlerChange(e) {
+      const obj = this.dataList.find((item) => {
+        return item.repoId == e
+      })
+
+      this.$emit('change', obj)
+      this.$emit('input', e)
+    }
+  }
+}
+</script>

+ 20 - 0
ui/src/router/index.js

@@ -580,6 +580,26 @@ export const constantRoutes = [
       }
     ]
   },
+  {
+    path: '/training/elearn',
+    component: Layout,
+    hidden: true,
+    children: [
+      {
+        path: 'exam/prepare/:examId',
+        component: () => import('@/views/training/elearn/paper/preview'),
+        name: 'PreExam',
+        meta: { title: '准备考试', noCache: true },
+        hidden: true
+      },{
+        path: 'paper',
+        component: () => import('@/views/training/elearn/paper/list'),
+        name: 'paper',
+        meta: { title: '在线考试', noCache: true },
+        hidden: true
+      },
+    ]
+  },
   {
     path: '/reliability',
     component: Layout,

+ 12 - 21
ui/src/views/components/meeting/ehsopenitem.vue

@@ -293,32 +293,23 @@
       // 表单参数
       form: {},
       categoryOptions: [{
-        value: '安全巡检开项',
-        label: '安全巡检开项'
+        value: '隐患排查',
+        label: '隐患排查'
       }, {
-        value: '审计开项',
-        label: '审计开项'
+        value: '审计',
+        label: '审计'
       }, {
-        value: '政府检查开项',
-        label: '政府检查开项'
+        value: '双预防隐患',
+        label: '双预防隐患'
       }, {
-        value: '会议中的EHS开项',
-        label: '会议中的EHS开项'
+        value: '项目/变更管理',
+        label: '项目/变更管理'
       },{
-        value: '事故调查开项',
-        label: '事故调查开项'
+        value: '事件调查',
+        label: '事件调查'
       },{
-        value: '项目/MOC EHS审查',
-        label: '项目/MOC EHS审查'
-      },{
-        value: '消防演练开项',
-        label: '消防演练开项'
-      },{
-        value: '现场EHS检查',
-        label: '现场EHS检查'
-      },{
-        value: '5S改进开项',
-        label: '5S改进开项'
+        value: '会议',
+        label: '会议'
       }, {
         value: 'Stature开项',
         label: 'Stature开项'

+ 1 - 1
ui/src/views/components/meeting/keymaintenance.vue

@@ -121,7 +121,7 @@
             type="text"
             icon="el-icon-delete"
             @click="handleDelete(scope.row)"
-            v-if="checkPermi(['plant:meeting:remove']) || getStaffId(scope.row.responsible,scope.row.createrCode)"
+            v-if="checkPermi(['plant:meeting:remove']) "
 
           >{{ $t('删除') }}</el-button>
         </template>

+ 1 - 1
ui/src/views/components/meeting/messageattention.vue

@@ -101,7 +101,7 @@
             type="text"
             icon="el-icon-delete"
             @click="handleDelete(scope.row)"
-            v-if="checkPermi(['plant:meeting:remove']) || getStaffId(scope.row.responsible,scope.row.createrCode)"
+            v-if="checkPermi(['plant:meeting:remove']) "
 
           >{{ $t('删除') }}</el-button>
         </template>

+ 126 - 68
ui/src/views/plant/confInfo/index.vue

@@ -9,14 +9,15 @@
     </div>
     <div style="position: absolute; top:40px; left:200px">
       会议室:
-      <!--      <el-select v-model="conferenceInfo.defultConferenceRoomId" placeholder="请选择会议室" style="width:300px; " size='small' @change="changeConferenceRoom" >-->
-      <!--        <el-option-->
-      <!--          v-for="item in conferenceInfo.conferenceRoom"-->
-      <!--          :key="item.value"-->
-      <!--          :label="item.label"-->
-      <!--          :value="item.value">-->
-      <!--        </el-option>-->
-      <!--      </el-select>-->
+            <el-select v-model="queryParams.roomId" placeholder="请选择会议室" style="width:300px; " size='small'@change="handleQuery" >
+              <el-option
+                v-for="dict in roomOptions"
+                :key="dict.id"
+                :label="dict.roomName"
+                :value="dict.id"
+              >
+              </el-option>
+            </el-select>
     </div>
 
     <div style="position: absolute; top:40px; right:300px">
@@ -31,94 +32,79 @@
     <!-- 添加或修改会议预约信息对话框 -->
     <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
       <el-form ref="form" :model="form" :rules="rules" label-width="80px">
-        <el-form-item label="会议室id" prop="roomId">
-          <el-input v-model="form.roomId" placeholder="请输入会议室id"/>
-        </el-form-item>
         <el-form-item label="会议主题" prop="subject">
-          <el-input v-model="form.subject" placeholder="请输入会议主题"/>
+          <el-input v-model="form.subject" placeholder="请输入会议主题" />
         </el-form-item>
         <el-form-item label="召集人" prop="convenerId">
-          <el-input v-model="form.convenerId" placeholder="请输入召集人"/>
-        </el-form-item>
-        <el-form-item label="召集人姓名" prop="convenerName">
-          <el-input v-model="form.convenerName" placeholder="请输入召集人姓名"/>
+          <el-input v-model="form.convenerId" placeholder="请输入召集人" />
         </el-form-item>
-        <el-form-item label="会议室名称" prop="roomName">
-          <el-input v-model="form.roomName" placeholder="请输入会议室名称"/>
+
+        <el-form-item label="会议室名称" prop="roomId">
+          <el-select v-model="form.roomId">
+            <el-option
+              v-for="dict in roomOptions"
+              :key="dict.id"
+              :label="dict.roomName"
+              :value="dict.id"
+            ></el-option>
+
+          </el-select>
         </el-form-item>
         <el-form-item label="参会人" prop="participantsList">
-          <el-input v-model="form.participantsList" placeholder="请输入参会人"/>
+          <el-input v-model="form.participantsList" placeholder="请输入参会人" />
         </el-form-item>
         <el-form-item label="会议开始时间" prop="beginDatetime">
           <el-date-picker clearable size="small" style="width: 200px"
                           v-model="form.beginDatetime"
-                          type="date"
-                          value-format="yyyy-MM-dd"
+                          type="datetime"
+                          value-format="yyyy-MM-dd HH:mm:ss"
+                          align="right"
+                          :picker-options="pickerOptions"
                           placeholder="选择会议开始时间">
+
           </el-date-picker>
         </el-form-item>
         <el-form-item label="会议结束时间" prop="endDatetime">
           <el-date-picker clearable size="small" style="width: 200px"
                           v-model="form.endDatetime"
-                          type="date"
-                          value-format="yyyy-MM-dd"
+                          type="datetime"
+                          value-format="yyyy-MM-dd HH:mm:ss"
+                          align="right"
+                          :picker-options="pickerOptions"
                           placeholder="选择会议结束时间">
           </el-date-picker>
         </el-form-item>
         <el-form-item label="颜色" prop="color">
-          <el-input v-model="form.color" placeholder="请输入颜色"/>
+          <el-color-picker v-model="form.color" show-alpha></el-color-picker>
         </el-form-item>
         <el-form-item label="全天显示" prop="isAllday">
-          <el-input v-model="form.isAllday" placeholder="请输入全天显示"/>
-        </el-form-item>
-        <el-form-item label="生成频率" prop="genFrequency">
-          <el-input v-model="form.genFrequency" placeholder="请输入生成频率"/>
+          <el-select v-model="form.isAllday" placeholder="请输入全天显示 ">
+            <el-option label="否" value="0" />
+            <el-option label="是" value="1" />
+          </el-select>
         </el-form-item>
-        <el-form-item label="生成月" prop="genMonth">
-          <el-input v-model="form.genMonth" placeholder="请输入生成月"/>
+<!--        <el-form-item label="生成频率" prop="genFrequency">
+          <el-select v-model="form.genFrequency" placeholder="请输入生成频率 ">
+            <el-option label="只生成一次" value="1-N" />
+            <el-option label="一天一次" value="1-D" />
+            <el-option label="一周一次" value="1-W" />
+            <el-option label="一月一次" value="1-M" />
+          </el-select>
+        </el-form-item>-->
+<!--        <el-form-item label="生成月" prop="genMonth">
+          <el-input v-model="form.genMonth" placeholder="请输入生成月" />
         </el-form-item>
         <el-form-item label="生成日" prop="genDay">
-          <el-input v-model="form.genDay" placeholder="请输入生成日"/>
+          <el-input v-model="form.genDay" placeholder="请输入生成日" />
         </el-form-item>
         <el-form-item label="生成日期" prop="genDate">
-          <el-input v-model="form.genDate" placeholder="请输入生成日期"/>
+          <el-input v-model="form.genDate" placeholder="请输入生成日期" />
         </el-form-item>
         <el-form-item label="生成时间" prop="genDatetime">
-          <el-input v-model="form.genDatetime" placeholder="请输入生成时间"/>
-        </el-form-item>
-        <el-form-item label="删除" prop="delFlag">
-          <el-input v-model="form.delFlag" placeholder="请输入删除"/>
-        </el-form-item>
-        <el-form-item label="创建人" prop="createrCode">
-          <el-input v-model="form.createrCode" placeholder="请输入创建人"/>
-        </el-form-item>
-        <el-form-item label="创建时间" prop="createdate">
-          <el-date-picker clearable size="small" style="width: 200px"
-                          v-model="form.createdate"
-                          type="date"
-                          value-format="yyyy-MM-dd"
-                          placeholder="选择创建时间">
-          </el-date-picker>
-        </el-form-item>
-        <el-form-item label="更新人" prop="updaterCode">
-          <el-input v-model="form.updaterCode" placeholder="请输入更新人"/>
-        </el-form-item>
-        <el-form-item label="更新日期" prop="updatedate">
-          <el-date-picker clearable size="small" style="width: 200px"
-                          v-model="form.updatedate"
-                          type="date"
-                          value-format="yyyy-MM-dd"
-                          placeholder="选择更新日期">
-          </el-date-picker>
-        </el-form-item>
-        <el-form-item label="所属部门" prop="deptId">
-          <el-input v-model="form.deptId" placeholder="请输入所属部门"/>
-        </el-form-item>
+          <el-input v-model="form.genDatetime" placeholder="请输入生成时间" />
+        </el-form-item>-->
         <el-form-item label="备注" prop="remarks">
-          <el-input v-model="form.remarks" placeholder="请输入备注"/>
-        </el-form-item>
-        <el-form-item label="归属部门" prop="deptId">
-          <treeselect v-model="form.deptId" :options="deptOptions" :show-count="true" placeholder="请选择归属部门"/>
+          <el-input v-model="form.remarks" placeholder="请输入备注" />
         </el-form-item>
       </el-form>
       <div slot="footer" class="dialog-footer">
@@ -153,6 +139,7 @@ import bootstrapPlugin from '@fullcalendar/bootstrap';
 import {INITIAL_EVENTS, createEventId} from '@/utils/event-utils'
 import 'bootstrap/dist/css/bootstrap.css';
 import {dateFormat} from '@/utils/date';
+import {listConfRoom} from "@/api/plant/confRoom";
 
 export default {
   name: "ConfInfo",
@@ -250,7 +237,7 @@ export default {
           },
         },
         selectMirror: 'true',
-        slotMinTime: '00:00:00',
+        slotMinTime: '06:00:00',
         slotMaxTime: '24:00:00',
         selectable: 'true',
         locale: 'zh-cn',
@@ -327,6 +314,49 @@ export default {
       title: "",
       // 部门树选项
       deptOptions: undefined,
+      roomOptions: [],
+      pickerOptions: {
+        selectableRange: '00:00:00 - 23:59:59',
+        disabledDate(time) {
+          const date = new Date();
+          let timeStr = dateFormat(time).substring(0, 10);
+          let nowStr = dateFormat(date).substring(0, 10);
+          return new Date(timeStr)  < new Date(nowStr);
+        },
+        shortcuts: [
+          {
+            text: '现在',
+            onClick(picker) {
+              const date = new Date();
+              picker.$emit('pick', date);
+            }
+          },
+          {
+            text: '一小时后',
+            onClick(picker) {
+              const date = new Date();
+              date.setTime(date.getTime() + 3600 * 1000);
+              picker.$emit('pick', date);
+            }
+          },
+          {
+            text: '两小时后',
+            onClick(picker) {
+              const date = new Date();
+              date.setTime(date.getTime() + 7200 * 1000);
+              picker.$emit('pick', date);
+            }
+          },
+          {
+            text: '三小时后',
+            onClick(picker) {
+              const date = new Date();
+              date.setTime(date.getTime() + 10800 * 1000);
+              picker.$emit('pick', date);
+            }
+          }
+        ]
+      },
       clientHeight: 300,
       // 是否显示弹出层
       open: false,
@@ -348,7 +378,7 @@ export default {
       // 查询参数
       queryParams: {
         pageNum: 1,
-        pageSize: 20,
+        pageSize: 50,
         roomId: null,
         subject: null,
         convenerId: null,
@@ -374,6 +404,10 @@ export default {
     this.$nextTick(() => {
       this.clientHeight = document.body.clientHeight - 250
     })
+    listConfRoom({}).then(response => {
+      this.roomOptions = response.rows;
+
+    });
     this.getList();
     this.getTreeselect();
   },
@@ -428,8 +462,10 @@ export default {
           });
         }
         else{
+          this.calendarOptions.events = [];
           //改写No Event To Display;
           var ele =document.getElementsByClassName('fc-list-empty-cushion');
+          console.log(ele)
           if(ele.length > 0){
             setTimeout(() => {
               ele[0].innerText = '没有更多数据!';
@@ -506,6 +542,16 @@ export default {
       this.open = true;
       this.title = "添加会议预约信息";
     },
+    /**
+     * 打开新建时初始化日期
+     */
+    handleDateSelect(selectInfo) {
+      console.log(selectInfo)
+      this.reset();
+      this.open = true;
+      this.title = "添加会议预约信息";
+      let startDate = selectInfo.start
+    },
     /** 修改按钮操作 */
     handleUpdate(row) {
       this.reset();
@@ -516,6 +562,18 @@ export default {
         this.title = "修改会议预约信息";
       });
     },
+    /**
+     * 点击会议查询当前会议记录
+     */
+    handleEventClick(clickInfo) {
+      this.reset();
+      const id = clickInfo.event.id
+      getConfInfo(id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改会议预约信息";
+      });
+    },
     /** 提交按钮 */
     submitForm() {
       this.$refs["form"].validate(valid => {

+ 0 - 1
ui/src/views/plant/confInfo/list.vue

@@ -361,7 +361,6 @@ export default {
     this.getTreeselect();
     listConfRoom({}).then(response => {
       this.roomOptions = response.rows;
-
     });
   },
   methods: {

+ 606 - 0
ui/src/views/training/bccnew/firstPlanTmpl/index.vue

@@ -0,0 +1,606 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="培训员工编号" prop="newId">
+        <el-input
+          v-model="queryParams.newId"
+          placeholder="请输入培训员工编号"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="课程编号" prop="courseCode">
+        <el-input
+          v-model="queryParams.courseCode"
+          placeholder="请输入课程编号"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="培训主题" prop="topic">
+        <el-input
+          v-model="queryParams.topic"
+          placeholder="请输入培训主题"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="培训天" prop="courseDay">
+        <el-input
+          v-model="queryParams.courseDay"
+          placeholder="请输入培训天"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="培训小时" prop="courseHour">
+        <el-input
+          v-model="queryParams.courseHour"
+          placeholder="请输入培训小时"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="培训类型" prop="courseType">
+        <el-select v-model="queryParams.courseType" placeholder="请选择培训类型" clearable size="small">
+          <el-option label="请选择字典生成" value="" />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="讲师" prop="trainer">
+        <el-input
+          v-model="queryParams.trainer"
+          placeholder="请输入讲师"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="培训日期" prop="courseDate">
+        <el-date-picker clearable size="small" style="width: 200px"
+          v-model="queryParams.courseDate"
+          type="date"
+          value-format="yyyy-MM-dd"
+          placeholder="选择培训日期">
+        </el-date-picker>
+      </el-form-item>
+      <el-form-item label="考核情况" prop="assess">
+        <el-input
+          v-model="queryParams.assess"
+          placeholder="请输入考核情况"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="创建人" prop="createrCode">
+        <el-input
+          v-model="queryParams.createrCode"
+          placeholder="请输入创建人"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="创建时间" prop="createdate">
+        <el-date-picker clearable size="small" style="width: 200px"
+          v-model="queryParams.createdate"
+          type="date"
+          value-format="yyyy-MM-dd"
+          placeholder="选择创建时间">
+        </el-date-picker>
+      </el-form-item>
+      <el-form-item label="修改人" prop="updaterCode">
+        <el-input
+          v-model="queryParams.updaterCode"
+          placeholder="请输入修改人"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="修改时间" prop="updatedate">
+        <el-date-picker clearable size="small" style="width: 200px"
+          v-model="queryParams.updatedate"
+          type="date"
+          value-format="yyyy-MM-dd"
+          placeholder="选择修改时间">
+        </el-date-picker>
+      </el-form-item>
+      <el-form-item label="部门编号" prop="deptId">
+        <el-input
+          v-model="queryParams.deptId"
+          placeholder="请输入部门编号"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="备注" prop="remarks">
+        <el-input
+          v-model="queryParams.remarks"
+          placeholder="请输入备注"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['bccnew:firstPlanTmpl:add']"
+        >新增</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="single"
+          @click="handleUpdate"
+          v-hasPermi="['bccnew:firstPlanTmpl:edit']"
+        >修改</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['bccnew:firstPlanTmpl:remove']"
+        >删除</el-button>
+      </el-col>
+        <el-col :span="1.5">
+            <el-button
+                    type="info"
+                    icon="el-icon-upload2"
+                    size="mini"
+                    @click="handleImport"
+                    v-hasPermi="['bccnew:firstPlanTmpl:edit']"
+            >导入</el-button>
+        </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          icon="el-icon-download"
+          size="mini"
+          @click="handleExport"
+          v-hasPermi="['bccnew:firstPlanTmpl:export']"
+        >导出</el-button>
+      </el-col>
+	  <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading" :data="firstPlanTmplList" @selection-change="handleSelectionChange" :height="clientHeight" border>
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="唯一标识ID" align="center" prop="id" :show-overflow-tooltip="true"/>
+      <el-table-column label="培训员工编号" align="center" prop="newId" :show-overflow-tooltip="true"/>
+      <el-table-column label="课程编号" align="center" prop="courseCode" :show-overflow-tooltip="true"/>
+      <el-table-column label="培训主题" align="center" prop="topic" :show-overflow-tooltip="true"/>
+      <el-table-column label="培训内容" align="center" prop="content" :show-overflow-tooltip="true"/>
+      <el-table-column label="培训天" align="center" prop="courseDay" :show-overflow-tooltip="true"/>
+      <el-table-column label="培训小时" align="center" prop="courseHour" :show-overflow-tooltip="true"/>
+      <el-table-column label="培训类型" align="center" prop="courseType" :show-overflow-tooltip="true"/>
+      <el-table-column label="讲师" align="center" prop="trainer" :show-overflow-tooltip="true"/>
+      <el-table-column label="培训日期" align="center" prop="courseDate" width="100">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.courseDate, '{y}-{m}-{d}') }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="考核情况" align="center" prop="assess" :show-overflow-tooltip="true"/>
+      <el-table-column label="创建人" align="center" prop="createrCode" :show-overflow-tooltip="true"/>
+      <el-table-column label="创建时间" align="center" prop="createdate" width="100">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.createdate, '{y}-{m}-{d}') }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="修改人" align="center" prop="updaterCode" :show-overflow-tooltip="true"/>
+      <el-table-column label="修改时间" align="center" prop="updatedate" width="100">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.updatedate, '{y}-{m}-{d}') }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="部门编号" align="center" prop="deptId" :show-overflow-tooltip="true"/>
+      <el-table-column label="备注" align="center" prop="remarks" :show-overflow-tooltip="true"/>
+      <el-table-column label="操作" align="center" fixed="right" width="120" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleUpdate(scope.row)"
+            v-hasPermi="['bccnew:firstPlanTmpl:edit']"
+          >修改</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['bccnew:firstPlanTmpl:remove']"
+          >删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 添加或修改进组培训模版对话框 -->
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="培训员工编号" prop="newId">
+          <el-input v-model="form.newId" placeholder="请输入培训员工编号" />
+        </el-form-item>
+        <el-form-item label="课程编号" prop="courseCode">
+          <el-input v-model="form.courseCode" placeholder="请输入课程编号" />
+        </el-form-item>
+        <el-form-item label="培训主题" prop="topic">
+          <el-input v-model="form.topic" placeholder="请输入培训主题" />
+        </el-form-item>
+        <el-form-item label="培训内容">
+          <editor v-model="form.content" :min-height="192"/>
+        </el-form-item>
+        <el-form-item label="培训天" prop="courseDay">
+          <el-input v-model="form.courseDay" placeholder="请输入培训天" />
+        </el-form-item>
+        <el-form-item label="培训小时" prop="courseHour">
+          <el-input v-model="form.courseHour" placeholder="请输入培训小时" />
+        </el-form-item>
+        <el-form-item label="培训类型" prop="courseType">
+          <el-select v-model="form.courseType" placeholder="请选择培训类型">
+            <el-option label="请选择字典生成" value="" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="讲师" prop="trainer">
+          <el-input v-model="form.trainer" placeholder="请输入讲师" />
+        </el-form-item>
+        <el-form-item label="培训日期" prop="courseDate">
+          <el-date-picker clearable size="small" style="width: 200px"
+            v-model="form.courseDate"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="选择培训日期">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="考核情况" prop="assess">
+          <el-input v-model="form.assess" placeholder="请输入考核情况" />
+        </el-form-item>
+        <el-form-item label="删除状态" prop="delFlag">
+          <el-input v-model="form.delFlag" placeholder="请输入删除状态" />
+        </el-form-item>
+        <el-form-item label="创建人" prop="createrCode">
+          <el-input v-model="form.createrCode" placeholder="请输入创建人" />
+        </el-form-item>
+        <el-form-item label="创建时间" prop="createdate">
+          <el-date-picker clearable size="small" style="width: 200px"
+            v-model="form.createdate"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="选择创建时间">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="修改人" prop="updaterCode">
+          <el-input v-model="form.updaterCode" placeholder="请输入修改人" />
+        </el-form-item>
+        <el-form-item label="修改时间" prop="updatedate">
+          <el-date-picker clearable size="small" style="width: 200px"
+            v-model="form.updatedate"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="选择修改时间">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="部门编号" prop="deptId">
+          <el-input v-model="form.deptId" placeholder="请输入部门编号" />
+        </el-form-item>
+        <el-form-item label="备注" prop="remarks">
+          <el-input v-model="form.remarks" placeholder="请输入备注" />
+        </el-form-item>
+          <el-form-item label="归属部门" prop="deptId">
+              <treeselect v-model="form.deptId" :options="deptOptions" :show-count="true" placeholder="请选择归属部门" />
+          </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
+      <!-- 用户导入对话框 -->
+      <el-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body>
+          <el-upload
+                  ref="upload"
+                  :limit="1"
+                  accept=".xlsx, .xls"
+                  :headers="upload.headers"
+                  :action="upload.url + '?updateSupport=' + upload.updateSupport"
+                  :disabled="upload.isUploading"
+                  :on-progress="handleFileUploadProgress"
+                  :on-success="handleFileSuccess"
+                  :auto-upload="false"
+                  drag
+          >
+              <i class="el-icon-upload"></i>
+              <div class="el-upload__text">
+                  将文件拖到此处,或
+                  <em>点击上传</em>
+              </div>
+              <div class="el-upload__tip" slot="tip">
+                  <el-checkbox v-model="upload.updateSupport" />是否更新已经存在的用户数据
+                  <el-link type="info" style="font-size:12px" @click="importTemplate">下载模板</el-link>
+              </div>
+              <div class="el-upload__tip" style="color:red" slot="tip">提示:仅允许导入“xls”或“xlsx”格式文件!</div>
+          </el-upload>
+          <div slot="footer" class="dialog-footer">
+              <el-button type="primary" @click="submitFileForm">确 定</el-button>
+              <el-button @click="upload.open = false">取 消</el-button>
+          </div>
+      </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listFirstPlanTmpl, getFirstPlanTmpl, delFirstPlanTmpl, addFirstPlanTmpl, updateFirstPlanTmpl, exportFirstPlanTmpl, importTemplate} from "@/api/training/bccnew/firstPlanTmpl";
+import { treeselect } from "@/api/system/dept";
+import { getToken } from "@/utils/auth";
+import Treeselect from "@riophae/vue-treeselect";
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
+import Editor from '@/components/Editor';
+
+export default {
+  name: "FirstPlanTmpl",
+  components: { Treeselect },
+  // components: { Editor },
+  data() {
+    return {
+      // 遮罩层
+      loading: true,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: false,
+      // 总条数
+      total: 0,
+      // 进组培训模版表格数据
+      firstPlanTmplList: [],
+      // 弹出层标题
+      title: "",
+      // 部门树选项
+      deptOptions: undefined,
+      clientHeight:300,
+      // 是否显示弹出层
+      open: false,
+        // 用户导入参数
+        upload: {
+            // 是否显示弹出层(用户导入)
+            open: false,
+            // 弹出层标题(用户导入)
+            title: "",
+            // 是否禁用上传
+            isUploading: false,
+            // 是否更新已经存在的用户数据
+            updateSupport: 0,
+            // 设置上传的请求头部
+            headers: { Authorization: "Bearer " + getToken() },
+            // 上传的地址
+            url: process.env.VUE_APP_BASE_API + "/bccnew/firstPlanTmpl/importData"
+        },
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 20,
+        newId: null,
+        courseCode: null,
+        topic: null,
+        content: null,
+        courseDay: null,
+        courseHour: null,
+        courseType: null,
+        trainer: null,
+        courseDate: null,
+        assess: null,
+        createrCode: null,
+        createdate: null,
+        updaterCode: null,
+        updatedate: null,
+        deptId: null,
+        remarks: null
+      },
+      // 表单参数
+      form: {},
+      // 表单校验
+      rules: {
+      }
+    };
+  },
+  watch: {
+        // 根据名称筛选部门树
+        deptName(val) {
+            this.$refs.tree.filter(val);
+        }
+   },
+  created() {
+      //设置表格高度对应屏幕高度
+      this.$nextTick(() => {
+          this.clientHeight = document.body.clientHeight -250
+      })
+    this.getList();
+    this.getTreeselect();
+  },
+  methods: {
+    /** 查询进组培训模版列表 */
+    getList() {
+      this.loading = true;
+      listFirstPlanTmpl(this.queryParams).then(response => {
+        this.firstPlanTmplList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+     /** 查询部门下拉树结构 */
+     getTreeselect() {
+          treeselect().then(response => {
+              this.deptOptions = response.data;
+          });
+     },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        id: null,
+        newId: null,
+        courseCode: null,
+        topic: null,
+        content: null,
+        courseDay: null,
+        courseHour: null,
+        courseType: null,
+        trainer: null,
+        courseDate: null,
+        assess: null,
+        delFlag: null,
+        createrCode: null,
+        createdate: null,
+        updaterCode: null,
+        updatedate: null,
+        deptId: null,
+        remarks: null
+      };
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "添加进组培训模版";
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      const id = row.id || this.ids
+      getFirstPlanTmpl(id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改进组培训模版";
+      });
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            updateFirstPlanTmpl(this.form).then(response => {
+              this.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addFirstPlanTmpl(this.form).then(response => {
+              this.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$confirm('是否确认删除?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return delFirstPlanTmpl(ids);
+        }).then(() => {
+          this.getList();
+          this.msgSuccess("删除成功");
+        })
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      const queryParams = this.queryParams;
+      this.$confirm('是否确认导出所有进组培训模版数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return exportFirstPlanTmpl(queryParams);
+        }).then(response => {
+          this.download(response.msg);
+        })
+    },
+      /** 导入按钮操作 */
+      handleImport() {
+          this.upload.title = "用户导入";
+          this.upload.open = true;
+      },
+      /** 下载模板操作 */
+      importTemplate() {
+          importTemplate().then(response => {
+              this.download(response.msg);
+          });
+      },
+      // 文件上传中处理
+      handleFileUploadProgress(event, file, fileList) {
+          this.upload.isUploading = true;
+      },
+      // 文件上传成功处理
+      handleFileSuccess(response, file, fileList) {
+          this.upload.open = false;
+          this.upload.isUploading = false;
+          this.$refs.upload.clearFiles();
+          this.$alert(response.msg, "导入结果", { dangerouslyUseHTMLString: true });
+          this.getList();
+      },
+      // 提交上传文件
+      submitFileForm() {
+          this.$refs.upload.submit();
+      }
+  }
+};
+</script>

+ 3 - 0
ui/src/views/training/bccnew/index.vue

@@ -0,0 +1,3 @@
+<template >
+  <router-view />
+</template>

+ 776 - 0
ui/src/views/training/bccnew/tsnew/index.vue

@@ -0,0 +1,776 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="年度培训标题" prop="name">
+        <el-input
+          v-model="queryParams.name"
+          placeholder="请输入年度培训标题"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="培训状态" prop="planStatus">
+        <el-select v-model="queryParams.planStatus" placeholder="请选择培训状态" clearable size="small">
+          <el-option
+            v-for="dict in planStatusOptions"
+            :key="dict.dictValue"
+            :label="dict.dictLabel"
+            :value="dict.dictValue"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="开始时间" prop="startdate">
+        <el-date-picker clearable size="small" style="width: 200px"
+                        v-model="queryParams.startdate"
+                        type="date"
+                        value-format="yyyy-MM-dd"
+                        placeholder="选择开始时间">
+        </el-date-picker>
+      </el-form-item>
+      <el-form-item label="结束时间" prop="enddate">
+        <el-date-picker clearable size="small" style="width: 200px"
+                        v-model="queryParams.enddate"
+                        type="date"
+                        value-format="yyyy-MM-dd"
+                        placeholder="选择结束时间">
+        </el-date-picker>
+      </el-form-item>
+      <el-form-item label="培训类型 " prop="planType">
+        <el-select v-model="queryParams.planType" placeholder="请选择培训类型" clearable size="small">
+          <el-option
+            v-for="dict in planTypeOptions"
+            :key="dict.dictValue"
+            :label="dict.dictLabel"
+            :value="dict.dictValue"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['newstaff:tnNew:add']"
+        >新增</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="single"
+          @click="handleUpdate"
+          v-hasPermi="['newstaff:tnNew:edit']"
+        >修改</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['newstaff:tnNew:remove']"
+        >删除</el-button>
+      </el-col>
+      <!--        <el-col :span="1.5">-->
+      <!--            <el-button-->
+      <!--                    type="info"-->
+      <!--                    icon="el-icon-upload2"-->
+      <!--                    size="mini"-->
+      <!--                    @click="handleImport"-->
+      <!--                    v-hasPermi="['newstaff:tnNew:edit']"-->
+      <!--            >导入</el-button>-->
+      <!--        </el-col>-->
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          icon="el-icon-download"
+          size="mini"
+          @click="handleExport"
+          v-hasPermi="['newstaff:tnNew:export']"
+        >导出</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading" :data="tnNewList" @selection-change="handleSelectionChange" :height="clientHeight" border>
+      <el-table-column type="selection" width="55" align="center" />
+      <!--      <el-table-column label="培训员工编号" align="center" prop="staffId" :show-overflow-tooltip="true"/>-->
+      <el-table-column label="新员工" align="center" prop="staffName" width="100" />
+      <el-table-column label="培训状态" align="center" prop="planStatus" width="100" :formatter="planStatusFormat" >
+        <template slot-scope="scope">
+          <el-tag v-if="scope.row.planStatus == 1" size="small" type="success">已完成</el-tag>
+          <el-tag v-else-if="scope.row.planStatus == 0" size="small" type="info">未完成</el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column label="进度" align="center" width="160">
+        <template slot-scope="scope">
+          <el-progress :percentage="scope.row.planFinish"></el-progress>
+        </template>
+      </el-table-column>
+      <el-table-column label="开始时间" align="center" prop="startdate" width="100">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.startdate, '{y}-{m}-{d}') }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="结束时间" align="center" prop="enddate" width="100">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.enddate, '{y}-{m}-{d}') }}</span>
+        </template>
+      </el-table-column>
+      <!--      <el-table-column label="导师员工编号" align="center" prop="mentorStaffId" :show-overflow-tooltip="true"/>-->
+      <el-table-column label="导师" align="center" prop="mentorStaffName" width="100" />
+      <el-table-column label="培训类型" align="center" prop="planType" width="100">
+          <template slot-scope="scope">
+            <span v-if="scope.row.planType == 1" size="small" type="success">裂解</span>
+            <span v-else-if="scope.row.planType == 2" size="small" type="success">压缩</span>
+            <span v-else-if="scope.row.planType == 3" size="small" type="success">分离</span>
+            <span v-else-if="scope.row.planType == 4" size="small" type="success">芳烃</span>
+          </template>
+      </el-table-column>
+      <el-table-column label="三级教育记录卡" align="center" prop="three" width="80">
+        <template slot-scope="scope">
+          <el-button  icon="el-icon-folder" style="color:#6e96fa;" @click="handleDoc(scope.row , 'tnNew-three')" circle></el-button>
+        </template>
+      </el-table-column>
+
+      <el-table-column label="上岗能力评测表" align="center" prop="firstplan-score" width="80">
+        <template slot-scope="scope">
+          <el-button  icon="el-icon-folder" style="color:#6e96fa;" @click="handleDoc(scope.row , 'tnNew-firstplan-score')" circle></el-button>
+        </template>
+      </el-table-column>
+      <el-table-column label="导师提名表" align="center" prop="agreement" width="80">
+        <template slot-scope="scope">
+          <el-button  icon="el-icon-folder" style="color:#6e96fa;" @click="handleDoc(scope.row , 'tnNew-teacher-order')" circle></el-button>
+        </template>
+      </el-table-column>
+      <el-table-column label="带徒协议" align="center" prop="agreement" width="80">
+        <template slot-scope="scope">
+          <el-button  icon="el-icon-folder" style="color:#6e96fa;" @click="handleDoc(scope.row , 'tnNew-teacher-agreement')" circle></el-button>
+        </template>
+      </el-table-column>
+      <el-table-column label="带徒目标" align="center" prop="target" width="80">
+        <template slot-scope="scope">
+          <el-button  icon="el-icon-folder" style="color:#6e96fa;" @click="handleDoc(scope.row , 'tnNew-teacher-target')" circle></el-button>
+        </template>
+      </el-table-column>
+      <el-table-column label="培训考评" align="center" prop="tnNew-score" width="80">
+        <template slot-scope="scope">
+          <el-button  icon="el-icon-folder" style="color:#6e96fa;" @click="handleDoc(scope.row , 'tnNew-score')" circle></el-button>
+        </template>
+      </el-table-column>
+      <el-table-column label="备注" align="center" prop="remarks" :show-overflow-tooltip="true" width="100"/>
+      <el-table-column label="操作" align="center" fixed="right"  class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-view"
+            @click="planList(scope.row)"
+          >培训计划</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleUpdate(scope.row)"
+            v-hasPermi="['newstaff:tnNew:edit']"
+          >修改</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 添加或修改新员工培训对话框 -->
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="培训员工" prop="mentorStaffId">
+          <el-select v-model="form.staffId" filterable :placeholder="$t('请选择')+$t('培训员工')">
+            <el-option
+              v-for="item in userOption"
+              :key="item.staffid"
+              :label="item.name +'  '+ item.deptName"
+              :value="item.staffid"
+              :disabled="item.disabled">
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="培训状态">
+          <el-select v-model="form.planStatus" placeholder="请选择培训状态">
+            <el-option
+              v-for="dict in planStatusOptions"
+              :key="dict.dictValue"
+              :label="dict.dictLabel"
+              :value="parseInt(dict.dictValue)"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="开始时间" prop="startdate">
+          <el-date-picker clearable size="small" style="width: 200px"
+                          v-model="form.startdate"
+                          type="date"
+                          value-format="yyyy-MM-dd"
+                          placeholder="选择开始时间">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="结束时间" prop="enddate">
+          <el-date-picker clearable size="small" style="width: 200px"
+                          v-model="form.enddate"
+                          type="date"
+                          value-format="yyyy-MM-dd"
+                          placeholder="选择结束时间">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="导师员工" prop="mentorStaffId">
+          <el-select v-model="form.mentorStaffId" filterable :placeholder="$t('请选择')+$t('导师员工')">
+            <el-option
+              v-for="item in userOption"
+              :key="item.staffid"
+              :label="item.name +'  '+ item.deptName"
+              :value="item.staffid"
+              :disabled="item.disabled">
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="培训类型" prop="planType">
+          <el-radio-group v-model="form.planType">
+            <el-radio
+              key="1"
+              label="裂解"
+            >裂解</el-radio>
+            <el-radio
+              key="2"
+              label="压缩"
+            >压缩</el-radio>
+            <el-radio
+              key="3"
+              label="分离"
+            >分离</el-radio>
+            <el-radio
+              key="4"
+              label="芳烃"
+            >芳烃</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item label="备注" prop="remarks">
+          <el-input v-model="form.remarks" placeholder="请输入备注" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
+    <!-- 用户导入对话框 -->
+    <el-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body>
+      <el-upload
+        ref="upload"
+        :limit="1"
+        accept=".xlsx, .xls"
+        :headers="upload.headers"
+        :action="upload.url + '?updateSupport=' + upload.updateSupport"
+        :disabled="upload.isUploading"
+        :on-progress="handleFileUploadProgress"
+        :on-success="handleFileSuccess"
+        :auto-upload="false"
+        drag
+      >
+        <i class="el-icon-upload"></i>
+        <div class="el-upload__text">
+          将文件拖到此处,或
+          <em>点击上传</em>
+        </div>
+        <div class="el-upload__tip" slot="tip">
+          <el-checkbox v-model="upload.updateSupport" />是否更新已经存在的用户数据
+          <el-link type="info" style="font-size:12px" @click="importTemplate">下载模板</el-link>
+        </div>
+        <div class="el-upload__tip" style="color:red" slot="tip">提示:仅允许导入“xls”或“xlsx”格式文件!</div>
+      </el-upload>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitFileForm">确 定</el-button>
+        <el-button @click="upload.open = false">取 消</el-button>
+      </div>
+    </el-dialog>
+    <!-- 报告附件对话框 -->
+    <el-dialog  :close-on-click-modal="false" v-dialogDrag :title="doc.title" :visible.sync="doc.open" width="1000px" append-to-body >
+      <el-upload v-hasPermi="['training:trainingrecords:file']"
+                 ref="doc"
+                 :limit="50"
+                 :headers="doc.headers"
+                 :action="doc.url + '?pType=' + doc.pType + '&pId=' + doc.pId"
+                 :disabled="doc.isUploading"
+                 :on-progress="handleFileDocProgress"
+                 :on-success="handleFileDocSuccess"
+                 :auto-upload="true"
+                 drag
+      >
+        <i class="el-icon-upload"></i>
+        <div class="el-upload__text">
+          {{ $t('将文件拖到此处,或') }}
+          <em>{{ $t('点击上传') }}</em>
+        </div>
+      </el-upload>
+      <el-table :data="doc.commonfileList" border>
+        <el-table-column :label="$t('文件名')" align="center" prop="fileName" :show-overflow-tooltip="true">
+          <template slot-scope="scope">
+            <a  class="link-type"  @click="handleDownload(scope.row)">
+              <span>{{ scope.row.fileName }}</span>
+            </a>
+          </template>
+        </el-table-column>
+        <el-table-column :label="$t('大小(Kb)')" align="center" prop="fileSize" :show-overflow-tooltip="true" width="80" />
+        <el-table-column :label="$t('上传人')" align="center" prop="creator" :show-overflow-tooltip="true" width="120"/>
+        <!--        <el-table-column :label="$t('培训日期')" align="center" prop="pDate"  width="150">-->
+        <!--          <template slot-scope="scope">-->
+        <!--            <el-date-picker-->
+        <!--              v-if="scope.row.isEdit"-->
+        <!--              v-model="scope.row.pDate"-->
+        <!--              type="date"-->
+        <!--              value-format="yyyy-MM-dd"-->
+        <!--              placeholder="日期">-->
+        <!--            </el-date-picker>-->
+        <!--            <span v-else>{{ parseTime(scope.row.pDate, '{y}-{m}-{d}') }}</span>-->
+        <!--          </template>-->
+        <!--        </el-table-column>-->
+        <el-table-column :label="$t('操作')" align="center" width="220" class-name="small-padding fixed-width">
+          <template slot-scope="scope">
+            <el-button
+              v-if="scope.row.fileName.endsWith('pdf')"
+              size="mini"
+              type="text"
+              icon="el-icon-view"
+              @click="handleSee(scope.row)"
+            >{{ $t('预览') }}</el-button>
+            <el-button v-hasPermi="['training:trainingrecords:file']"  type="text" size="small" v-if="scope.row.isEdit" @click="save(scope.row)">保存</el-button>
+            <el-button type="text" size="small" v-if="scope.row.isEdit" @click="cancelFile(scope.row, scope.$index)">取消</el-button>
+            <!--            <el-button v-hasPermi="['training:trainingrecords:file']" v-if="!scope.row.isEdit" @click="edit(scope.row)" icon="el-icon-edit" type="text" size="mini">编辑</el-button>-->
+            <el-button
+              size="mini"
+              type="text"
+              icon="el-icon-download"
+              @click="handleDownload(scope.row)"
+            >{{ $t('下载') }}</el-button>
+            <el-button
+              size="mini"
+              type="text"
+              icon="el-icon-delete"
+              @click="handleDeleteDoc(scope.row)"
+              v-hasPermi="['training:trainingrecords:file']"
+            >{{ $t('删除') }}</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      <el-dialog  :close-on-click-modal="false" v-dialogDrag :title="pdf.title" :visible.sync="pdf.open" width="1300px" append-to-body>
+        <div style="margin-top: -60px;float: right;margin-right: 40px;">
+          <el-button size="mini" type="text" @click="openPdf">{{$t('新页面打开PDF')}}</el-button></div>
+        <div style="margin-top: -30px">
+          <iframe :src="pdf.pdfUrl" frameborder="0" width="100%" height="700px"></iframe>
+        </div>
+      </el-dialog>
+
+      <div slot="footer" class="dialog-footer">
+        <!--        <el-button type="primary" @click="submitFileForm">{{ $t('确 定') }}</el-button>-->
+        <el-button @click="doc.open = false">{{ $t('返 回') }}</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listTsnew, getTsnew, delTsnew, addTsnew, updateTsnew, exportTsnew, importTemplate} from "@/api/training/bccnew/tsnew";
+import { treeselect } from "@/api/system/dept";
+import { getToken } from "@/utils/auth";
+import Treeselect from "@riophae/vue-treeselect";
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
+import {
+  addTnNew,
+  delTnNew,
+  exportTnNew,
+  getTnNew,
+  listStaff,
+  listTnNew,
+  updateTnNew
+} from "@/api/training/newstaff/tnNew";
+import {allFileList, delCommonfile} from "@/api/common/commonfile";
+
+export default {
+  name: "Tsnew",
+  components: { Treeselect },
+  data() {
+    return {
+      // 遮罩层
+      loading: true,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: false,
+      // 总条数
+      total: 0,
+      // 新员工培训表格数据
+      tnNewList: [],
+      // 弹出层标题
+      title: "",
+      // 部门树选项
+      deptOptions: undefined,
+      clientHeight:300,
+      // 培训状态字典
+      planStatusOptions: [],
+      // 培训类型 1-新员工 2-转岗字典
+      planTypeOptions: [],
+      userOption:[],
+      // 是否显示弹出层
+      open: false,
+      // 用户导入参数
+      upload: {
+        // 是否显示弹出层(用户导入)
+        open: false,
+        // 弹出层标题(用户导入)
+        title: "",
+        // 是否禁用上传
+        isUploading: false,
+        // 是否更新已经存在的用户数据
+        updateSupport: 0,
+        // 设置上传的请求头部
+        headers: { Authorization: "Bearer " + getToken() },
+        // 上传的地址
+        url: process.env.VUE_APP_BASE_API + "/newstaff/tnNew/importData"
+      },
+      // 报告附件参数
+      doc: {
+        file: "",
+        // 是否显示弹出层(报告附件)
+        open: false,
+        // 弹出层标题(报告附件)
+        title: "附件",
+        // 是否禁用上传
+        isUploading: false,
+        // 是否更新已经存在的用户数据
+        updateSupport: 0,
+        // 报告附件上传位置编号
+        ids: 0,
+        // 设置上传的请求头部
+        headers: { Authorization: "Bearer " + getToken() },
+        // 上传的地址
+        url: process.env.VUE_APP_BASE_API + "/common/commonfile/uploadFile",
+        commonfileList: null,
+        queryParams: {
+          pId: null,
+          pType: 'traning'
+        },
+        pType: 'traning',
+        pId: null,
+        form: {}
+      },
+      pdf : {
+        title: '',
+        pdfUrl: '',
+        numPages: null,
+        open: false,
+        pageNum: 1,
+        pageTotalNum: 1,
+        loadedRatio: 0,
+      },
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 20,
+        name: null,
+        planStatus: null,
+        startdate: null,
+        enddate: null,
+        planType: null,
+      },
+      // 表单参数
+      form: {},
+      // 表单校验
+      rules: {
+      }
+    };
+  },
+  watch: {
+    // 根据名称筛选部门树
+    deptName(val) {
+      this.$refs.tree.filter(val);
+    }
+  },
+  created() {
+    //设置表格高度对应屏幕高度
+    this.$nextTick(() => {
+      this.clientHeight = document.body.clientHeight -250
+    })
+    this.getList();
+    this.getTreeselect();
+    this.getDicts("training_newstaff_status").then(response => {
+      this.planStatusOptions = response.data;
+    });
+    this.getDicts("training_newstaff_type").then(response => {
+      this.planTypeOptions = response.data;
+    });
+    listStaff(this.queryParams).then(response => {
+      this.userOption = response.data;
+    });
+  },
+  methods: {
+    /** 查询新员工培训列表 */
+    getList() {
+      this.loading = true;
+      listTnNew(this.queryParams).then(response => {
+        this.tnNewList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    /** 查询部门下拉树结构 */
+    getTreeselect() {
+      treeselect().then(response => {
+        this.deptOptions = response.data;
+      });
+    },
+    // 培训状态字典翻译
+    planStatusFormat(row, column) {
+      return this.selectDictLabel(this.planStatusOptions, row.planStatus);
+    },
+    // 培训类型 1-新员工 2-转岗字典翻译
+    planTypeFormat(row, column) {
+      return this.selectDictLabel(this.planTypeOptions, row.planType);
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        newId: null,
+        staffId: null,
+        name: null,
+        delFlag: null,
+        createrCode: null,
+        createdate: null,
+        updaterCode: null,
+        updatedate: null,
+        deptId: null,
+        planStatus: 0,
+        planYear: null,
+        startdate: null,
+        enddate: null,
+        mentorStaffId: null,
+        planType: null,
+        remarks: null
+      };
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.newId)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    planList(row){
+      const newId = row.newId
+      this.$router.push("/training/newstaff/planList/" + newId);
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "添加新员工培训";
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      const newId = row.newId || this.ids
+      getTsnew(newId).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改新员工培训";
+      });
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.newId != null) {
+            updateTsnew(this.form).then(response => {
+              this.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addTsnew(this.form).then(response => {
+              this.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const newIds = row.newId || this.ids;
+      this.$confirm('是否确认删除?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(function() {
+        return delTsnew(newIds);
+      }).then(() => {
+        this.getList();
+        this.msgSuccess("删除成功");
+      })
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      const queryParams = this.queryParams;
+      this.$confirm('是否确认导出所有新员工培训数据项?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(function() {
+        return exportTsnew(queryParams);
+      }).then(response => {
+        this.download(response.msg);
+      })
+    },
+    /** 导入按钮操作 */
+    handleImport() {
+      this.upload.title = "用户导入";
+      this.upload.open = true;
+    },
+    /** 下载模板操作 */
+    importTemplate() {
+      importTemplate().then(response => {
+        this.download(response.msg);
+      });
+    },
+    // 文件上传中处理
+    handleFileUploadProgress(event, file, fileList) {
+      this.upload.isUploading = true;
+    },
+    // 文件上传成功处理
+    handleFileSuccess(response, file, fileList) {
+      this.upload.open = false;
+      this.upload.isUploading = false;
+      this.$refs.upload.clearFiles();
+      this.$alert(response.msg, "导入结果", { dangerouslyUseHTMLString: true });
+      this.getList();
+    },
+    // 提交上传文件
+    submitFileForm() {
+      this.$refs.upload.submit();
+    },
+    /** 报告附件按钮操作 */
+    handleDoc(row , fileType) {
+      var workType = "";
+      if (fileType === "byxworklicense-boiler"){
+        workType = this.$t('裂解(裂化)');
+      }else if (fileType === "byxworklicense-compression"){
+        workType = this.$t('压力容器');
+      }else if (fileType === "byxworklicense-separation"){
+        workType = this.$t('压力管道');
+      }else if (fileType === "byxworklicense-pguaeu"){
+        workType = '';
+      }
+      this.doc.pType = fileType
+      this.doc.queryParams.pType = fileType
+      this.doc.id = row.id;
+      this.doc.title = this.$t('附件') ;
+      this.doc.open = true;
+      this.doc.queryParams.pId = row.newId
+      this.doc.pId = row.newId
+      this.getFileList()
+      this.$nextTick(() => {
+        this.$refs.doc.clearFiles()
+      })
+    },
+    getFileList (){
+      allFileList(this.doc.queryParams).then(response => {
+        response.forEach(element => {
+          element["isEdit"] = false
+        });
+        response.forEach(element => {
+          element["isAdd"] = false
+        });
+        this.doc.commonfileList = response;
+      });
+    },
+    //附件上传中处理
+    handleFileDocProgress(event, file, fileList) {
+      this.doc.file = file;
+      this.doc.isUploading = true;
+    },
+    //附件上传成功处理
+    handleFileDocSuccess(response, file, fileList) {
+      this.doc.isUploading = false;
+      this.$alert(response.msg, this.$t('导入结果'), { dangerouslyUseHTMLString: true });
+      this.getFileList()
+    },
+    // 文件下载处理
+    handleDownload(row) {
+      var name = row.fileName;
+      var url = row.fileUrl;
+      var suffix = url.substring(url.lastIndexOf("."), url.length);
+      const a = document.createElement('a')
+      a.setAttribute('download', name)
+      a.setAttribute('target', '_blank')
+      a.setAttribute('href', process.env.VUE_APP_BASE_API + url)
+      a.click()
+    },
+    openPdf(){
+      window.open(this.pdf.pdfUrl);//path是文件的全路径地址
+    },
+    handleSee (row){
+      // window.open(process.env.VUE_APP_BASE_API +'/pdf/web/viewer.html?file=' + process.env.VUE_APP_BASE_API + row.fileUrl);//path是文件的全路径地址
+      this.pdf.open =true
+      this.pdf.title = row.fileName
+      this.pdf.pdfUrl = process.env.VUE_APP_BASE_API +'/pdf/web/viewer.html?file=' + process.env.VUE_APP_BASE_API + row.fileUrl
+    },
+    /** 删除按钮操作 */
+    handleDeleteDoc(row) {
+      const ids = row.id || this.ids;
+      this.$confirm(this.$t('是否确认删除?'), this.$t('警告'), {
+        confirmButtonText: this.$t('确定'),
+        cancelButtonText: this.$t('取消'),
+        type: "warning"
+      }).then(function() {
+        return delCommonfile(ids);
+      }).then(() => {
+        this.getFileList()
+        this.msgSuccess(this.$t('删除成功'));
+      })
+    },
+  }
+};
+</script>

+ 467 - 0
ui/src/views/training/elearn/answer/index.vue

@@ -0,0 +1,467 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="是否正确答案" prop="isRight">
+        <el-input
+          v-model="queryParams.isRight"
+          placeholder="请输入是否正确答案"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="照片" prop="image">
+        <el-input
+          v-model="queryParams.image"
+          placeholder="请输入照片"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="解析" prop="analysis">
+        <el-input
+          v-model="queryParams.analysis"
+          placeholder="请输入解析"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="备注" prop="remarks">
+        <el-input
+          v-model="queryParams.remarks"
+          placeholder="请输入备注"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['elearn:answer:add']"
+        >新增</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="single"
+          @click="handleUpdate"
+          v-hasPermi="['elearn:answer:edit']"
+        >修改</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['elearn:answer:remove']"
+        >删除</el-button>
+      </el-col>
+        <el-col :span="1.5">
+            <el-button
+                    type="info"
+                    icon="el-icon-upload2"
+                    size="mini"
+                    @click="handleImport"
+                    v-hasPermi="['elearn:answer:edit']"
+            >导入</el-button>
+        </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          icon="el-icon-download"
+          size="mini"
+          @click="handleExport"
+          v-hasPermi="['elearn:answer:export']"
+        >导出</el-button>
+      </el-col>
+	  <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading" :data="answerList" @selection-change="handleSelectionChange" :height="clientHeight" border>
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="id" align="center" prop="answerId" :show-overflow-tooltip="true"/>
+      <el-table-column label="题目id" align="center" prop="quId" :show-overflow-tooltip="true"/>
+      <el-table-column label="是否正确答案" align="center" prop="isRight" :show-overflow-tooltip="true"/>
+      <el-table-column label="答案内容" align="center" prop="content" :show-overflow-tooltip="true"/>
+      <el-table-column label="照片" align="center" prop="image" :show-overflow-tooltip="true"/>
+      <el-table-column label="解析" align="center" prop="analysis" :show-overflow-tooltip="true"/>
+      <el-table-column label="创建人" align="center" prop="createrCode" :show-overflow-tooltip="true"/>
+      <el-table-column label="创建时间" align="center" prop="createdate" width="100">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.createdate, '{y}-{m}-{d}') }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="更新人" align="center" prop="updaterCode" :show-overflow-tooltip="true"/>
+      <el-table-column label="更新日期" align="center" prop="updatedate" width="100">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.updatedate, '{y}-{m}-{d}') }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="所属部门" align="center" prop="deptId" :show-overflow-tooltip="true"/>
+      <el-table-column label="备注" align="center" prop="remarks" :show-overflow-tooltip="true"/>
+      <el-table-column label="操作" align="center" fixed="right" width="120" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleUpdate(scope.row)"
+            v-hasPermi="['elearn:answer:edit']"
+          >修改</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['elearn:answer:remove']"
+          >删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 添加或修改试题选项答案对话框 -->
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="题目id" prop="quId">
+          <el-input v-model="form.quId" placeholder="请输入题目id" />
+        </el-form-item>
+        <el-form-item label="是否正确答案" prop="isRight">
+          <el-input v-model="form.isRight" placeholder="请输入是否正确答案" />
+        </el-form-item>
+        <el-form-item label="答案内容">
+          <editor v-model="form.content" :min-height="192"/>
+        </el-form-item>
+        <el-form-item label="照片" prop="image">
+          <el-input v-model="form.image" placeholder="请输入照片" />
+        </el-form-item>
+        <el-form-item label="解析" prop="analysis">
+          <el-input v-model="form.analysis" placeholder="请输入解析" />
+        </el-form-item>
+        <el-form-item label="删除" prop="delFlag">
+          <el-input v-model="form.delFlag" placeholder="请输入删除" />
+        </el-form-item>
+        <el-form-item label="创建人" prop="createrCode">
+          <el-input v-model="form.createrCode" placeholder="请输入创建人" />
+        </el-form-item>
+        <el-form-item label="创建时间" prop="createdate">
+          <el-date-picker clearable size="small" style="width: 200px"
+            v-model="form.createdate"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="选择创建时间">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="更新人" prop="updaterCode">
+          <el-input v-model="form.updaterCode" placeholder="请输入更新人" />
+        </el-form-item>
+        <el-form-item label="更新日期" prop="updatedate">
+          <el-date-picker clearable size="small" style="width: 200px"
+            v-model="form.updatedate"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="选择更新日期">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="所属部门" prop="deptId">
+          <el-input v-model="form.deptId" placeholder="请输入所属部门" />
+        </el-form-item>
+        <el-form-item label="备注" prop="remarks">
+          <el-input v-model="form.remarks" placeholder="请输入备注" />
+        </el-form-item>
+          <el-form-item label="归属部门" prop="deptId">
+              <treeselect v-model="form.deptId" :options="deptOptions" :show-count="true" placeholder="请选择归属部门" />
+          </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
+      <!-- 用户导入对话框 -->
+      <el-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body>
+          <el-upload
+                  ref="upload"
+                  :limit="1"
+                  accept=".xlsx, .xls"
+                  :headers="upload.headers"
+                  :action="upload.url + '?updateSupport=' + upload.updateSupport"
+                  :disabled="upload.isUploading"
+                  :on-progress="handleFileUploadProgress"
+                  :on-success="handleFileSuccess"
+                  :auto-upload="false"
+                  drag
+          >
+              <i class="el-icon-upload"></i>
+              <div class="el-upload__text">
+                  将文件拖到此处,或
+                  <em>点击上传</em>
+              </div>
+              <div class="el-upload__tip" slot="tip">
+                  <el-checkbox v-model="upload.updateSupport" />是否更新已经存在的用户数据
+                  <el-link type="info" style="font-size:12px" @click="importTemplate">下载模板</el-link>
+              </div>
+              <div class="el-upload__tip" style="color:red" slot="tip">提示:仅允许导入“xls”或“xlsx”格式文件!</div>
+          </el-upload>
+          <div slot="footer" class="dialog-footer">
+              <el-button type="primary" @click="submitFileForm">确 定</el-button>
+              <el-button @click="upload.open = false">取 消</el-button>
+          </div>
+      </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listAnswer, getAnswer, delAnswer, addAnswer, updateAnswer, exportAnswer, importTemplate} from "@/api/training/elearn/answer";
+import { treeselect } from "@/api/system/dept";
+import { getToken } from "@/utils/auth";
+import Treeselect from "@riophae/vue-treeselect";
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
+import Editor from '@/components/Editor';
+
+export default {
+  name: "Answer",
+  components: { Treeselect },
+  // components: { Editor },
+  data() {
+    return {
+      // 遮罩层
+      loading: true,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: false,
+      // 总条数
+      total: 0,
+      // 试题选项答案表格数据
+      answerList: [],
+      // 弹出层标题
+      title: "",
+      // 部门树选项
+      deptOptions: undefined,
+      clientHeight:300,
+      // 是否显示弹出层
+      open: false,
+        // 用户导入参数
+        upload: {
+            // 是否显示弹出层(用户导入)
+            open: false,
+            // 弹出层标题(用户导入)
+            title: "",
+            // 是否禁用上传
+            isUploading: false,
+            // 是否更新已经存在的用户数据
+            updateSupport: 0,
+            // 设置上传的请求头部
+            headers: { Authorization: "Bearer " + getToken() },
+            // 上传的地址
+            url: process.env.VUE_APP_BASE_API + "/elearn/answer/importData"
+        },
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 20,
+        isRight: null,
+        content: null,
+        image: null,
+        analysis: null,
+        remarks: null
+      },
+      // 表单参数
+      form: {},
+      // 表单校验
+      rules: {
+      }
+    };
+  },
+  watch: {
+        // 根据名称筛选部门树
+        deptName(val) {
+            this.$refs.tree.filter(val);
+        }
+   },
+  created() {
+      //设置表格高度对应屏幕高度
+      this.$nextTick(() => {
+          this.clientHeight = document.body.clientHeight -250
+      })
+    this.getList();
+    this.getTreeselect();
+  },
+  methods: {
+    /** 查询试题选项答案列表 */
+    getList() {
+      this.loading = true;
+      listAnswer(this.queryParams).then(response => {
+        this.answerList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+     /** 查询部门下拉树结构 */
+     getTreeselect() {
+          treeselect().then(response => {
+              this.deptOptions = response.data;
+          });
+     },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        answerId: null,
+        quId: null,
+        isRight: null,
+        content: null,
+        image: null,
+        analysis: null,
+        delFlag: null,
+        createrCode: null,
+        createdate: null,
+        updaterCode: null,
+        updatedate: null,
+        deptId: null,
+        remarks: null
+      };
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.answerId)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "添加试题选项答案";
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      const answerId = row.answerId || this.ids
+      getAnswer(answerId).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改试题选项答案";
+      });
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.answerId != null) {
+            updateAnswer(this.form).then(response => {
+              this.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addAnswer(this.form).then(response => {
+              this.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const answerIds = row.answerId || this.ids;
+      this.$confirm('是否确认删除?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return delAnswer(answerIds);
+        }).then(() => {
+          this.getList();
+          this.msgSuccess("删除成功");
+        })
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      const queryParams = this.queryParams;
+      this.$confirm('是否确认导出所有试题选项答案数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return exportAnswer(queryParams);
+        }).then(response => {
+          this.download(response.msg);
+        })
+    },
+      /** 导入按钮操作 */
+      handleImport() {
+          this.upload.title = "用户导入";
+          this.upload.open = true;
+      },
+      /** 下载模板操作 */
+      importTemplate() {
+          importTemplate().then(response => {
+              this.download(response.msg);
+          });
+      },
+      // 文件上传中处理
+      handleFileUploadProgress(event, file, fileList) {
+          this.upload.isUploading = true;
+      },
+      // 文件上传成功处理
+      handleFileSuccess(response, file, fileList) {
+          this.upload.open = false;
+          this.upload.isUploading = false;
+          this.$refs.upload.clearFiles();
+          this.$alert(response.msg, "导入结果", { dangerouslyUseHTMLString: true });
+          this.getList();
+      },
+      // 提交上传文件
+      submitFileForm() {
+          this.$refs.upload.submit();
+      }
+  }
+};
+</script>

+ 658 - 0
ui/src/views/training/elearn/exam/index.vue

@@ -0,0 +1,658 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="考试名称" prop="title">
+        <el-input
+          v-model="queryParams.title"
+          placeholder="请输入考试名称"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+<!--      <el-form-item label="1公开2部门3定员" prop="openType">-->
+<!--        <el-select v-model="queryParams.openType" placeholder="请选择1公开2部门3定员" clearable size="small">-->
+<!--          <el-option label="请选择字典生成" value="" />-->
+<!--        </el-select>-->
+<!--      </el-form-item>-->
+
+      <el-form-item>
+        <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['elearn:exam:add']"
+        >新增</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="single"
+          @click="handleUpdate"
+          v-hasPermi="['elearn:exam:edit']"
+        >修改</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['elearn:exam:remove']"
+        >删除</el-button>
+      </el-col>
+
+	  <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading" :data="examList" @selection-change="handleSelectionChange" :height="clientHeight" border>
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="考试名称" align="center" prop="title" :show-overflow-tooltip="true"/>
+      <el-table-column label="考试描述" align="center" prop="content" :show-overflow-tooltip="true"/>
+<!--      <el-table-column label="考试类型" align="center" prop="openType" :show-overflow-tooltip="true"/>-->
+<!--      <el-table-column label="考试状态" align="center" prop="state" :show-overflow-tooltip="true"/>-->
+      <el-table-column label="总分" align="center" prop="totalScore" :show-overflow-tooltip="true"/>
+      <el-table-column label="及格分" align="center" prop="qualifyScore" :show-overflow-tooltip="true"/>
+      <el-table-column label="创建时间" align="center" prop="createdate" width="100">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.createdate, '{y}-{m}-{d}') }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" fixed="right" width="120" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleUpdate(scope.row)"
+            v-hasPermi="['elearn:exam:edit']"
+          >修改</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['elearn:exam:remove']"
+          >删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 添加或修改考试对话框 -->
+    <el-dialog :title="title" :visible.sync="open" width="1400px" append-to-body>
+      <h3>组卷信息</h3>
+      <el-card style="margin-top: 20px">
+
+        <div style="float: right; font-weight: bold; color: #ff0000">试卷总分:{{ form.totalScore }}分</div>
+
+        <div>
+
+          <el-button class="filter-item" size="small" type="primary" icon="el-icon-plus" @click="handleAddItem">
+            添加题库
+          </el-button>
+
+          <el-table
+            :data="repoList"
+            :border="false"
+            empty-text="请点击上面的`添加题库`进行设置"
+            style="width: 100%; margin-top: 15px"
+          >
+            <el-table-column
+              label="题库"
+              width="200"
+            >
+              <template v-slot="scope">
+                <repo-select
+                  v-model="scope.row.repoId"
+                  :multi="false"
+                  :excludes="excludes"
+                  @change="repoChange($event, scope.row)" />
+              </template>
+
+            </el-table-column>
+            <el-table-column
+              label="单选数量"
+              align="center"
+            >
+
+              <template v-slot="scope">
+                <el-input-number v-model="scope.row.radioCount" :min="0" :max="scope.row.totalRadio" :controls="false" style="width: 100px" /> / {{ scope.row.totalRadio }}
+              </template>
+
+            </el-table-column>
+
+            <el-table-column
+              label="单选分数"
+              align="center"
+            >
+              <template v-slot="scope">
+                <el-input-number v-model="scope.row.radioScore" :min="0" :controls="false" style="width: 100%" />
+              </template>
+            </el-table-column>
+
+            <el-table-column
+              label="多选数量"
+              align="center"
+            >
+
+              <template v-slot="scope">
+                <el-input-number v-model="scope.row.multiCount" :min="0" :max="scope.row.totalMulti" :controls="false" style="width: 100px" /> / {{ scope.row.totalMulti }}
+              </template>
+
+            </el-table-column>
+
+            <el-table-column
+              label="多选分数"
+              align="center"
+            >
+              <template v-slot="scope">
+                <el-input-number v-model="scope.row.multiScore" :min="0" :controls="false" style="width: 100%" />
+              </template>
+            </el-table-column>
+
+            <el-table-column
+              label="判断题数量"
+              align="center"
+            >
+
+              <template v-slot="scope">
+                <el-input-number v-model="scope.row.judgeCount" :min="0" :max="scope.row.totalJudge" :controls="false" style="width: 100px" />  / {{ scope.row.totalJudge }}
+              </template>
+
+            </el-table-column>
+
+            <el-table-column
+              label="判断题分数"
+              align="center"
+            >
+              <template v-slot="scope">
+                <el-input-number v-model="scope.row.judgeScore" :min="0" :controls="false" style="width: 100%" />
+              </template>
+            </el-table-column>
+
+            <el-table-column
+              label="删除"
+              align="center"
+              width="80px"
+            >
+              <template v-slot="scope">
+                <el-button type="danger" icon="el-icon-delete" circle @click="removeItem(scope.$index)" />
+              </template>
+            </el-table-column>
+
+          </el-table>
+
+        </div>
+
+      </el-card>
+
+      <h3>考试配置</h3>
+      <el-card style="margin-top: 20px">
+
+        <el-form ref="form" :model="form" :rules="rules" label-position="left" label-width="120px">
+
+          <el-form-item label="考试名称" prop="title">
+            <el-input v-model="form.title" />
+          </el-form-item>
+
+          <el-form-item label="考试描述" prop="content">
+            <el-input v-model="form.content" type="textarea" />
+          </el-form-item>
+
+          <el-form-item label="总分数" prop="totalScore">
+            <el-input-number :value="form.totalScore" disabled />
+          </el-form-item>
+
+          <el-form-item label="及格分" prop="qualifyScore">
+            <el-input-number v-model="form.qualifyScore" :max="form.totalScore" />
+          </el-form-item>
+
+          <el-form-item label="考试时长(分钟)" prop="totalTime">
+            <el-input-number v-model="form.totalTime" />
+          </el-form-item>
+
+<!--          <el-form-item label="是否限时">
+            <el-checkbox :true-label=1 :false-label=0  v-model="form.timeLimit" />
+          </el-form-item>
+
+          <el-form-item v-if="form.timeLimit == 1" label="考试时间" prop="totalTime">
+
+            <el-date-picker
+              v-model="dateValues"
+              format="yyyy-MM-dd"
+              value-format="yyyy-MM-dd"
+              type="daterange"
+              range-separator="至"
+              start-placeholder="开始时间"
+              end-placeholder="结束时间"
+            />
+
+          </el-form-item>-->
+
+        </el-form>
+
+      </el-card>
+
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="handleSave">保 存</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>-->
+<!--      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="考试名称" prop="title">
+          <el-input v-model="form.title" placeholder="请输入考试名称" />
+        </el-form-item>
+        <el-form-item label="考试内容">
+          <editor v-model="form.content" :min-height="192"/>
+        </el-form-item>
+        <el-form-item label="1公开2部门3定员" prop="openType">
+          <el-select v-model="form.openType" placeholder="请选择1公开2部门3定员">
+            <el-option label="请选择字典生成" value="" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="考试状态" prop="state">
+          <el-input v-model="form.state" placeholder="请输入考试状态" />
+        </el-form-item>
+        <el-form-item label="是否限时" prop="timeLimit">
+          <el-input v-model="form.timeLimit" placeholder="请输入是否限时" />
+        </el-form-item>
+        <el-form-item label="开始时间" prop="examStartTime">
+          <el-date-picker clearable size="small" style="width: 200px"
+            v-model="form.examStartTime"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="选择开始时间">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="结束时间" prop="examEndTime">
+          <el-date-picker clearable size="small" style="width: 200px"
+            v-model="form.examEndTime"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="选择结束时间">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="总分" prop="totalScore">
+          <el-input v-model="form.totalScore" placeholder="请输入总分" />
+        </el-form-item>
+        <el-form-item label="总时长" prop="totalTime">
+          <el-input v-model="form.totalTime" placeholder="请输入总时长" />
+        </el-form-item>
+        <el-form-item label="及格分" prop="qualifyScore">
+          <el-input v-model="form.qualifyScore" placeholder="请输入及格分" />
+        </el-form-item>
+        <el-form-item label="删除" prop="delFlag">
+          <el-input v-model="form.delFlag" placeholder="请输入删除" />
+        </el-form-item>
+        <el-form-item label="创建人" prop="createrCode">
+          <el-input v-model="form.createrCode" placeholder="请输入创建人" />
+        </el-form-item>
+        <el-form-item label="创建时间" prop="createdate">
+          <el-date-picker clearable size="small" style="width: 200px"
+            v-model="form.createdate"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="选择创建时间">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="更新人" prop="updaterCode">
+          <el-input v-model="form.updaterCode" placeholder="请输入更新人" />
+        </el-form-item>
+        <el-form-item label="更新日期" prop="updatedate">
+          <el-date-picker clearable size="small" style="width: 200px"
+            v-model="form.updatedate"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="选择更新日期">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="所属部门" prop="deptId">
+          <el-input v-model="form.deptId" placeholder="请输入所属部门" />
+        </el-form-item>
+        <el-form-item label="备注" prop="remarks">
+          <el-input v-model="form.remarks" placeholder="请输入备注" />
+        </el-form-item>
+          <el-form-item label="归属部门" prop="deptId">
+              <treeselect v-model="form.deptId" :options="deptOptions" :show-count="true" placeholder="请选择归属部门" />
+          </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>-->
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listExam, getExam, delExam, addExam, updateExam, exportExam, importTemplate} from "@/api/training/elearn/exam";
+import { treeselect } from "@/api/system/dept";
+import { getToken } from "@/utils/auth";
+import Treeselect from "@riophae/vue-treeselect";
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
+import RepoSelect from '@/components/RepoSelect'
+
+export default {
+  name: "Exam",
+  components: { Treeselect,RepoSelect },
+  // components: { Editor },
+  data() {
+    return {
+      // 遮罩层
+      loading: true,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: false,
+      // 总条数
+      total: 0,
+      // 考试表格数据
+      examList: [],
+      // 已选择的题库
+      excludes: [],
+      // 弹出层标题
+      title: "",
+      // 部门树选项
+      deptOptions: undefined,
+      clientHeight:300,
+      // 是否显示弹出层
+      open: false,
+        // 用户导入参数
+        upload: {
+            // 是否显示弹出层(用户导入)
+            open: false,
+            // 弹出层标题(用户导入)
+            title: "",
+            // 是否禁用上传
+            isUploading: false,
+            // 是否更新已经存在的用户数据
+            updateSupport: 0,
+            // 设置上传的请求头部
+            headers: { Authorization: "Bearer " + getToken() },
+            // 上传的地址
+            url: process.env.VUE_APP_BASE_API + "/elearn/exam/importData"
+        },
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 20,
+        title: null,
+        content: null,
+        openType: null,
+        state: null,
+        timeLimit: null,
+        examStartTime: null,
+        examEndTime: null,
+        totalScore: null,
+        totalTime: null,
+        qualifyScore: null,
+        createrCode: null,
+        createdate: null,
+        updaterCode: null,
+        updatedate: null,
+        deptId: null,
+        remarks: null
+      },
+      // 题库
+      repoList: [],
+      // 表单参数
+      form: {},
+      // 表单校验
+      rules: {
+      }
+    };
+  },
+  watch: {
+
+    filterText(val) {
+      this.$refs.tree.filter(val)
+    },
+
+    dateValues: {
+
+      handler() {
+        this.form.examStartTime = this.dateValues[0]
+        this.form.examEndTime = this.dateValues[1]
+      }
+    },
+
+    // 题库变换
+    repoList: {
+
+      handler(val) {
+        let totalScore = 0
+        this.excludes = []
+        for (let i = 0; i<val.length; i++) {
+          const item = val[i]
+          if (item.radioCount > 0 && item.radioScore>0) {
+            totalScore += item.radioCount * item.radioScore
+          }
+
+          if (item.multiCount>0 && item.multiScore>0) {
+            totalScore += item.multiCount * item.multiScore
+          }
+
+          if (item.judgeCount>0 && item.judgeScore>0) {
+            totalScore += item.judgeCount * item.judgeScore
+          }
+          this.excludes.push(item.id)
+        }
+
+        // 赋值
+        this.form.totalScore = totalScore
+        this.form.repoList = val
+        this.$forceUpdate()
+      },
+      deep: true
+    }
+
+  },
+  created() {
+      //设置表格高度对应屏幕高度
+      this.$nextTick(() => {
+          this.clientHeight = document.body.clientHeight -250
+      })
+    this.getList();
+    this.getTreeselect();
+  },
+  methods: {
+    /** 查询考试列表 */
+    getList() {
+      this.loading = true;
+      listExam(this.queryParams).then(response => {
+        this.examList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+     /** 查询部门下拉树结构 */
+     getTreeselect() {
+          treeselect().then(response => {
+              this.deptOptions = response.data;
+          });
+     },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        examId: null,
+        title: null,
+        content: null,
+        openType: null,
+        state: null,
+        timeLimit: null,
+        examStartTime: null,
+        examEndTime: null,
+        totalScore: null,
+        totalTime: null,
+        qualifyScore: null,
+        delFlag: null,
+        createrCode: null,
+        createdate: null,
+        updaterCode: null,
+        updatedate: null,
+        deptId: null,
+        remarks: null,
+        repoList: [],
+      };
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.examId)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.repoList = []
+      this.title = "添加考试";
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      const examId = row.examId || this.ids
+      getExam(examId).then(response => {
+        this.form = response.data;
+        this.repoList = this.form.repoList
+        this.open = true;
+        this.title = "修改考试";
+      });
+    },
+    /** 提交按钮 */
+    handleSave() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.examId != null) {
+            updateExam(this.form).then(response => {
+              this.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addExam(this.form).then(response => {
+              this.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const examIds = row.examId || this.ids;
+      this.$confirm('是否确认删除?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return delExam(examIds);
+        }).then(() => {
+          this.getList();
+          this.msgSuccess("删除成功");
+        })
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      const queryParams = this.queryParams;
+      this.$confirm('是否确认导出所有考试数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return exportExam(queryParams);
+        }).then(response => {
+          this.download(response.msg);
+        })
+    },
+      /** 导入按钮操作 */
+      handleImport() {
+          this.upload.title = "用户导入";
+          this.upload.open = true;
+      },
+      /** 下载模板操作 */
+      importTemplate() {
+          importTemplate().then(response => {
+              this.download(response.msg);
+          });
+      },
+      // 文件上传中处理
+      handleFileUploadProgress(event, file, fileList) {
+          this.upload.isUploading = true;
+      },
+      // 文件上传成功处理
+      handleFileSuccess(response, file, fileList) {
+          this.upload.open = false;
+          this.upload.isUploading = false;
+          this.$refs.upload.clearFiles();
+          this.$alert(response.msg, "导入结果", { dangerouslyUseHTMLString: true });
+          this.getList();
+      },
+      // 提交上传文件
+      submitFileForm() {
+          this.$refs.upload.submit();
+      },
+    // 添加子项
+    handleAddItem() {
+      this.repoList.push({ id: '', rowId: new Date().getTime(), radioCount: 0, radioScore: 0, multiCount: 0, multiScore: 0, judgeCount: 0, judgeScore: 0, saqCount: 0, saqScore: 0 })
+    },
+
+    removeItem(index) {
+      this.repoList.splice(index, 1)
+    },
+    repoChange(e, row) {
+      // 赋值ID
+      row.id = e.id
+
+      if (e != null) {
+        row.totalRadio = e.radioCount
+        row.totalMulti = e.multiCount
+        row.totalJudge = e.judgeCount
+      } else {
+        row.totalRadio = 0
+        row.totalMulti = 0
+        row.totalJudge = 0
+      }
+    }
+  }
+};
+</script>

+ 3 - 0
ui/src/views/training/elearn/index.vue

@@ -0,0 +1,3 @@
+<template >
+  <router-view />
+</template>

+ 675 - 0
ui/src/views/training/elearn/paper/index.vue

@@ -0,0 +1,675 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="用户id" prop="userId">
+        <el-input
+          v-model="queryParams.userId"
+          placeholder="请输入用户id"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="员工编号" prop="staffId">
+        <el-input
+          v-model="queryParams.staffId"
+          placeholder="请输入员工编号"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="考试id" prop="examId">
+        <el-input
+          v-model="queryParams.examId"
+          placeholder="请输入考试id"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="考试标题" prop="title">
+        <el-input
+          v-model="queryParams.title"
+          placeholder="请输入考试标题"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="考试时长" prop="totalTime">
+        <el-input
+          v-model="queryParams.totalTime"
+          placeholder="请输入考试时长"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="用户时长" prop="userTime">
+        <el-input
+          v-model="queryParams.userTime"
+          placeholder="请输入用户时长"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="试卷总分" prop="totalScore">
+        <el-input
+          v-model="queryParams.totalScore"
+          placeholder="请输入试卷总分"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="及格分" prop="qualifyScore">
+        <el-input
+          v-model="queryParams.qualifyScore"
+          placeholder="请输入及格分"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="客观分" prop="objScore">
+        <el-input
+          v-model="queryParams.objScore"
+          placeholder="请输入客观分"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="主观分" prop="subjScore">
+        <el-input
+          v-model="queryParams.subjScore"
+          placeholder="请输入主观分"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="用户得分" prop="userScore">
+        <el-input
+          v-model="queryParams.userScore"
+          placeholder="请输入用户得分"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="是否包含简答题" prop="hasSaq">
+        <el-input
+          v-model="queryParams.hasSaq"
+          placeholder="请输入是否包含简答题"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="试卷状态" prop="state">
+        <el-input
+          v-model="queryParams.state"
+          placeholder="请输入试卷状态"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="截止时间" prop="limitTime">
+        <el-date-picker clearable size="small" style="width: 200px"
+          v-model="queryParams.limitTime"
+          type="date"
+          value-format="yyyy-MM-dd"
+          placeholder="选择截止时间">
+        </el-date-picker>
+      </el-form-item>
+      <el-form-item label="创建人" prop="createrCode">
+        <el-input
+          v-model="queryParams.createrCode"
+          placeholder="请输入创建人"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="创建时间" prop="createdate">
+        <el-date-picker clearable size="small" style="width: 200px"
+          v-model="queryParams.createdate"
+          type="date"
+          value-format="yyyy-MM-dd"
+          placeholder="选择创建时间">
+        </el-date-picker>
+      </el-form-item>
+      <el-form-item label="更新人" prop="updaterCode">
+        <el-input
+          v-model="queryParams.updaterCode"
+          placeholder="请输入更新人"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="更新日期" prop="updatedate">
+        <el-date-picker clearable size="small" style="width: 200px"
+          v-model="queryParams.updatedate"
+          type="date"
+          value-format="yyyy-MM-dd"
+          placeholder="选择更新日期">
+        </el-date-picker>
+      </el-form-item>
+      <el-form-item label="所属部门" prop="deptId">
+        <el-input
+          v-model="queryParams.deptId"
+          placeholder="请输入所属部门"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="备注" prop="remarks">
+        <el-input
+          v-model="queryParams.remarks"
+          placeholder="请输入备注"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['elearn:paper:add']"
+        >新增</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="single"
+          @click="handleUpdate"
+          v-hasPermi="['elearn:paper:edit']"
+        >修改</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['elearn:paper:remove']"
+        >删除</el-button>
+      </el-col>
+        <el-col :span="1.5">
+            <el-button
+                    type="info"
+                    icon="el-icon-upload2"
+                    size="mini"
+                    @click="handleImport"
+                    v-hasPermi="['elearn:paper:edit']"
+            >导入</el-button>
+        </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          icon="el-icon-download"
+          size="mini"
+          @click="handleExport"
+          v-hasPermi="['elearn:paper:export']"
+        >导出</el-button>
+      </el-col>
+	  <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading" :data="paperList" @selection-change="handleSelectionChange" :height="clientHeight" border>
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="id" align="center" prop="paperId" :show-overflow-tooltip="true"/>
+      <el-table-column label="用户id" align="center" prop="userId" :show-overflow-tooltip="true"/>
+      <el-table-column label="员工编号" align="center" prop="staffId" :show-overflow-tooltip="true"/>
+      <el-table-column label="考试id" align="center" prop="examId" :show-overflow-tooltip="true"/>
+      <el-table-column label="考试标题" align="center" prop="title" :show-overflow-tooltip="true"/>
+      <el-table-column label="考试时长" align="center" prop="totalTime" :show-overflow-tooltip="true"/>
+      <el-table-column label="用户时长" align="center" prop="userTime" :show-overflow-tooltip="true"/>
+      <el-table-column label="试卷总分" align="center" prop="totalScore" :show-overflow-tooltip="true"/>
+      <el-table-column label="及格分" align="center" prop="qualifyScore" :show-overflow-tooltip="true"/>
+      <el-table-column label="客观分" align="center" prop="objScore" :show-overflow-tooltip="true"/>
+      <el-table-column label="主观分" align="center" prop="subjScore" :show-overflow-tooltip="true"/>
+      <el-table-column label="用户得分" align="center" prop="userScore" :show-overflow-tooltip="true"/>
+      <el-table-column label="是否包含简答题" align="center" prop="hasSaq" :show-overflow-tooltip="true"/>
+      <el-table-column label="试卷状态" align="center" prop="state" :show-overflow-tooltip="true"/>
+      <el-table-column label="截止时间" align="center" prop="limitTime" width="100">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.limitTime, '{y}-{m}-{d}') }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="创建人" align="center" prop="createrCode" :show-overflow-tooltip="true"/>
+      <el-table-column label="创建时间" align="center" prop="createdate" width="100">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.createdate, '{y}-{m}-{d}') }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="更新人" align="center" prop="updaterCode" :show-overflow-tooltip="true"/>
+      <el-table-column label="更新日期" align="center" prop="updatedate" width="100">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.updatedate, '{y}-{m}-{d}') }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="所属部门" align="center" prop="deptId" :show-overflow-tooltip="true"/>
+      <el-table-column label="备注" align="center" prop="remarks" :show-overflow-tooltip="true"/>
+      <el-table-column label="操作" align="center" fixed="right" width="120" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleUpdate(scope.row)"
+            v-hasPermi="['elearn:paper:edit']"
+          >修改</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['elearn:paper:remove']"
+          >删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 添加或修改在线考试对话框 -->
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="用户id" prop="userId">
+          <el-input v-model="form.userId" placeholder="请输入用户id" />
+        </el-form-item>
+        <el-form-item label="员工编号" prop="staffId">
+          <el-input v-model="form.staffId" placeholder="请输入员工编号" />
+        </el-form-item>
+        <el-form-item label="考试id" prop="examId">
+          <el-input v-model="form.examId" placeholder="请输入考试id" />
+        </el-form-item>
+        <el-form-item label="考试标题" prop="title">
+          <el-input v-model="form.title" placeholder="请输入考试标题" />
+        </el-form-item>
+        <el-form-item label="考试时长" prop="totalTime">
+          <el-input v-model="form.totalTime" placeholder="请输入考试时长" />
+        </el-form-item>
+        <el-form-item label="用户时长" prop="userTime">
+          <el-input v-model="form.userTime" placeholder="请输入用户时长" />
+        </el-form-item>
+        <el-form-item label="试卷总分" prop="totalScore">
+          <el-input v-model="form.totalScore" placeholder="请输入试卷总分" />
+        </el-form-item>
+        <el-form-item label="及格分" prop="qualifyScore">
+          <el-input v-model="form.qualifyScore" placeholder="请输入及格分" />
+        </el-form-item>
+        <el-form-item label="客观分" prop="objScore">
+          <el-input v-model="form.objScore" placeholder="请输入客观分" />
+        </el-form-item>
+        <el-form-item label="主观分" prop="subjScore">
+          <el-input v-model="form.subjScore" placeholder="请输入主观分" />
+        </el-form-item>
+        <el-form-item label="用户得分" prop="userScore">
+          <el-input v-model="form.userScore" placeholder="请输入用户得分" />
+        </el-form-item>
+        <el-form-item label="是否包含简答题" prop="hasSaq">
+          <el-input v-model="form.hasSaq" placeholder="请输入是否包含简答题" />
+        </el-form-item>
+        <el-form-item label="试卷状态" prop="state">
+          <el-input v-model="form.state" placeholder="请输入试卷状态" />
+        </el-form-item>
+        <el-form-item label="截止时间" prop="limitTime">
+          <el-date-picker clearable size="small" style="width: 200px"
+            v-model="form.limitTime"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="选择截止时间">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="删除" prop="delFlag">
+          <el-input v-model="form.delFlag" placeholder="请输入删除" />
+        </el-form-item>
+        <el-form-item label="创建人" prop="createrCode">
+          <el-input v-model="form.createrCode" placeholder="请输入创建人" />
+        </el-form-item>
+        <el-form-item label="创建时间" prop="createdate">
+          <el-date-picker clearable size="small" style="width: 200px"
+            v-model="form.createdate"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="选择创建时间">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="更新人" prop="updaterCode">
+          <el-input v-model="form.updaterCode" placeholder="请输入更新人" />
+        </el-form-item>
+        <el-form-item label="更新日期" prop="updatedate">
+          <el-date-picker clearable size="small" style="width: 200px"
+            v-model="form.updatedate"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="选择更新日期">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="所属部门" prop="deptId">
+          <el-input v-model="form.deptId" placeholder="请输入所属部门" />
+        </el-form-item>
+        <el-form-item label="备注" prop="remarks">
+          <el-input v-model="form.remarks" placeholder="请输入备注" />
+        </el-form-item>
+          <el-form-item label="归属部门" prop="deptId">
+              <treeselect v-model="form.deptId" :options="deptOptions" :show-count="true" placeholder="请选择归属部门" />
+          </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
+      <!-- 用户导入对话框 -->
+      <el-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body>
+          <el-upload
+                  ref="upload"
+                  :limit="1"
+                  accept=".xlsx, .xls"
+                  :headers="upload.headers"
+                  :action="upload.url + '?updateSupport=' + upload.updateSupport"
+                  :disabled="upload.isUploading"
+                  :on-progress="handleFileUploadProgress"
+                  :on-success="handleFileSuccess"
+                  :auto-upload="false"
+                  drag
+          >
+              <i class="el-icon-upload"></i>
+              <div class="el-upload__text">
+                  将文件拖到此处,或
+                  <em>点击上传</em>
+              </div>
+              <div class="el-upload__tip" slot="tip">
+                  <el-checkbox v-model="upload.updateSupport" />是否更新已经存在的用户数据
+                  <el-link type="info" style="font-size:12px" @click="importTemplate">下载模板</el-link>
+              </div>
+              <div class="el-upload__tip" style="color:red" slot="tip">提示:仅允许导入“xls”或“xlsx”格式文件!</div>
+          </el-upload>
+          <div slot="footer" class="dialog-footer">
+              <el-button type="primary" @click="submitFileForm">确 定</el-button>
+              <el-button @click="upload.open = false">取 消</el-button>
+          </div>
+      </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listPaper, getPaper, delPaper, addPaper, updatePaper, exportPaper, importTemplate} from "@/api/training/elearn/paper";
+import { treeselect } from "@/api/system/dept";
+import { getToken } from "@/utils/auth";
+import Treeselect from "@riophae/vue-treeselect";
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
+
+export default {
+  name: "Paper",
+  components: { Treeselect },
+  data() {
+    return {
+      // 遮罩层
+      loading: true,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: false,
+      // 总条数
+      total: 0,
+      // 在线考试表格数据
+      paperList: [],
+      // 弹出层标题
+      title: "",
+      // 部门树选项
+      deptOptions: undefined,
+      clientHeight:300,
+      // 是否显示弹出层
+      open: false,
+        // 用户导入参数
+        upload: {
+            // 是否显示弹出层(用户导入)
+            open: false,
+            // 弹出层标题(用户导入)
+            title: "",
+            // 是否禁用上传
+            isUploading: false,
+            // 是否更新已经存在的用户数据
+            updateSupport: 0,
+            // 设置上传的请求头部
+            headers: { Authorization: "Bearer " + getToken() },
+            // 上传的地址
+            url: process.env.VUE_APP_BASE_API + "/elearn/paper/importData"
+        },
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 20,
+        userId: null,
+        staffId: null,
+        examId: null,
+        title: null,
+        totalTime: null,
+        userTime: null,
+        totalScore: null,
+        qualifyScore: null,
+        objScore: null,
+        subjScore: null,
+        userScore: null,
+        hasSaq: null,
+        state: null,
+        limitTime: null,
+        createrCode: null,
+        createdate: null,
+        updaterCode: null,
+        updatedate: null,
+        deptId: null,
+        remarks: null
+      },
+      // 表单参数
+      form: {},
+      // 表单校验
+      rules: {
+      }
+    };
+  },
+  watch: {
+        // 根据名称筛选部门树
+        deptName(val) {
+            this.$refs.tree.filter(val);
+        }
+   },
+  created() {
+      //设置表格高度对应屏幕高度
+      this.$nextTick(() => {
+          this.clientHeight = document.body.clientHeight -250
+      })
+    this.getList();
+    this.getTreeselect();
+  },
+  methods: {
+    /** 查询在线考试列表 */
+    getList() {
+      this.loading = true;
+      listPaper(this.queryParams).then(response => {
+        this.paperList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+     /** 查询部门下拉树结构 */
+     getTreeselect() {
+          treeselect().then(response => {
+              this.deptOptions = response.data;
+          });
+     },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        paperId: null,
+        userId: null,
+        staffId: null,
+        examId: null,
+        title: null,
+        totalTime: null,
+        userTime: null,
+        totalScore: null,
+        qualifyScore: null,
+        objScore: null,
+        subjScore: null,
+        userScore: null,
+        hasSaq: null,
+        state: null,
+        limitTime: null,
+        delFlag: null,
+        createrCode: null,
+        createdate: null,
+        updaterCode: null,
+        updatedate: null,
+        deptId: null,
+        remarks: null
+      };
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.paperId)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "添加在线考试";
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      const paperId = row.paperId || this.ids
+      getPaper(paperId).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改在线考试";
+      });
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.paperId != null) {
+            updatePaper(this.form).then(response => {
+              this.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addPaper(this.form).then(response => {
+              this.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const paperIds = row.paperId || this.ids;
+      this.$confirm('是否确认删除?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return delPaper(paperIds);
+        }).then(() => {
+          this.getList();
+          this.msgSuccess("删除成功");
+        })
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      const queryParams = this.queryParams;
+      this.$confirm('是否确认导出所有在线考试数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return exportPaper(queryParams);
+        }).then(response => {
+          this.download(response.msg);
+        })
+    },
+      /** 导入按钮操作 */
+      handleImport() {
+          this.upload.title = "用户导入";
+          this.upload.open = true;
+      },
+      /** 下载模板操作 */
+      importTemplate() {
+          importTemplate().then(response => {
+              this.download(response.msg);
+          });
+      },
+      // 文件上传中处理
+      handleFileUploadProgress(event, file, fileList) {
+          this.upload.isUploading = true;
+      },
+      // 文件上传成功处理
+      handleFileSuccess(response, file, fileList) {
+          this.upload.open = false;
+          this.upload.isUploading = false;
+          this.$refs.upload.clearFiles();
+          this.$alert(response.msg, "导入结果", { dangerouslyUseHTMLString: true });
+          this.getList();
+      },
+      // 提交上传文件
+      submitFileForm() {
+          this.$refs.upload.submit();
+      }
+  }
+};
+</script>

+ 296 - 0
ui/src/views/training/elearn/paper/list.vue

@@ -0,0 +1,296 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="考试名称" prop="title">
+        <el-input
+          v-model="queryParams.title"
+          placeholder="请输入考试名称"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+<!--      <el-form-item label="1公开2部门3定员" prop="openType">-->
+<!--        <el-select v-model="queryParams.openType" placeholder="请选择1公开2部门3定员" clearable size="small">-->
+<!--          <el-option label="请选择字典生成" value="" />-->
+<!--        </el-select>-->
+<!--      </el-form-item>-->
+
+      <el-form-item>
+        <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+
+	  <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading" :data="examList" :height="clientHeight" border>
+      <el-table-column
+        label="考试名称"
+        prop="title"
+        show-overflow-tooltip
+      />
+
+<!--      <el-table-column
+        label="考试类型"
+        align="center"
+      >
+        <template v-slot="scope">
+          {{ scope.row.openType | examOpenType }}
+        </template>
+
+      </el-table-column>-->
+
+      <el-table-column
+        label="考试时间"
+        width="220px"
+        align="center"
+      >
+
+        <template v-slot="scope">
+            <span v-if="scope.row.timeLimit">
+              {{ scope.row.startTime }} ~ {{ scope.row.endTime }}
+            </span>
+          <span v-else>不限时</span>
+        </template>
+
+      </el-table-column>
+
+      <el-table-column
+        label="考试时长"
+        align="center"
+      >
+
+        <template v-slot="scope">
+          {{ scope.row.totalTime }}分钟
+        </template>
+
+      </el-table-column>
+
+      <el-table-column
+        label="考试总分"
+        prop="totalScore"
+        align="center"
+      />
+
+      <el-table-column
+        label="及格线"
+        prop="qualifyScore"
+        align="center"
+      />
+
+      <el-table-column
+        label="操作"
+        align="center"
+      >
+        <template v-slot="scope">
+          <el-button v-if="scope.row.state===0" icon="el-icon-caret-right" type="primary" size="mini" @click="handlePre(scope.row.examId)">去考试</el-button>
+          <el-button v-if="scope.row.state===1" icon="el-icon-s-release" size="mini" disabled>已禁用</el-button>
+          <el-button v-if="scope.row.state===2" icon="el-icon-s-fold" size="mini" disabled>待开始</el-button>
+          <el-button v-if="scope.row.state===3" icon="el-icon-s-unfold" size="mini" disabled>已结束</el-button>
+        </template>
+
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+  </div>
+</template>
+
+<script>
+import { listExam, getExam, delExam, addExam, updateExam, exportExam, importTemplate} from "@/api/training/elearn/exam";
+import { treeselect } from "@/api/system/dept";
+import { getToken } from "@/utils/auth";
+import Treeselect from "@riophae/vue-treeselect";
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
+import RepoSelect from '@/components/RepoSelect'
+
+export default {
+  name: "ExamList",
+  components: { Treeselect,RepoSelect },
+  // components: { Editor },
+  data() {
+    return {
+      // 遮罩层
+      loading: true,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 考试表格数据
+      examList: [],
+      // 已选择的题库
+      excludes: [],
+      // 弹出层标题
+      title: "",
+      // 部门树选项
+      deptOptions: undefined,
+      clientHeight:300,
+      // 是否显示弹出层
+      open: false,
+        // 用户导入参数
+        upload: {
+            // 是否显示弹出层(用户导入)
+            open: false,
+            // 弹出层标题(用户导入)
+            title: "",
+            // 是否禁用上传
+            isUploading: false,
+            // 是否更新已经存在的用户数据
+            updateSupport: 0,
+            // 设置上传的请求头部
+            headers: { Authorization: "Bearer " + getToken() },
+            // 上传的地址
+            url: process.env.VUE_APP_BASE_API + "/elearn/exam/importData"
+        },
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 20,
+        title: null,
+        content: null,
+        openType: null,
+        state: null,
+        timeLimit: null,
+        examStartTime: null,
+        examEndTime: null,
+        totalScore: null,
+        totalTime: null,
+        qualifyScore: null,
+        createrCode: null,
+        createdate: null,
+        updaterCode: null,
+        updatedate: null,
+        deptId: null,
+        remarks: null
+      },
+      // 题库
+      repoList: [],
+      // 表单参数
+      form: {},
+      // 表单校验
+      rules: {
+      }
+    };
+  },
+  watch: {
+
+    filterText(val) {
+      this.$refs.tree.filter(val)
+    },
+
+    dateValues: {
+
+      handler() {
+        this.form.examStartTime = this.dateValues[0]
+        this.form.examEndTime = this.dateValues[1]
+      }
+    },
+
+    // 题库变换
+    repoList: {
+
+      handler(val) {
+        let totalScore = 0
+        this.excludes = []
+        for (let i = 0; i<val.length; i++) {
+          const item = val[i]
+          if (item.radioCount > 0 && item.radioScore>0) {
+            totalScore += item.radioCount * item.radioScore
+          }
+
+          if (item.multiCount>0 && item.multiScore>0) {
+            totalScore += item.multiCount * item.multiScore
+          }
+
+          if (item.judgeCount>0 && item.judgeScore>0) {
+            totalScore += item.judgeCount * item.judgeScore
+          }
+          this.excludes.push(item.id)
+        }
+
+        // 赋值
+        this.form.totalScore = totalScore
+        this.form.repoList = val
+        this.$forceUpdate()
+      },
+      deep: true
+    }
+
+  },
+  created() {
+      //设置表格高度对应屏幕高度
+      this.$nextTick(() => {
+          this.clientHeight = document.body.clientHeight -250
+      })
+    this.getList();
+    this.getTreeselect();
+  },
+  methods: {
+    /** 查询考试列表 */
+    getList() {
+      this.loading = true;
+      listExam(this.queryParams).then(response => {
+        this.examList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        examId: null,
+        title: null,
+        content: null,
+        openType: null,
+        state: null,
+        timeLimit: null,
+        examStartTime: null,
+        examEndTime: null,
+        totalScore: null,
+        totalTime: null,
+        qualifyScore: null,
+        delFlag: null,
+        createrCode: null,
+        createdate: null,
+        updaterCode: null,
+        updatedate: null,
+        deptId: null,
+        remarks: null,
+        repoList: [],
+      };
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 开始考试
+    handlePre(examId) {
+      this.$router.push({ name: 'PreExam', params: { examId: examId }})
+    },
+  }
+};
+</script>

+ 113 - 0
ui/src/views/training/elearn/paper/preview.vue

@@ -0,0 +1,113 @@
+<template>
+  <div class="app-container">
+    <el-row :gutter="24">
+
+      <el-col :span="24" style="margin-bottom: 20px">
+
+        <el-alert
+          title="点击`开始考试`后将自动进入考试,请诚信考试!"
+          type="error"
+          style="margin-bottom: 10px"
+        />
+
+        <el-card class="pre-exam">
+
+          <div><strong>考试名称:</strong>{{ detailData.title }}</div>
+          <div><strong>考试时长:</strong>{{ detailData.totalTime }}分钟</div>
+          <div><strong>试卷总分:</strong>{{ detailData.totalScore }}分</div>
+          <div><strong>及格分数:</strong>{{ detailData.qualifyScore }}分</div>
+          <div><strong>考试描述:</strong>{{ detailData.content }}</div>
+
+        </el-card>
+
+      </el-col>
+
+      <el-col :span="24">
+
+        <el-button :loading="loading" type="primary" icon="el-icon-caret-right" @click="handleCreate">
+          开始考试
+        </el-button>
+
+        <el-button @click="handleBack">
+          返回
+        </el-button>
+
+      </el-col>
+
+    </el-row>
+  </div>
+</template>
+
+<script>
+import { listExam, getExam, delExam, addExam, updateExam, exportExam, importTemplate} from "@/api/training/elearn/exam";
+import { createPaper} from "@/api/training/elearn/paper";
+import Treeselect from "@riophae/vue-treeselect";
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
+
+export default {
+  name: "Exam",
+  components: { Treeselect },
+  // components: { Editor },
+  data() {
+    return {
+      detailData: {},
+      postForm: {
+        examId: '',
+      },
+    };
+  },
+  watch: {
+
+  },
+  created() {
+    this.postForm.examId = this.$route.params.examId
+    getExam(this.$route.params.examId).then(response => {
+      this.detailData = response.data;
+    });
+  },
+  methods: {
+
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      const examId = row.examId || this.ids
+      getExam(examId).then(response => {
+        this.form = response.data;
+        this.repoList = this.form.repoList
+        this.open = true;
+        this.title = "修改考试";
+      });
+    },
+    handleCreate() {
+      const that = this
+      this.loading = true
+
+      createPaper(this.postForm).then(response => {
+        console.log(response)
+
+        if (response.code === 0) {
+          setTimeout(function() {
+            this.loading = false
+            that.dialogVisible = false
+            that.$router.push({ name: 'StartExam', params: { id: response.data.id }})
+          }, 1000)
+        }
+      }).catch(() => {
+        this.loading = false
+      })
+    },
+    handleBack() {
+      this.$router.push({ name: 'paper' })
+    }
+  }
+};
+</script>
+<style scoped>
+
+.pre-exam div {
+
+  line-height: 42px;
+  color: #555555;
+}
+
+</style>

+ 512 - 0
ui/src/views/training/elearn/qu/index.vue

@@ -0,0 +1,512 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="题目类型" prop="quType">
+        <el-select v-model="queryParams.quType" placeholder="请选择题目类型" clearable size="small">
+          <el-option
+            v-for="item in quTypes"
+            :key="item.value"
+            :label="item.label"
+            :value="item.value"
+          />
+        </el-select>
+      </el-form-item>
+
+      <el-form-item>
+        <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['elearn:qu:add']"
+        >新增</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="single"
+          @click="handleUpdate"
+          v-hasPermi="['elearn:qu:edit']"
+        >修改</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['elearn:qu:remove']"
+        >删除</el-button>
+      </el-col>
+	  <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading" :data="quList" @selection-change="handleSelectionChange" :height="clientHeight" border>
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="题目类型" align="center" prop="quType" width="100" :show-overflow-tooltip="true">
+        <template v-slot="scope">
+          <span v-if="scope.row.quType == 1" size="small" type="success">单选题</span>
+          <span v-else-if="scope.row.quType == 2" size="small" type="success">多选题</span>
+          <span v-else-if="scope.row.quType == 3" size="small" type="success">判断题</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="题目内容" align="center" prop="content"  :show-overflow-tooltip="true"/>
+      <el-table-column label="创建时间" align="center" prop="createdate" width="100">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.createdate, '{y}-{m}-{d}') }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" fixed="right" width="120" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleUpdate(scope.row)"
+            v-hasPermi="['elearn:qu:edit']"
+          >修改</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['elearn:qu:remove']"
+          >删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 添加或修改试题对话框 -->
+    <el-dialog :title="title" :visible.sync="open" width="1200px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="100px">
+        <el-card>
+
+          <el-form-item label="题目类型 " prop="quType">
+
+            <el-select v-model="form.quType" :disabled="quTypeDisabled" class="filter-item" @change="handleTypeChange">
+              <el-option
+                v-for="item in quTypes"
+                :key="item.value"
+                :label="item.label"
+                :value="item.value"
+              />
+            </el-select>
+
+          </el-form-item>
+
+          <el-form-item label="难度等级 " prop="qlevel">
+
+            <el-select v-model="form.qlevel" class="filter-item">
+              <el-option
+                v-for="item in levels"
+                :key="item.value"
+                :label="item.label"
+                :value="item.value"
+              />
+            </el-select>
+
+          </el-form-item>
+
+          <el-form-item label="归属题库" prop="repoIds">
+
+            <repo-select v-model="form.repoIds" :multi="true" />
+
+          </el-form-item>
+
+          <el-form-item label="题目内容" prop="content">
+            <el-input v-model="form.content" type="textarea" />
+          </el-form-item>
+
+          <el-form-item label="试题图片">
+            <file-upload v-model="form.image" accept=".jpg,.jepg,.png" />
+          </el-form-item>
+
+          <el-form-item label="整题解析" prop="oriPrice">
+            <el-input v-model="form.analysis" :precision="1" :max="999999" type="textarea" />
+          </el-form-item>
+
+        </el-card>
+        <div v-if="form.quType!==4" class="filter-container" style="margin-top: 25px">
+
+          <el-button class="filter-item" type="primary" icon="el-icon-plus" size="small" plain @click="handleAddItem">
+            添加
+          </el-button>
+
+          <el-table
+            :data="form.answerList"
+            :border="true"
+            style="width: 100%;"
+          >
+            <el-table-column
+              label="是否答案"
+              width="120"
+              align="center"
+            >
+              <template v-slot="scope">
+
+                <el-checkbox v-model="scope.row.isRight" :true-label=1 :false-label=0>答案</el-checkbox>
+
+              </template>
+
+            </el-table-column>
+
+            <el-table-column
+              v-if="itemImage"
+              label="选项图片"
+              width="120px"
+              align="center"
+            >
+              <template v-slot="scope">
+
+                <file-upload
+                  v-model="scope.row.image"
+                  accept=".jpg,.jepg,.png"
+                />
+
+              </template>
+            </el-table-column>
+
+            <el-table-column
+              label="答案内容"
+            >
+              <template v-slot="scope">
+                <el-input v-model="scope.row.content" type="textarea" />
+              </template>
+            </el-table-column>
+
+            <el-table-column
+              label="答案解析"
+            >
+              <template v-slot="scope">
+                <el-input v-model="scope.row.analysis" type="textarea" />
+              </template>
+            </el-table-column>
+
+            <el-table-column
+              label="操作"
+              align="center"
+              width="100px"
+            >
+              <template v-slot="scope">
+                <el-button type="danger" icon="el-icon-delete" circle @click="removeItem(scope.$index)" />
+              </template>
+            </el-table-column>
+
+          </el-table>
+
+        </div>
+
+
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
+
+  </div>
+</template>
+
+<script>
+import { listQu, getQu, delQu, addQu, updateQu, exportQu, importTemplate} from "@/api/training/elearn/qu";
+import { treeselect } from "@/api/system/dept";
+import { getToken } from "@/utils/auth";
+import Treeselect from "@riophae/vue-treeselect";
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
+import Editor from '@/components/Editor';
+import RepoSelect from '@/components/RepoSelect'
+
+export default {
+  name: "Qu",
+  components: { Treeselect,RepoSelect },
+  data() {
+    return {
+      // 遮罩层
+      loading: true,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: false,
+      // 总条数
+      total: 0,
+      // 试题表格数据
+      quList: [],
+      // 弹出层标题
+      title: "",
+      // 部门树选项
+      deptOptions: undefined,
+      quTypes: [
+        {
+          value: 1,
+          label: '单选题'
+        },
+        {
+          value: 2,
+          label: '多选题'
+        },
+        {
+          value: 3,
+          label: '判断题'
+        }
+      ],
+      quTypeDisabled: false,
+      itemImage: true,
+      levels: [
+        { value: 1, label: '普通' },
+        { value: 2, label: '较难' }
+      ],
+      clientHeight:300,
+      // 是否显示弹出层
+      open: false,
+        // 用户导入参数
+        upload: {
+            // 是否显示弹出层(用户导入)
+            open: false,
+            // 弹出层标题(用户导入)
+            title: "",
+            // 是否禁用上传
+            isUploading: false,
+            // 是否更新已经存在的用户数据
+            updateSupport: 0,
+            // 设置上传的请求头部
+            headers: { Authorization: "Bearer " + getToken() },
+            // 上传的地址
+            url: process.env.VUE_APP_BASE_API + "/elearn/qu/importData"
+        },
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 20,
+        quType: null,
+        qlevel: null,
+        content: null,
+        image: null,
+        analysis: null,
+        createrCode: null,
+        createdate: null,
+        updaterCode: null,
+        updatedate: null,
+        deptId: null,
+        remarks: null
+      },
+      // 表单参数
+      form: {
+        repoIds: [],
+        tagList: [],
+        answerList: []
+      },
+      // 表单校验
+      rules: {
+      }
+    };
+  },
+  watch: {
+        // 根据名称筛选部门树
+        deptName(val) {
+            this.$refs.tree.filter(val);
+        }
+   },
+  created() {
+      //设置表格高度对应屏幕高度
+      this.$nextTick(() => {
+          this.clientHeight = document.body.clientHeight -250
+      })
+    this.getList();
+    this.getTreeselect();
+  },
+  methods: {
+    /** 查询试题列表 */
+    getList() {
+      this.loading = true;
+      listQu(this.queryParams).then(response => {
+        this.quList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+     /** 查询部门下拉树结构 */
+     getTreeselect() {
+          treeselect().then(response => {
+              this.deptOptions = response.data;
+          });
+     },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        quId: null,
+        quType: null,
+        qlevel: null,
+        content: null,
+        image: null,
+        analysis: null,
+        delFlag: null,
+        createrCode: null,
+        createdate: null,
+        updaterCode: null,
+        updatedate: null,
+        deptId: null,
+        remarks: null,
+        repoIds: [],
+        tagList: [],
+        answerList: []
+      };
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.quId)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "添加试题";
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      const quId = row.quId || this.ids
+      getQu(quId).then(response => {
+        this.form = response.data;
+        this.form.repoIds = this.form.repoIds.map(Number)
+        this.open = true;
+        this.title = "修改试题";
+      });
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.quId != null) {
+            updateQu(this.form).then(response => {
+              this.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addQu(this.form).then(response => {
+              this.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const quIds = row.quId || this.ids;
+      this.$confirm('是否确认删除?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return delQu(quIds);
+        }).then(() => {
+          this.getList();
+          this.msgSuccess("删除成功");
+        })
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      const queryParams = this.queryParams;
+      this.$confirm('是否确认导出所有试题数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return exportQu(queryParams);
+        }).then(response => {
+          this.download(response.msg);
+        })
+    },
+      /** 导入按钮操作 */
+      handleImport() {
+          this.upload.title = "用户导入";
+          this.upload.open = true;
+      },
+      /** 下载模板操作 */
+      importTemplate() {
+          importTemplate().then(response => {
+              this.download(response.msg);
+          });
+      },
+      // 文件上传中处理
+      handleFileUploadProgress(event, file, fileList) {
+          this.upload.isUploading = true;
+      },
+      // 文件上传成功处理
+      handleFileSuccess(response, file, fileList) {
+          this.upload.open = false;
+          this.upload.isUploading = false;
+          this.$refs.upload.clearFiles();
+          this.$alert(response.msg, "导入结果", { dangerouslyUseHTMLString: true });
+          this.getList();
+      },
+      // 提交上传文件
+      submitFileForm() {
+          this.$refs.upload.submit();
+      },
+    handleTypeChange(v) {
+      this.form.answerList = []
+      if (v === 3) {
+        this.form.answerList.push({ isRight: 1, content: '正确', analysis: '' })
+        this.form.answerList.push({ isRight: 0, content: '错误', analysis: '' })
+      }
+
+      if (v === 1 || v === 2) {
+        this.form.answerList.push({ isRight: 0, content: '', analysis: '' })
+        this.form.answerList.push({ isRight: 0, content: '', analysis: '' })
+        this.form.answerList.push({ isRight: 0, content: '', analysis: '' })
+        this.form.answerList.push({ isRight: 0, content: '', analysis: '' })
+      }
+    },
+    // 添加子项
+    handleAddItem() {
+      this.form.answerList.push({ isRight: 0, content: '', analysis: '' })
+    },
+    removeItem(index) {
+      this.form.answerList.splice(index, 1)
+    },
+  }
+};
+</script>

+ 449 - 0
ui/src/views/training/elearn/repo/index.vue

@@ -0,0 +1,449 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="题库编号" prop="code">
+        <el-input
+          v-model="queryParams.code"
+          placeholder="请输入题库编号"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="题库名称" prop="title">
+        <el-input
+          v-model="queryParams.title"
+          placeholder="请输入题库名称"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="创建人" prop="createrCode">
+        <el-input
+          v-model="queryParams.createrCode"
+          placeholder="请输入创建人"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="创建时间" prop="createdate">
+        <el-date-picker clearable size="small" style="width: 200px"
+                        v-model="queryParams.createdate"
+                        type="date"
+                        value-format="yyyy-MM-dd"
+                        placeholder="选择创建时间">
+        </el-date-picker>
+      </el-form-item>
+      <el-form-item label="更新人" prop="updaterCode">
+        <el-input
+          v-model="queryParams.updaterCode"
+          placeholder="请输入更新人"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="更新日期" prop="updatedate">
+        <el-date-picker clearable size="small" style="width: 200px"
+                        v-model="queryParams.updatedate"
+                        type="date"
+                        value-format="yyyy-MM-dd"
+                        placeholder="选择更新日期">
+        </el-date-picker>
+      </el-form-item>
+      <el-form-item label="所属部门" prop="deptId">
+        <el-input
+          v-model="queryParams.deptId"
+          placeholder="请输入所属部门"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="备注" prop="remarks">
+        <el-input
+          v-model="queryParams.remarks"
+          placeholder="请输入备注"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['elearn:repo:add']"
+        >新增
+        </el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="single"
+          @click="handleUpdate"
+          v-hasPermi="['elearn:repo:edit']"
+        >修改
+        </el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['elearn:repo:remove']"
+        >删除
+        </el-button>
+      </el-col>
+      <el-col :span="1.5">
+      </el-col>
+      <el-col :span="1.5">
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading" :data="repoList" @selection-change="handleSelectionChange" :height="clientHeight"
+              border>
+      <el-table-column type="selection" width="55" align="center"/>
+      <!--      <el-table-column label="题库编号" align="center" prop="code" :show-overflow-tooltip="true"/>-->
+      <el-table-column label="题库名称" align="center" prop="title" :show-overflow-tooltip="true"/>
+      <el-table-column
+        label="单选题数量"
+        prop="radioCount"
+        align="center"
+      />
+      <el-table-column
+        label="多选题数量"
+        prop="multiCount"
+        align="center"
+      />
+      <el-table-column
+        label="判断题数量"
+        prop="judgeCount"
+        align="center"
+      />
+      <el-table-column label="备注" align="center" prop="remarks" :show-overflow-tooltip="true"/>
+      <el-table-column label="操作" align="center" fixed="right" width="120" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleUpdate(scope.row)"
+            v-hasPermi="['elearn:repo:edit']"
+          >修改
+          </el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['elearn:repo:remove']"
+          >删除
+          </el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 添加或修改题库对话框 -->
+    <el-dialog :title="title" :visible.sync="open" width="900px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="120px">
+        <!--        <el-form-item label="题库编号" prop="code">-->
+        <!--          <el-input v-model="form.code" placeholder="请输入题库编号" />-->
+        <!--        </el-form-item>-->
+        <el-form-item label="题库名称" prop="title">
+          <el-input v-model="form.title" placeholder="请输入题库名称"/>
+        </el-form-item>
+        <el-form-item label="备注" prop="remarks">
+          <el-input v-model="form.remarks" placeholder="请输入备注"/>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
+    <!-- 用户导入对话框 -->
+    <el-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body>
+      <el-upload
+        ref="upload"
+        :limit="1"
+        accept=".xlsx, .xls"
+        :headers="upload.headers"
+        :action="upload.url + '?updateSupport=' + upload.updateSupport"
+        :disabled="upload.isUploading"
+        :on-progress="handleFileUploadProgress"
+        :on-success="handleFileSuccess"
+        :auto-upload="false"
+        drag
+      >
+        <i class="el-icon-upload"></i>
+        <div class="el-upload__text">
+          将文件拖到此处,或
+          <em>点击上传</em>
+        </div>
+        <div class="el-upload__tip" slot="tip">
+          <el-checkbox v-model="upload.updateSupport"/>
+          是否更新已经存在的用户数据
+          <el-link type="info" style="font-size:12px" @click="importTemplate">下载模板</el-link>
+        </div>
+        <div class="el-upload__tip" style="color:red" slot="tip">提示:仅允许导入“xls”或“xlsx”格式文件!</div>
+      </el-upload>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitFileForm">确 定</el-button>
+        <el-button @click="upload.open = false">取 消</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import {listRepo, getRepo, delRepo, addRepo, updateRepo, exportRepo, importTemplate} from "@/api/training/elearn/repo";
+import {treeselect} from "@/api/system/dept";
+import {getToken} from "@/utils/auth";
+import Treeselect from "@riophae/vue-treeselect";
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
+
+export default {
+  name: "Repo",
+  components: {Treeselect},
+  data() {
+    return {
+      // 遮罩层
+      loading: true,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: false,
+      // 总条数
+      total: 0,
+      // 题库表格数据
+      repoList: [],
+      // 弹出层标题
+      title: "",
+      // 部门树选项
+      deptOptions: undefined,
+      clientHeight: 300,
+      // 是否显示弹出层
+      open: false,
+      // 用户导入参数
+      upload: {
+        // 是否显示弹出层(用户导入)
+        open: false,
+        // 弹出层标题(用户导入)
+        title: "",
+        // 是否禁用上传
+        isUploading: false,
+        // 是否更新已经存在的用户数据
+        updateSupport: 0,
+        // 设置上传的请求头部
+        headers: {Authorization: "Bearer " + getToken()},
+        // 上传的地址
+        url: process.env.VUE_APP_BASE_API + "/elearn/repo/importData"
+      },
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 20,
+        code: null,
+        title: null,
+        createrCode: null,
+        createdate: null,
+        updaterCode: null,
+        updatedate: null,
+        deptId: null,
+        remarks: null
+      },
+      // 表单参数
+      form: {},
+      // 表单校验
+      rules: {}
+    };
+  },
+  watch: {
+    // 根据名称筛选部门树
+    deptName(val) {
+      this.$refs.tree.filter(val);
+    }
+  },
+  created() {
+    //设置表格高度对应屏幕高度
+    this.$nextTick(() => {
+      this.clientHeight = document.body.clientHeight - 250
+    })
+    this.getList();
+    this.getTreeselect();
+  },
+  methods: {
+    /** 查询题库列表 */
+    getList() {
+      this.loading = true;
+      listRepo(this.queryParams).then(response => {
+        this.repoList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    /** 查询部门下拉树结构 */
+    getTreeselect() {
+      treeselect().then(response => {
+        this.deptOptions = response.data;
+      });
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        repoId: null,
+        code: null,
+        title: null,
+        delFlag: null,
+        createrCode: null,
+        createdate: null,
+        updaterCode: null,
+        updatedate: null,
+        deptId: null,
+        remarks: null
+      };
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.repoId)
+      this.single = selection.length !== 1
+      this.multiple = !selection.length
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "添加题库";
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      const repoId = row.repoId || this.ids
+      getRepo(repoId).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改题库";
+      });
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.repoId != null) {
+            updateRepo(this.form).then(response => {
+              this.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addRepo(this.form).then(response => {
+              this.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const repoIds = row.repoId || this.ids;
+      this.$confirm('是否确认删除?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(function () {
+        return delRepo(repoIds);
+      }).then(() => {
+        this.getList();
+        this.msgSuccess("删除成功");
+      })
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      const queryParams = this.queryParams;
+      this.$confirm('是否确认导出所有题库数据项?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(function () {
+        return exportRepo(queryParams);
+      }).then(response => {
+        this.download(response.msg);
+      })
+    },
+    /** 导入按钮操作 */
+    handleImport() {
+      this.upload.title = "用户导入";
+      this.upload.open = true;
+    },
+    /** 下载模板操作 */
+    importTemplate() {
+      importTemplate().then(response => {
+        this.download(response.msg);
+      });
+    },
+    // 文件上传中处理
+    handleFileUploadProgress(event, file, fileList) {
+      this.upload.isUploading = true;
+    },
+    // 文件上传成功处理
+    handleFileSuccess(response, file, fileList) {
+      this.upload.open = false;
+      this.upload.isUploading = false;
+      this.$refs.upload.clearFiles();
+      this.$alert(response.msg, "导入结果", {dangerouslyUseHTMLString: true});
+      this.getList();
+    },
+    // 提交上传文件
+    submitFileForm() {
+      this.$refs.upload.submit();
+    }
+  }
+};
+</script>