Kaynağa Gözat

LY 装置培训 统计 在线学习

ly 1 yıl önce
ebeveyn
işleme
3add410b32
24 değiştirilmiş dosya ile 3455 ekleme ve 76 silme
  1. 1 1
      master/pom.xml
  2. 28 8
      master/src/main/java/com/ruoyi/project/training/controller/TTrainingbccController.java
  3. 10 0
      master/src/main/java/com/ruoyi/project/training/controller/TTrainingbccDeviceController.java
  4. 268 0
      master/src/main/java/com/ruoyi/project/training/controller/TTrainingbccRegularController.java
  5. 349 0
      master/src/main/java/com/ruoyi/project/training/domain/TTrainingbccRegular.java
  6. 187 0
      master/src/main/java/com/ruoyi/project/training/elearn/controller/TElRecordController.java
  7. 268 0
      master/src/main/java/com/ruoyi/project/training/elearn/domain/TElRecord.java
  8. 73 0
      master/src/main/java/com/ruoyi/project/training/elearn/mapper/TElRecordMapper.java
  9. 61 0
      master/src/main/java/com/ruoyi/project/training/elearn/service/ITElRecordService.java
  10. 93 0
      master/src/main/java/com/ruoyi/project/training/elearn/service/impl/TElRecordServiceImpl.java
  11. 63 0
      master/src/main/java/com/ruoyi/project/training/mapper/TTrainingbccRegularMapper.java
  12. 61 0
      master/src/main/java/com/ruoyi/project/training/service/ITTrainingbccRegularService.java
  13. 93 0
      master/src/main/java/com/ruoyi/project/training/service/impl/TTrainingbccRegularServiceImpl.java
  14. 2 2
      master/src/main/resources/application.yml
  15. 165 0
      master/src/main/resources/mybatis/training/TTrainingbccRegularMapper.xml
  16. 185 0
      master/src/main/resources/mybatis/training/elearn/TElRecordMapper.xml
  17. 10 0
      ui/src/api/training/bccdevice.js
  18. 53 0
      ui/src/api/training/bccregular.js
  19. 63 0
      ui/src/api/training/elearn/record.js
  20. 106 32
      ui/src/views/training/bccdevice/index.vue
  21. 822 0
      ui/src/views/training/bccregular/index.vue
  22. 343 0
      ui/src/views/training/elearn/record/index.vue
  23. 150 32
      ui/src/views/training/trainingbcc/index.vue
  24. 1 1
      ui/vue.config.js

+ 1 - 1
master/pom.xml

@@ -6,7 +6,7 @@
     <groupId>com.cpms</groupId>
     <artifactId>cpms</artifactId>
     <version>3.2.0</version>
-    <packaging>war</packaging>
+    <packaging>jar</packaging>
 
     <name>cpms</name>
     <description>cpms管理系统</description>

+ 28 - 8
master/src/main/java/com/ruoyi/project/training/controller/TTrainingbccController.java

@@ -1,20 +1,18 @@
 package com.ruoyi.project.training.controller;
 
+import java.io.IOException;
+import java.time.LocalDate;
 import java.util.List;
 
+import com.ruoyi.common.utils.file.FileUploadUtils;
+import com.ruoyi.framework.config.RuoYiConfig;
+import com.ruoyi.project.training.bccnew.domain.TTsFirstplanTmpl;
 import com.ruoyi.project.training.domain.TTrainingbccDevice;
 import com.ruoyi.project.training.mapper.TTrainingbccDeviceMapper;
 import com.ruoyi.project.training.mapper.TTrainingbccMapper;
 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 org.springframework.web.bind.annotation.*;
 import com.ruoyi.framework.aspectj.lang.annotation.Log;
 import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
 import com.ruoyi.project.training.domain.TTrainingbcc;
@@ -23,6 +21,7 @@ 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;
+import org.springframework.web.multipart.MultipartFile;
 
 import javax.annotation.Resource;
 
@@ -159,4 +158,25 @@ public class TTrainingbccController extends BaseController
     {
         return toAjax(tTrainingbccService.deleteTTrainingbccByIds(ids));
     }
+
+    @Log(title = "附件上传", businessType = BusinessType.UPDATE)
+    @PostMapping("/uploadFile/{id}")
+    public AjaxResult uploadFile(@RequestParam("file") MultipartFile file, @PathVariable Long id) throws IOException {
+        if (!file.isEmpty()) {
+            // 获取当前日期
+            LocalDate currentDate = LocalDate.now();
+            // 获取年份
+            int year = currentDate.getYear();
+            // 获取月份
+            int month = currentDate.getMonthValue();
+            String dir = "/elearn/" + year ;
+            String url = FileUploadUtils.upload(RuoYiConfig.getFilePath(dir), file);
+            TTrainingbcc entity = tTrainingbccService.selectTTrainingbccById(id);
+            entity.setFileUrl(url);
+            entity.setFileName(file.getOriginalFilename());
+            tTrainingbccService.updateTTrainingbcc(entity);
+            return AjaxResult.success(id);
+        }
+        return AjaxResult.error("上传失败,请联系管理员");
+    }
 }

+ 10 - 0
master/src/main/java/com/ruoyi/project/training/controller/TTrainingbccDeviceController.java

@@ -96,9 +96,19 @@ public class TTrainingbccDeviceController extends BaseController
     @PutMapping
     public AjaxResult edit(@RequestBody TTrainingbccDevice tTrainingbccDevice)
     {
+
         return toAjax(tTrainingbccDeviceService.updateTTrainingbccDevice(tTrainingbccDevice));
     }
 
+    @PutMapping("/updateDeviceLearnTime")
+    @Log(title = "人员-装置级培训-更新时长", businessType = BusinessType.UPDATE)
+    public AjaxResult updateDeviceLearnTime(@RequestBody TTrainingbccDevice tTrainingbccDevice)
+    {
+        TTrainingbccDevice t=   tTrainingbccDeviceService.selectTTrainingbccDeviceById(tTrainingbccDevice.getId());
+        t.setLearnTime(t.getLearnTime() +1);
+        return toAjax(tTrainingbccDeviceService.updateTTrainingbccDevice(t));
+    }
+
     /**
      * 删除人员-装置级培训关系
      */

+ 268 - 0
master/src/main/java/com/ruoyi/project/training/controller/TTrainingbccRegularController.java

@@ -0,0 +1,268 @@
+package com.ruoyi.project.training.controller;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import com.ruoyi.project.plant.domain.TStaffmgr;
+import com.ruoyi.project.plant.service.ITStaffmgrService;
+import com.ruoyi.project.system.domain.SysDictData;
+import com.ruoyi.project.system.service.ISysDictTypeService;
+import com.ruoyi.project.training.domain.*;
+import com.ruoyi.project.training.service.ITTrainingService;
+import com.ruoyi.project.training.service.ITTrainingbccDeviceService;
+import com.ruoyi.project.training.service.ITTrainingbccService;
+import org.apache.commons.lang.StringUtils;
+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.service.ITTrainingbccRegularService;
+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-06-24
+ */
+@RestController
+@RequestMapping("/training/bccregular")
+public class TTrainingbccRegularController extends BaseController
+{
+    @Autowired
+    private ITTrainingbccRegularService tTrainingbccRegularService;
+    @Autowired
+    private ISysDictTypeService iSysDictTypeService;
+    @Autowired
+    private ITTrainingbccService trainingbccService;
+
+    @Autowired
+    private ITTrainingbccDeviceService trainingbccDeviceService;
+
+    @Autowired
+    private ITStaffmgrService tStaffmgrService;
+    /**
+     * 查询装置培训计划列表
+     */
+    @PreAuthorize("@ss.hasPermi('training:bccregular:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(TTrainingbccRegular tTrainingRegular)
+    {
+        startPage();
+        List<TTrainingbccRegular> list = tTrainingbccRegularService.selectTTrainingbccRegularList(tTrainingRegular);
+        List<SysDictData> actualpost = iSysDictTypeService.selectDictDataByType("ACTUALPOST");
+        for (TTrainingbccRegular t : list) {
+            String[] actualpostId = new String[0];;
+            if (t.getActualpostId() != null) {
+                actualpostId = t.getActualpostId().split(",");
+            }
+            List<String> postStatu = new ArrayList<>();
+            for (SysDictData p : actualpost) {
+                int i = 0;
+                for (String a : actualpostId) {
+                    if (p.getDictValue().equals(a)) {
+                        i = 1;
+                    }
+                }
+                if (t.getDesignatedPosition() != null) {
+                    String[] designatedPosition = t.getDesignatedPosition().split(",");
+                    for (String d : designatedPosition) {
+                        if (p.getDictValue().equals(d)) {
+                            i = 2;
+                        }
+                    }
+                }
+                if (i == 1) {
+                    postStatu.add("M");
+                }else if (i == 2) {
+                    postStatu.add("|");
+                }else {
+                    postStatu.add("-");
+                }
+            }
+            if (t.getInvolvedMoc().equals("true")) {
+                if (t.getDesignatedOther() != null) {
+                    String[] designatedOther = t.getDesignatedOther().split(",");
+                    for (String d : designatedOther) {
+                        if (d.equals("28")) {
+                            postStatu.set(postStatu.size() - 5, "(M)");
+                        }
+                        if (d.equals("30")) {
+                            postStatu.set(postStatu.size() - 4, "(M)");
+                        }
+                        if (d.equals("32")) {
+                            postStatu.set(postStatu.size() - 3, "(M)");
+                        }
+                    }
+                }
+            }
+            t.setActualpost(postStatu);
+        }
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出装置培训计划列表
+     */
+    @PreAuthorize("@ss.hasPermi('training:bccregular:export')")
+    @Log(title = "装置培训计划", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(TTrainingbccRegular tTrainingbccRegular)
+    {
+        List<TTrainingbccRegular> list = tTrainingbccRegularService.selectTTrainingbccRegularList(tTrainingbccRegular);
+        ExcelUtil<TTrainingbccRegular> util = new ExcelUtil<TTrainingbccRegular>(TTrainingbccRegular.class);
+        return util.exportExcel(list, "bccregular");
+    }
+
+    /**
+     * 获取装置培训计划详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('training:bccregular:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return AjaxResult.success(tTrainingbccRegularService.selectTTrainingbccRegularById(id));
+    }
+
+    /**
+     * 新增装置培训计划
+     */
+    @PreAuthorize("@ss.hasPermi('training:bccregular:add')")
+    @Log(title = "装置培训计划", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody TTrainingbccRegular tTrainingRegular)
+    {
+        int doInsert = tTrainingbccRegularService.insertTTrainingbccRegular(tTrainingRegular);
+        logger.info("regular:" + tTrainingRegular);
+        //如果确定计划日期新增关联内容
+        if (tTrainingRegular.getNotPlan().equals("true")) {
+            //新增培训计划定期类
+            TTrainingbcc tTraining = new TTrainingbcc();
+            tTraining.setTrainingType("10");
+            tTraining.setYears(tTrainingRegular.getYear());
+            tTraining.setCourse(tTrainingRegular.getItem());
+            tTraining.setCourseid(tTrainingRegular.getCourseCode());
+            tTraining.setDuration(tTrainingRegular.getHour());
+            tTraining.setTrainer(tTrainingRegular.getLecturer());
+            tTraining.setPosition(tTrainingRegular.getActualpostId());
+            tTraining.setIsfinish(Long.parseLong("0"));
+            tTraining.setDeptId(tTrainingRegular.getDeptId());
+            tTraining.setRegularId(tTrainingRegular.getId());
+            trainingbccService.insertTTrainingbcc(tTraining);
+            Long trainingId = tTraining.getId();
+            //新增人员-装置级关系
+            // 参培岗位人员
+            if (tTrainingRegular.getActualpostId() != null) {
+                logger.info("参培岗位人员");
+                TStaffmgr staffmgr = new TStaffmgr();
+                staffmgr.setActualposts(tTrainingRegular.getActualpostId());
+                List<TStaffmgr> staffmgrs = tStaffmgrService.selectAllTStaffmgrList(staffmgr);
+                try {
+                    //判断离职
+                    if (!StringUtils.isEmpty(tTrainingRegular.getYear())) {
+                        Iterator<TStaffmgr> iterator = staffmgrs.iterator();
+                        while (iterator.hasNext()) {
+                            TStaffmgr t = iterator.next();
+                            if (t.getLeftDate() != null && t.getDelFlag() == 9){
+                                if (t.getLeftDate().getTime() - tTrainingRegular.getPlanTrainingdate().getTime() < 0l ) {
+                                    logger.debug(t.getName() + "离职时间小于培训时间");
+                                    iterator.remove();
+                                }
+                            }
+                        }
+                    }
+                }catch (Exception e) {
+                    logger.error(e.toString());
+                }
+                for (TStaffmgr s : staffmgrs) {
+                    TTrainingbccDevice tTrainingDevice = new TTrainingbccDevice();
+                    tTrainingDevice.setStaffId(s.getStaffid());
+                    tTrainingDevice.setRegularId(trainingId);
+                    tTrainingDevice.setStartDate(tTrainingRegular.getPlanTrainingdate());
+                    tTrainingDevice.setSupplementary("0");
+                    trainingbccDeviceService.insertTTrainingbccDevice(tTrainingDevice);
+                }
+            }
+            //指定岗位人员
+            if (tTrainingRegular.getDesignatedStaff() != null) {
+                logger.info("指定岗位人员");
+                String[] designatedStaffs = tTrainingRegular.getDesignatedStaff().split(",");
+                for (String staffId : designatedStaffs) {
+                    TTrainingbccDevice tTrainingDevice = new TTrainingbccDevice();
+                    tTrainingDevice.setStaffId(staffId);
+                    tTrainingDevice.setRegularId(trainingId);
+                    tTrainingDevice.setStartDate(tTrainingRegular.getPlanTrainingdate());
+                    tTrainingDevice.setSupplementary("0");
+                    trainingbccDeviceService.insertTTrainingbccDevice(tTrainingDevice);
+                }
+            }
+            //涉及其他部门
+            if (tTrainingRegular.getInvolvedMoc().equals("true")){
+                logger.info("涉及MOC人员");
+                TStaffmgr staffmgrMoc = new TStaffmgr();
+                staffmgrMoc.setActualposts(tTrainingRegular.getDesignatedOther());
+                List<TStaffmgr> staffmgrsMoc = tStaffmgrService.selectAllTStaffmgrList(staffmgrMoc);
+                try {
+                    //判断离职
+                    if (!StringUtils.isEmpty(tTrainingRegular.getYear())) {
+                        Iterator<TStaffmgr> iterator = staffmgrsMoc.iterator();
+                        while (iterator.hasNext()) {
+                            TStaffmgr t = iterator.next();
+                            if (t.getLeftDate() != null && t.getDelFlag() == 9){
+                                if (t.getLeftDate().getTime() - tTrainingRegular.getPlanTrainingdate().getTime() > 0l ) {
+                                    logger.debug(t.getName() + "离职时间小于培训时间");
+                                    iterator.remove();
+                                }
+                            }
+                        }
+                    }
+                }catch (Exception e) {
+                    logger.error(e.toString());
+                }
+                for (TStaffmgr s : staffmgrsMoc) {
+                    TTrainingbccDevice tTrainingDevice = new TTrainingbccDevice();
+                    tTrainingDevice.setStaffId(s.getStaffid());
+                    tTrainingDevice.setRegularId(trainingId);
+                    tTrainingDevice.setStartDate(tTrainingRegular.getPlanTrainingdate());
+                    tTrainingDevice.setSupplementary("0");
+                    trainingbccDeviceService.insertTTrainingbccDevice(tTrainingDevice);
+                }
+            }
+        }
+        return toAjax(doInsert);
+    }
+
+    /**
+     * 修改装置培训计划
+     */
+    @PreAuthorize("@ss.hasPermi('training:bccregular:edit')")
+    @Log(title = "装置培训计划", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody TTrainingbccRegular tTrainingbccRegular)
+    {
+        return toAjax(tTrainingbccRegularService.updateTTrainingbccRegular(tTrainingbccRegular));
+    }
+
+    /**
+     * 删除装置培训计划
+     */
+    @PreAuthorize("@ss.hasPermi('training:bccregular:remove')")
+    @Log(title = "装置培训计划", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(tTrainingbccRegularService.deleteTTrainingbccRegularByIds(ids));
+    }
+}

+ 349 - 0
master/src/main/java/com/ruoyi/project/training/domain/TTrainingbccRegular.java

@@ -0,0 +1,349 @@
+package com.ruoyi.project.training.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_trainingbcc_regular
+ *
+ * @author ssy
+ * @date 2024-06-24
+ */
+public class TTrainingbccRegular extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 唯一标识ID */
+    private Long id;
+
+    /** 课程代码 */
+    @Excel(name = "课程代码")
+    private String courseCode;
+
+    /** 课程名称 */
+    @Excel(name = "课程名称")
+    private String item;
+
+    /** 需参培岗位 */
+    @Excel(name = "需参培岗位")
+    private String actualpostId;
+
+    /** 岗位 */
+    private List<String> actualpost;
+
+    /** 备注 */
+    @Excel(name = "备注")
+    private String remarks;
+
+    /** 删除状态 */
+    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;
+
+    /** 计划培训时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd" , timezone = "GMT+8")
+    @Excel(name = "计划培训时间", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date planTrainingdate;
+
+    /** 实际完成培训日期 */
+    @JsonFormat(pattern = "yyyy-MM-dd" , timezone = "GMT+8")
+    @Excel(name = "实际完成培训日期", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date actualCompletedate;
+
+    /** 授课人 */
+    @Excel(name = "授课人")
+    private String lecturer;
+
+    /** 课时 */
+    @Excel(name = "课时")
+    private String hour;
+
+    /** 年份 */
+    @Excel(name = "年份")
+    private String year;
+
+    /** 指定岗位 */
+    @Excel(name = "指定岗位")
+    private String designatedPosition;
+
+    /** 指定人员 */
+    @Excel(name = "指定人员")
+    private String designatedStaff;
+
+    /** 是否涉及其他部门 */
+    @Excel(name = "是否涉及其他部门")
+    private String involvedMoc;
+
+    /** 不存在计划日期 */
+    @Excel(name = "不存在计划日期")
+    private String notPlan;
+
+    /** 不确定日期时培训计划日期显示字段 */
+    @Excel(name = "不确定日期时培训计划日期显示字段")
+    private String notTrainingdate;
+
+    /** 指定其他部门 */
+    @Excel(name = "指定其他部门")
+    private String designatedOther;
+
+    public List<String> getActualpost() {
+        return actualpost;
+    }
+
+    public void setActualpost(List<String> actualpost) {
+        this.actualpost = actualpost;
+    }
+
+    public void setId(Long id)
+    {
+        this.id = id;
+    }
+
+    public Long getId()
+    {
+        return id;
+    }
+    public void setCourseCode(String courseCode)
+    {
+        this.courseCode = courseCode;
+    }
+
+    public String getCourseCode()
+    {
+        return courseCode;
+    }
+    public void setItem(String item)
+    {
+        this.item = item;
+    }
+
+    public String getItem()
+    {
+        return item;
+    }
+    public void setActualpostId(String actualpostId)
+    {
+        this.actualpostId = actualpostId;
+    }
+
+    public String getActualpostId()
+    {
+        return actualpostId;
+    }
+    public void setRemarks(String remarks)
+    {
+        this.remarks = remarks;
+    }
+
+    public String getRemarks()
+    {
+        return remarks;
+    }
+    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 setPlanTrainingdate(Date planTrainingdate)
+    {
+        this.planTrainingdate = planTrainingdate;
+    }
+
+    public Date getPlanTrainingdate()
+    {
+        return planTrainingdate;
+    }
+    public void setActualCompletedate(Date actualCompletedate)
+    {
+        this.actualCompletedate = actualCompletedate;
+    }
+
+    public Date getActualCompletedate()
+    {
+        return actualCompletedate;
+    }
+    public void setLecturer(String lecturer)
+    {
+        this.lecturer = lecturer;
+    }
+
+    public String getLecturer()
+    {
+        return lecturer;
+    }
+    public void setHour(String hour)
+    {
+        this.hour = hour;
+    }
+
+    public String getHour()
+    {
+        return hour;
+    }
+    public void setYear(String year)
+    {
+        this.year = year;
+    }
+
+    public String getYear()
+    {
+        return year;
+    }
+    public void setDesignatedPosition(String designatedPosition)
+    {
+        this.designatedPosition = designatedPosition;
+    }
+
+    public String getDesignatedPosition()
+    {
+        return designatedPosition;
+    }
+    public void setDesignatedStaff(String designatedStaff)
+    {
+        this.designatedStaff = designatedStaff;
+    }
+
+    public String getDesignatedStaff()
+    {
+        return designatedStaff;
+    }
+    public void setInvolvedMoc(String involvedMoc)
+    {
+        this.involvedMoc = involvedMoc;
+    }
+
+    public String getInvolvedMoc()
+    {
+        return involvedMoc;
+    }
+    public void setNotPlan(String notPlan)
+    {
+        this.notPlan = notPlan;
+    }
+
+    public String getNotPlan()
+    {
+        return notPlan;
+    }
+    public void setNotTrainingdate(String notTrainingdate)
+    {
+        this.notTrainingdate = notTrainingdate;
+    }
+
+    public String getNotTrainingdate()
+    {
+        return notTrainingdate;
+    }
+    public void setDesignatedOther(String designatedOther)
+    {
+        this.designatedOther = designatedOther;
+    }
+
+    public String getDesignatedOther()
+    {
+        return designatedOther;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("id", getId())
+            .append("courseCode", getCourseCode())
+            .append("item", getItem())
+            .append("actualpostId", getActualpostId())
+            .append("remarks", getRemarks())
+            .append("delFlag", getDelFlag())
+            .append("createrCode", getCreaterCode())
+            .append("createdate", getCreatedate())
+            .append("updaterCode", getUpdaterCode())
+            .append("updatedate", getUpdatedate())
+            .append("deptId", getDeptId())
+            .append("planTrainingdate", getPlanTrainingdate())
+            .append("actualCompletedate", getActualCompletedate())
+            .append("lecturer", getLecturer())
+            .append("hour", getHour())
+            .append("year", getYear())
+            .append("designatedPosition", getDesignatedPosition())
+            .append("designatedStaff", getDesignatedStaff())
+            .append("involvedMoc", getInvolvedMoc())
+            .append("notPlan", getNotPlan())
+            .append("notTrainingdate", getNotTrainingdate())
+            .append("designatedOther", getDesignatedOther())
+            .toString();
+    }
+}

+ 187 - 0
master/src/main/java/com/ruoyi/project/training/elearn/controller/TElRecordController.java

@@ -0,0 +1,187 @@
+package com.ruoyi.project.training.elearn.controller;
+
+import java.util.List;
+
+import com.alibaba.fastjson.JSON;
+import com.ruoyi.project.plant.domain.TStaffmgr;
+import com.ruoyi.project.plant.mapper.TStaffmgrMapper;
+import com.ruoyi.project.system.domain.SysUser;
+import com.ruoyi.project.system.mapper.SysUserMapper;
+import com.ruoyi.project.training.domain.TWorkcertificateCbps;
+import com.ruoyi.project.training.elearn.mapper.TElRecordMapper;
+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.TElRecord;
+import com.ruoyi.project.training.elearn.service.ITElRecordService;
+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;
+
+import javax.annotation.Resource;
+
+/**
+ * 岗位培训统计Controller
+ *
+ * @author ssy
+ * @date 2024-06-25
+ */
+@RestController
+@RequestMapping("/elearn/record")
+public class TElRecordController extends BaseController
+{
+    @Autowired
+    private ITElRecordService tElRecordService;
+    @Resource
+    private TElRecordMapper tElRecordMapper;
+    @Resource
+    private TStaffmgrMapper tStaffmgrMapper;
+    @Resource
+    private SysUserMapper sysUserMapper;
+    /**
+     * 查询岗位培训统计列表
+     */
+    @PreAuthorize("@ss.hasPermi('elearn:record:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(TElRecord tElRecord)
+    {
+        try {
+            //  同步人员
+            syncUser();
+        }catch (Exception e) {
+            e.printStackTrace();
+        };
+        startPage();
+        List<TElRecord> list = tElRecordService.selectTElRecordList(tElRecord);
+        return getDataTable(list);
+    }
+
+    /**
+     * 查询岗位培训统计列表
+     */
+    @PreAuthorize("@ss.hasPermi('elearn:record:list')")
+    @GetMapping("/syncRecord")
+    public AjaxResult syncRecord(TElRecord tElRecord)
+    {
+        syncRecord();
+        return AjaxResult.success();
+    }
+
+    private void syncUser() {
+       List<String> delList = tElRecordMapper.queryNeedDeleteIds();
+        if (delList.size() > 0){
+            for (String staffId : delList
+            ) {
+                tElRecordMapper.deleteTElRecordByStaffId(staffId);
+            }
+        }
+       List<String> addList = tElRecordMapper.queryNeedInsertIds();
+        if (addList.size() > 0) {
+            for (String id: addList
+            ) {
+
+                TStaffmgr staffmgr = tStaffmgrMapper.selectTStaffmgrByStaffId(id);
+                SysUser sysUser = sysUserMapper.selectUserByStaffId(staffmgr.getStaffid());
+
+                TElRecord t = new TElRecord();
+                t.setStaffId(staffmgr.getStaffid());
+                t.setClasses(staffmgr.getTeam());
+                t.setName(staffmgr.getName());
+                t.setDeptId(staffmgr.getDeptId());
+                t.setPlantCode(staffmgr.getPlantCode());
+                if (sysUser != null) {
+                    t.setUserId(sysUser.getUserId());
+                }
+                tElRecordMapper.insertTElRecord(t);
+            }
+        }
+
+
+    }
+
+    private void syncRecord(){
+        TElRecord tElRecord = new TElRecord();
+        List<TElRecord> list = tElRecordService.selectTElRecordList(tElRecord);
+
+        for (TElRecord t: list
+             ) {
+            if (t.getUserId() != null) {
+                TElRecord quData = tElRecordMapper.queryQuData(t.getUserId());
+                TElRecord exmaData = tElRecordMapper.queryExamData(t.getUserId());
+                t.setQuTotal(quData.getQuTotal());
+                t.setQuRight(quData.getQuRight());
+                t.setExamTotal(exmaData.getExamTotal());
+                t.setExamPassed(exmaData.getExamPassed());
+                tElRecordMapper.updateTElRecord(t);
+            }
+        }
+
+
+
+    }
+    /**
+     * 导出岗位培训统计列表
+     */
+    @PreAuthorize("@ss.hasPermi('elearn:record:export')")
+    @Log(title = "岗位培训统计", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(TElRecord tElRecord)
+    {
+        List<TElRecord> list = tElRecordService.selectTElRecordList(tElRecord);
+        ExcelUtil<TElRecord> util = new ExcelUtil<TElRecord>(TElRecord.class);
+        return util.exportExcel(list, "record");
+    }
+
+    /**
+     * 获取岗位培训统计详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('elearn:record:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return AjaxResult.success(tElRecordService.selectTElRecordById(id));
+    }
+
+    /**
+     * 新增岗位培训统计
+     */
+    @PreAuthorize("@ss.hasPermi('elearn:record:add')")
+    @Log(title = "岗位培训统计", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody TElRecord tElRecord)
+    {
+        return toAjax(tElRecordService.insertTElRecord(tElRecord));
+    }
+
+    /**
+     * 修改岗位培训统计
+     */
+    @PreAuthorize("@ss.hasPermi('elearn:record:edit')")
+    @Log(title = "岗位培训统计", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody TElRecord tElRecord)
+    {
+        return toAjax(tElRecordService.updateTElRecord(tElRecord));
+    }
+
+    /**
+     * 删除岗位培训统计
+     */
+    @PreAuthorize("@ss.hasPermi('elearn:record:remove')")
+    @Log(title = "岗位培训统计", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(tElRecordService.deleteTElRecordByIds(ids));
+    }
+}

+ 268 - 0
master/src/main/java/com/ruoyi/project/training/elearn/domain/TElRecord.java

@@ -0,0 +1,268 @@
+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_record
+ *
+ * @author ssy
+ * @date 2024-06-25
+ */
+public class TElRecord extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 唯一标识ID */
+    private Long id;
+
+    /** 装置名称 */
+    @Excel(name = "装置名称")
+    private String plantCode;
+
+    /** 姓名 */
+    @Excel(name = "姓名")
+    private String name;
+
+    /** 员工号 */
+    @Excel(name = "员工号")
+    private String staffId;
+    private Long userId;
+    /** 班组 */
+    @Excel(name = "班组")
+    private String classes;
+
+    /** 删除状态 */
+    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 String remarks;
+
+    /** 部门编号 */
+    @Excel(name = "部门编号")
+    private Long deptId;
+
+    /** 答题总数 */
+    @Excel(name = "答题总数")
+    private Integer quTotal;
+
+    /** 正确数 */
+    @Excel(name = "正确数")
+    private Integer quRight;
+
+    /** 考试次数 */
+    @Excel(name = "考试次数")
+    private Integer examTotal;
+
+    /** 考试通过次数 */
+    @Excel(name = "考试通过次数")
+    private Integer examPassed;
+
+    private String actualpost;
+
+    public String getActualpost() {
+        return actualpost;
+    }
+
+    public void setActualpost(String actualpost) {
+        this.actualpost = actualpost;
+    }
+
+    public void setId(Long id)
+    {
+        this.id = id;
+    }
+
+    public Long getId()
+    {
+        return id;
+    }
+    public void setPlantCode(String plantCode)
+    {
+        this.plantCode = plantCode;
+    }
+
+    public String getPlantCode()
+    {
+        return plantCode;
+    }
+    public void setName(String name)
+    {
+        this.name = name;
+    }
+
+    public String getName()
+    {
+        return name;
+    }
+    public void setStaffId(String staffId)
+    {
+        this.staffId = staffId;
+    }
+
+    public String getStaffId()
+    {
+        return staffId;
+    }
+    public void setClasses(String classes)
+    {
+        this.classes = classes;
+    }
+
+    public String getClasses()
+    {
+        return classes;
+    }
+    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 setRemarks(String remarks)
+    {
+        this.remarks = remarks;
+    }
+
+    public String getRemarks()
+    {
+        return remarks;
+    }
+
+    public Long getDeptId() {
+        return deptId;
+    }
+
+    public void setDeptId(Long deptId) {
+        this.deptId = deptId;
+    }
+
+    public void setQuTotal(Integer quTotal)
+    {
+        this.quTotal = quTotal;
+    }
+
+    public Integer getQuTotal()
+    {
+        return quTotal;
+    }
+    public void setQuRight(Integer quRight)
+    {
+        this.quRight = quRight;
+    }
+
+    public Integer getQuRight()
+    {
+        return quRight;
+    }
+    public void setExamTotal(Integer examTotal)
+    {
+        this.examTotal = examTotal;
+    }
+
+    public Integer getExamTotal()
+    {
+        return examTotal;
+    }
+    public void setExamPassed(Integer examPassed)
+    {
+        this.examPassed = examPassed;
+    }
+
+    public Integer getExamPassed()
+    {
+        return examPassed;
+    }
+
+    public Long getUserId() {
+        return userId;
+    }
+
+    public void setUserId(Long userId) {
+        this.userId = userId;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("id", getId())
+            .append("plantCode", getPlantCode())
+            .append("name", getName())
+            .append("staffId", getStaffId())
+            .append("classes", getClasses())
+            .append("delFlag", getDelFlag())
+            .append("createrCode", getCreaterCode())
+            .append("createdate", getCreatedate())
+            .append("updaterCode", getUpdaterCode())
+            .append("updatedate", getUpdatedate())
+            .append("remarks", getRemarks())
+            .append("deptId", getDeptId())
+            .append("quTotal", getQuTotal())
+            .append("quRight", getQuRight())
+            .append("examTotal", getExamTotal())
+            .append("examPassed", getExamPassed())
+            .toString();
+    }
+}

+ 73 - 0
master/src/main/java/com/ruoyi/project/training/elearn/mapper/TElRecordMapper.java

@@ -0,0 +1,73 @@
+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.TElRecord;
+
+/**
+ * 岗位培训统计Mapper接口
+ *
+ * @author ssy
+ * @date 2024-06-25
+ */
+public interface TElRecordMapper
+{
+    /**
+     * 查询岗位培训统计
+     *
+     * @param id 岗位培训统计ID
+     * @return 岗位培训统计
+     */
+    public TElRecord selectTElRecordById(Long id);
+
+    /**
+     * 查询岗位培训统计列表
+     *
+     * @param tElRecord 岗位培训统计
+     * @return 岗位培训统计集合
+     */
+    @DataScope(deptAlias = "d")
+    public List<TElRecord> selectTElRecordList(TElRecord tElRecord);
+
+    /**
+     * 新增岗位培训统计
+     *
+     * @param tElRecord 岗位培训统计
+     * @return 结果
+     */
+    public int insertTElRecord(TElRecord tElRecord);
+
+    /**
+     * 修改岗位培训统计
+     *
+     * @param tElRecord 岗位培训统计
+     * @return 结果
+     */
+    public int updateTElRecord(TElRecord tElRecord);
+
+    /**
+     * 删除岗位培训统计
+     *
+     * @param id 岗位培训统计ID
+     * @return 结果
+     */
+    public int deleteTElRecordById(Long id);
+
+    /**
+     * 批量删除岗位培训统计
+     *
+     * @param ids 需要删除的数据ID
+     * @return 结果
+     */
+    public int deleteTElRecordByIds(Long[] ids);
+
+    List<String> queryNeedDeleteIds();
+
+    List<String> queryNeedInsertIds();
+
+    void deleteTElRecordByStaffId(String staffId);
+
+    TElRecord queryQuData(Long id);
+
+    TElRecord queryExamData(Long userId);
+}

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

@@ -0,0 +1,61 @@
+package com.ruoyi.project.training.elearn.service;
+
+import java.util.List;
+import com.ruoyi.project.training.elearn.domain.TElRecord;
+
+/**
+ * 岗位培训统计Service接口
+ *
+ * @author ssy
+ * @date 2024-06-25
+ */
+public interface ITElRecordService
+{
+    /**
+     * 查询岗位培训统计
+     *
+     * @param id 岗位培训统计ID
+     * @return 岗位培训统计
+     */
+    public TElRecord selectTElRecordById(Long id);
+
+    /**
+     * 查询岗位培训统计列表
+     *
+     * @param tElRecord 岗位培训统计
+     * @return 岗位培训统计集合
+     */
+    public List<TElRecord> selectTElRecordList(TElRecord tElRecord);
+
+    /**
+     * 新增岗位培训统计
+     *
+     * @param tElRecord 岗位培训统计
+     * @return 结果
+     */
+    public int insertTElRecord(TElRecord tElRecord);
+
+    /**
+     * 修改岗位培训统计
+     *
+     * @param tElRecord 岗位培训统计
+     * @return 结果
+     */
+    public int updateTElRecord(TElRecord tElRecord);
+
+    /**
+     * 批量删除岗位培训统计
+     *
+     * @param ids 需要删除的岗位培训统计ID
+     * @return 结果
+     */
+    public int deleteTElRecordByIds(Long[] ids);
+
+    /**
+     * 删除岗位培训统计信息
+     *
+     * @param id 岗位培训统计ID
+     * @return 结果
+     */
+    public int deleteTElRecordById(Long id);
+}

+ 93 - 0
master/src/main/java/com/ruoyi/project/training/elearn/service/impl/TElRecordServiceImpl.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.TElRecordMapper;
+import com.ruoyi.project.training.elearn.domain.TElRecord;
+import com.ruoyi.project.training.elearn.service.ITElRecordService;
+
+/**
+ * 岗位培训统计Service业务层处理
+ *
+ * @author ssy
+ * @date 2024-06-25
+ */
+@Service
+public class TElRecordServiceImpl implements ITElRecordService
+{
+    @Autowired
+    private TElRecordMapper tElRecordMapper;
+
+    /**
+     * 查询岗位培训统计
+     *
+     * @param id 岗位培训统计ID
+     * @return 岗位培训统计
+     */
+    @Override
+    public TElRecord selectTElRecordById(Long id)
+    {
+        return tElRecordMapper.selectTElRecordById(id);
+    }
+
+    /**
+     * 查询岗位培训统计列表
+     *
+     * @param tElRecord 岗位培训统计
+     * @return 岗位培训统计
+     */
+    @Override
+    public List<TElRecord> selectTElRecordList(TElRecord tElRecord)
+    {
+        return tElRecordMapper.selectTElRecordList(tElRecord);
+    }
+
+    /**
+     * 新增岗位培训统计
+     *
+     * @param tElRecord 岗位培训统计
+     * @return 结果
+     */
+    @Override
+    public int insertTElRecord(TElRecord tElRecord)
+    {
+        return tElRecordMapper.insertTElRecord(tElRecord);
+    }
+
+    /**
+     * 修改岗位培训统计
+     *
+     * @param tElRecord 岗位培训统计
+     * @return 结果
+     */
+    @Override
+    public int updateTElRecord(TElRecord tElRecord)
+    {
+        return tElRecordMapper.updateTElRecord(tElRecord);
+    }
+
+    /**
+     * 批量删除岗位培训统计
+     *
+     * @param ids 需要删除的岗位培训统计ID
+     * @return 结果
+     */
+    @Override
+    public int deleteTElRecordByIds(Long[] ids)
+    {
+        return tElRecordMapper.deleteTElRecordByIds(ids);
+    }
+
+    /**
+     * 删除岗位培训统计信息
+     *
+     * @param id 岗位培训统计ID
+     * @return 结果
+     */
+    @Override
+    public int deleteTElRecordById(Long id)
+    {
+        return tElRecordMapper.deleteTElRecordById(id);
+    }
+}

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

@@ -0,0 +1,63 @@
+package com.ruoyi.project.training.mapper;
+
+import java.util.List;
+import com.ruoyi.framework.aspectj.lang.annotation.DataScope;
+import com.ruoyi.project.training.domain.TTrainingbccRegular;
+
+/**
+ * 装置培训计划Mapper接口
+ *
+ * @author ssy
+ * @date 2024-06-24
+ */
+public interface TTrainingbccRegularMapper
+{
+    /**
+     * 查询装置培训计划
+     *
+     * @param id 装置培训计划ID
+     * @return 装置培训计划
+     */
+    public TTrainingbccRegular selectTTrainingbccRegularById(Long id);
+
+    /**
+     * 查询装置培训计划列表
+     *
+     * @param tTrainingbccRegular 装置培训计划
+     * @return 装置培训计划集合
+     */
+    @DataScope(deptAlias = "d")
+    public List<TTrainingbccRegular> selectTTrainingbccRegularList(TTrainingbccRegular tTrainingbccRegular);
+
+    /**
+     * 新增装置培训计划
+     *
+     * @param tTrainingbccRegular 装置培训计划
+     * @return 结果
+     */
+    public int insertTTrainingbccRegular(TTrainingbccRegular tTrainingbccRegular);
+
+    /**
+     * 修改装置培训计划
+     *
+     * @param tTrainingbccRegular 装置培训计划
+     * @return 结果
+     */
+    public int updateTTrainingbccRegular(TTrainingbccRegular tTrainingbccRegular);
+
+    /**
+     * 删除装置培训计划
+     *
+     * @param id 装置培训计划ID
+     * @return 结果
+     */
+    public int deleteTTrainingbccRegularById(Long id);
+
+    /**
+     * 批量删除装置培训计划
+     *
+     * @param ids 需要删除的数据ID
+     * @return 结果
+     */
+    public int deleteTTrainingbccRegularByIds(Long[] ids);
+}

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

@@ -0,0 +1,61 @@
+package com.ruoyi.project.training.service;
+
+import java.util.List;
+import com.ruoyi.project.training.domain.TTrainingbccRegular;
+
+/**
+ * 装置培训计划Service接口
+ *
+ * @author ssy
+ * @date 2024-06-24
+ */
+public interface ITTrainingbccRegularService
+{
+    /**
+     * 查询装置培训计划
+     *
+     * @param id 装置培训计划ID
+     * @return 装置培训计划
+     */
+    public TTrainingbccRegular selectTTrainingbccRegularById(Long id);
+
+    /**
+     * 查询装置培训计划列表
+     *
+     * @param tTrainingbccRegular 装置培训计划
+     * @return 装置培训计划集合
+     */
+    public List<TTrainingbccRegular> selectTTrainingbccRegularList(TTrainingbccRegular tTrainingbccRegular);
+
+    /**
+     * 新增装置培训计划
+     *
+     * @param tTrainingbccRegular 装置培训计划
+     * @return 结果
+     */
+    public int insertTTrainingbccRegular(TTrainingbccRegular tTrainingbccRegular);
+
+    /**
+     * 修改装置培训计划
+     *
+     * @param tTrainingbccRegular 装置培训计划
+     * @return 结果
+     */
+    public int updateTTrainingbccRegular(TTrainingbccRegular tTrainingbccRegular);
+
+    /**
+     * 批量删除装置培训计划
+     *
+     * @param ids 需要删除的装置培训计划ID
+     * @return 结果
+     */
+    public int deleteTTrainingbccRegularByIds(Long[] ids);
+
+    /**
+     * 删除装置培训计划信息
+     *
+     * @param id 装置培训计划ID
+     * @return 结果
+     */
+    public int deleteTTrainingbccRegularById(Long id);
+}

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

@@ -0,0 +1,93 @@
+package com.ruoyi.project.training.service.impl;
+
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.ruoyi.project.training.mapper.TTrainingbccRegularMapper;
+import com.ruoyi.project.training.domain.TTrainingbccRegular;
+import com.ruoyi.project.training.service.ITTrainingbccRegularService;
+
+/**
+ * 装置培训计划Service业务层处理
+ *
+ * @author ssy
+ * @date 2024-06-24
+ */
+@Service
+public class TTrainingbccRegularServiceImpl implements ITTrainingbccRegularService
+{
+    @Autowired
+    private TTrainingbccRegularMapper tTrainingbccRegularMapper;
+
+    /**
+     * 查询装置培训计划
+     *
+     * @param id 装置培训计划ID
+     * @return 装置培训计划
+     */
+    @Override
+    public TTrainingbccRegular selectTTrainingbccRegularById(Long id)
+    {
+        return tTrainingbccRegularMapper.selectTTrainingbccRegularById(id);
+    }
+
+    /**
+     * 查询装置培训计划列表
+     *
+     * @param tTrainingbccRegular 装置培训计划
+     * @return 装置培训计划
+     */
+    @Override
+    public List<TTrainingbccRegular> selectTTrainingbccRegularList(TTrainingbccRegular tTrainingbccRegular)
+    {
+        return tTrainingbccRegularMapper.selectTTrainingbccRegularList(tTrainingbccRegular);
+    }
+
+    /**
+     * 新增装置培训计划
+     *
+     * @param tTrainingbccRegular 装置培训计划
+     * @return 结果
+     */
+    @Override
+    public int insertTTrainingbccRegular(TTrainingbccRegular tTrainingbccRegular)
+    {
+        return tTrainingbccRegularMapper.insertTTrainingbccRegular(tTrainingbccRegular);
+    }
+
+    /**
+     * 修改装置培训计划
+     *
+     * @param tTrainingbccRegular 装置培训计划
+     * @return 结果
+     */
+    @Override
+    public int updateTTrainingbccRegular(TTrainingbccRegular tTrainingbccRegular)
+    {
+        return tTrainingbccRegularMapper.updateTTrainingbccRegular(tTrainingbccRegular);
+    }
+
+    /**
+     * 批量删除装置培训计划
+     *
+     * @param ids 需要删除的装置培训计划ID
+     * @return 结果
+     */
+    @Override
+    public int deleteTTrainingbccRegularByIds(Long[] ids)
+    {
+        return tTrainingbccRegularMapper.deleteTTrainingbccRegularByIds(ids);
+    }
+
+    /**
+     * 删除装置培训计划信息
+     *
+     * @param id 装置培训计划ID
+     * @return 结果
+     */
+    @Override
+    public int deleteTTrainingbccRegularById(Long id)
+    {
+        return tTrainingbccRegularMapper.deleteTTrainingbccRegularById(id);
+    }
+}

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

@@ -20,7 +20,7 @@ ruoyi:
 # 开发环境配置
 server:
   # 服务器的HTTP端口,默认为8080
-  port: 8080
+  port: 8090
   servlet:
     # 应用的访问路径
     context-path: /
@@ -193,7 +193,7 @@ gen:
   # 作者
   author: ssy
   # 默认生成包路径 system 需改成自己的模块名称 如 system monitor tool
-  packageName: com.ruoyi.project.training # 自动去除表前缀,默认是true
+  packageName: com.ruoyi.project.training.elearn # 自动去除表前缀,默认是true
   autoRemovePre: false
   # 表前缀(生成类名不会包含表前缀,多个用逗号分隔)
   tablePrefix: sys_

+ 165 - 0
master/src/main/resources/mybatis/training/TTrainingbccRegularMapper.xml

@@ -0,0 +1,165 @@
+<?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.mapper.TTrainingbccRegularMapper">
+
+    <resultMap type="TTrainingbccRegular" id="TTrainingbccRegularResult">
+        <result property="id"    column="id"    />
+        <result property="courseCode"    column="course_code"    />
+        <result property="item"    column="item"    />
+        <result property="actualpostId"    column="actualpost_id"    />
+        <result property="remarks"    column="remarks"    />
+        <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="planTrainingdate"    column="plan_trainingdate"    />
+        <result property="actualCompletedate"    column="actual_completedate"    />
+        <result property="lecturer"    column="lecturer"    />
+        <result property="hour"    column="hour"    />
+        <result property="year"    column="year"    />
+        <result property="designatedPosition"    column="designated_position"    />
+        <result property="designatedStaff"    column="designated_staff"    />
+        <result property="involvedMoc"    column="involved_moc"    />
+        <result property="notPlan"    column="not_plan"    />
+        <result property="notTrainingdate"    column="not_trainingdate"    />
+        <result property="designatedOther"    column="designated_other"    />
+        <result property="deptName" column="dept_name" />
+    </resultMap>
+
+    <sql id="selectTTrainingbccRegularVo">
+        select d.id, d.course_code, d.item, d.actualpost_id, d.remarks, d.del_flag, d.creater_code, d.createdate, d.updater_code, d.updatedate, d.dept_id, d.plan_trainingdate, d.actual_completedate, d.lecturer, d.hour, d.year, d.designated_position, d.designated_staff, d.involved_moc, d.not_plan, d.not_trainingdate, d.designated_other  from t_trainingbcc_regular d
+    </sql>
+
+    <select id="selectTTrainingbccRegularList" parameterType="TTrainingbccRegular" resultMap="TTrainingbccRegularResult">
+        <include refid="selectTTrainingbccRegularVo"/>
+        <where>
+            <if test="courseCode != null  and courseCode != ''"> and course_code = #{courseCode}</if>
+            <if test="item != null  and item != ''"> and item = #{item}</if>
+            <if test="actualpostId != null  and actualpostId != ''"> and actualpost_id = #{actualpostId}</if>
+            <if test="remarks != null  and remarks != ''"> and remarks = #{remarks}</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="planTrainingdate != null "> and plan_trainingdate = #{planTrainingdate}</if>
+            <if test="actualCompletedate != null "> and actual_completedate = #{actualCompletedate}</if>
+            <if test="lecturer != null  and lecturer != ''"> and lecturer = #{lecturer}</if>
+            <if test="hour != null  and hour != ''"> and hour = #{hour}</if>
+            <if test="year != null  and year != ''"> and year = #{year}</if>
+            <if test="designatedPosition != null  and designatedPosition != ''"> and designated_position = #{designatedPosition}</if>
+            <if test="designatedStaff != null  and designatedStaff != ''"> and designated_staff = #{designatedStaff}</if>
+            <if test="involvedMoc != null  and involvedMoc != ''"> and involved_moc = #{involvedMoc}</if>
+            <if test="notPlan != null  and notPlan != ''"> and not_plan = #{notPlan}</if>
+            <if test="notTrainingdate != null  and notTrainingdate != ''"> and not_trainingdate = #{notTrainingdate}</if>
+            <if test="designatedOther != null  and designatedOther != ''"> and designated_other = #{designatedOther}</if>
+            and d.del_flag = 0
+        </where>
+        <!-- 数据范围过滤 -->
+        ${params.dataScope}
+    </select>
+
+    <select id="selectTTrainingbccRegularById" parameterType="Long" resultMap="TTrainingbccRegularResult">
+        <include refid="selectTTrainingbccRegularVo"/>
+        where id = #{id}
+    </select>
+
+    <insert id="insertTTrainingbccRegular" parameterType="TTrainingbccRegular">
+        <selectKey keyProperty="id" resultType="long" order="BEFORE">
+            SELECT seq_t_trainingbcc_regular.NEXTVAL as id FROM DUAL
+        </selectKey>
+        insert into t_trainingbcc_regular
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="id != null">id,</if>
+            <if test="courseCode != null">course_code,</if>
+            <if test="item != null">item,</if>
+            <if test="actualpostId != null">actualpost_id,</if>
+            <if test="remarks != null">remarks,</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="planTrainingdate != null">plan_trainingdate,</if>
+            <if test="actualCompletedate != null">actual_completedate,</if>
+            <if test="lecturer != null">lecturer,</if>
+            <if test="hour != null">hour,</if>
+            <if test="year != null">year,</if>
+            <if test="designatedPosition != null">designated_position,</if>
+            <if test="designatedStaff != null">designated_staff,</if>
+            <if test="involvedMoc != null">involved_moc,</if>
+            <if test="notPlan != null">not_plan,</if>
+            <if test="notTrainingdate != null">not_trainingdate,</if>
+            <if test="designatedOther != null">designated_other,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="id != null">#{id},</if>
+            <if test="courseCode != null">#{courseCode},</if>
+            <if test="item != null">#{item},</if>
+            <if test="actualpostId != null">#{actualpostId},</if>
+            <if test="remarks != null">#{remarks},</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="planTrainingdate != null">#{planTrainingdate},</if>
+            <if test="actualCompletedate != null">#{actualCompletedate},</if>
+            <if test="lecturer != null">#{lecturer},</if>
+            <if test="hour != null">#{hour},</if>
+            <if test="year != null">#{year},</if>
+            <if test="designatedPosition != null">#{designatedPosition},</if>
+            <if test="designatedStaff != null">#{designatedStaff},</if>
+            <if test="involvedMoc != null">#{involvedMoc},</if>
+            <if test="notPlan != null">#{notPlan},</if>
+            <if test="notTrainingdate != null">#{notTrainingdate},</if>
+            <if test="designatedOther != null">#{designatedOther},</if>
+         </trim>
+    </insert>
+
+    <update id="updateTTrainingbccRegular" parameterType="TTrainingbccRegular">
+        update t_trainingbcc_regular
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="courseCode != null">course_code = #{courseCode},</if>
+            <if test="item != null">item = #{item},</if>
+            <if test="actualpostId != null">actualpost_id = #{actualpostId},</if>
+            <if test="remarks != null">remarks = #{remarks},</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="planTrainingdate != null">plan_trainingdate = #{planTrainingdate},</if>
+            <if test="actualCompletedate != null">actual_completedate = #{actualCompletedate},</if>
+            <if test="lecturer != null">lecturer = #{lecturer},</if>
+            <if test="hour != null">hour = #{hour},</if>
+            <if test="year != null">year = #{year},</if>
+            <if test="designatedPosition != null">designated_position = #{designatedPosition},</if>
+            <if test="designatedStaff != null">designated_staff = #{designatedStaff},</if>
+            <if test="involvedMoc != null">involved_moc = #{involvedMoc},</if>
+            <if test="notPlan != null">not_plan = #{notPlan},</if>
+            <if test="notTrainingdate != null">not_trainingdate = #{notTrainingdate},</if>
+            <if test="designatedOther != null">designated_other = #{designatedOther},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <update id="deleteTTrainingbccRegularById" parameterType="Long">
+        update t_trainingbcc_regular set del_flag = 2 where id = #{id}
+    </update>
+
+    <update id="deleteTTrainingbccRegularByIds" parameterType="String">
+        update t_trainingbcc_regular set del_flag = 2 where id in
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </update>
+
+</mapper>

+ 185 - 0
master/src/main/resources/mybatis/training/elearn/TElRecordMapper.xml

@@ -0,0 +1,185 @@
+<?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.TElRecordMapper">
+
+    <resultMap type="TElRecord" id="TElRecordResult">
+        <result property="id"    column="id"    />
+        <result property="plantCode"    column="plant_code"    />
+        <result property="name"    column="name"    />
+        <result property="staffId"    column="staff_id"    />
+        <result property="userId"    column="user_id"    />
+        <result property="classes"    column="classes"    />
+        <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="remarks"    column="remarks"    />
+        <result property="deptId"    column="dept_id"    />
+        <result property="quTotal"    column="qu_total"    />
+        <result property="quRight"    column="qu_right"    />
+        <result property="examTotal"    column="exam_total"    />
+        <result property="examPassed"    column="exam_passed"    />
+        <result property="deptName" column="dept_name" />
+    </resultMap>
+
+    <sql id="selectTElRecordVo">
+        select d.id, d.plant_code, d.name, d.staff_id,d.user_id, d.classes, d.del_flag, d.creater_code, d.createdate, d.updater_code, d.updatedate, d.remarks, d.dept_id, d.qu_total, d.qu_right, d.exam_total, d.exam_passed from t_el_record d
+    </sql>
+
+    <select id="selectTElRecordList" parameterType="TElRecord" resultMap="TElRecordResult">
+        <include refid="selectTElRecordVo"/>
+        <where>
+            <if test="plantCode != null  and plantCode != ''"> and plant_code = #{plantCode}</if>
+            <if test="name != null  and name != ''"> and name like concat(concat('%', #{name}), '%')</if>
+            <if test="staffId != null  and staffId != ''"> and staff_id = #{staffId}</if>
+            <if test="classes != null  and classes != ''"> and classes = #{classes}</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="remarks != null  and remarks != ''"> and remarks = #{remarks}</if>
+            <if test="deptId != null "> and dept_id = #{deptId}</if>
+            <if test="quTotal != null "> and qu_total = #{quTotal}</if>
+            <if test="quRight != null "> and qu_right = #{quRight}</if>
+            <if test="examTotal != null "> and exam_total = #{examTotal}</if>
+            <if test="examPassed != null "> and exam_passed = #{examPassed}</if>
+            and d.del_flag = 0
+        </where>
+        <!-- 数据范围过滤 -->
+        ${params.dataScope}
+    </select>
+
+    <select id="selectTElRecordById" parameterType="Long" resultMap="TElRecordResult">
+        <include refid="selectTElRecordVo"/>
+        where id = #{id}
+    </select>
+
+    <insert id="insertTElRecord" parameterType="TElRecord">
+        <selectKey keyProperty="id" resultType="long" order="BEFORE">
+            SELECT seq_t_el_record.NEXTVAL as id FROM DUAL
+        </selectKey>
+        insert into t_el_record
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="id != null">id,</if>
+            <if test="plantCode != null">plant_code,</if>
+            <if test="name != null">name,</if>
+            <if test="staffId != null">staff_id,</if>
+            <if test="userId != null">user_id,</if>
+            <if test="classes != null">classes,</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="remarks != null">remarks,</if>
+            <if test="deptId != null">dept_id,</if>
+            <if test="quTotal != null">qu_total,</if>
+            <if test="quRight != null">qu_right,</if>
+            <if test="examTotal != null">exam_total,</if>
+            <if test="examPassed != null">exam_passed,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="id != null">#{id},</if>
+            <if test="plantCode != null">#{plantCode},</if>
+            <if test="name != null">#{name},</if>
+            <if test="staffId != null">#{staffId},</if>
+            <if test="userId != null">#{userId},</if>
+            <if test="classes != null">#{classes},</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="remarks != null">#{remarks},</if>
+            <if test="deptId != null">#{deptId},</if>
+            <if test="quTotal != null">#{quTotal},</if>
+            <if test="quRight != null">#{quRight},</if>
+            <if test="examTotal != null">#{examTotal},</if>
+            <if test="examPassed != null">#{examPassed},</if>
+         </trim>
+    </insert>
+
+    <update id="updateTElRecord" parameterType="TElRecord">
+        update t_el_record
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="plantCode != null">plant_code = #{plantCode},</if>
+            <if test="name != null">name = #{name},</if>
+            <if test="staffId != null">staff_id = #{staffId},</if>
+            <if test="userId != null">user_id = #{userId},</if>
+            <if test="classes != null">classes = #{classes},</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="remarks != null">remarks = #{remarks},</if>
+            <if test="deptId != null">dept_id = #{deptId},</if>
+            <if test="quTotal != null">qu_total = #{quTotal},</if>
+            <if test="quRight != null">qu_right = #{quRight},</if>
+            <if test="examTotal != null">exam_total = #{examTotal},</if>
+            <if test="examPassed != null">exam_passed = #{examPassed},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <update id="deleteTElRecordById" parameterType="Long">
+        update t_el_record set del_flag = 2 where id = #{id}
+    </update>
+
+
+    <update id="deleteTElRecordByIds" parameterType="String">
+        update t_el_record set del_flag = 2 where id in
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </update>
+
+    <select id="queryNeedDeleteIds" resultType="String">
+        SELECT b.staff_id from t_el_record b where b.del_flag = 0
+            minus
+        SELECT a.STAFFID FROM "T_STAFFMGR" a where DEPT_ID = 103 and a.del_flag = 0 and a.unit = 10
+    </select>
+
+    <select id="queryNeedInsertIds" resultType="String">
+        SELECT a.STAFFID FROM "T_STAFFMGR" a where DEPT_ID = 103 and a.del_flag = 0 and a.unit = 10
+            minus
+        SELECT b.staff_id from t_el_record b where b.del_flag = 0
+    </select>
+
+    <update id="deleteTElRecordByStaffId" parameterType="String">
+        update t_el_record set del_flag = 2 where staff_id = #{staffId}
+    </update>
+
+    <select id="queryQuData" parameterType="Long" resultMap="TElRecordResult">
+        SELECT
+            COUNT(*) AS qu_total,
+            SUM(IS_RIGHT) AS qu_right
+        FROM
+            T_EL_USER_QU
+        WHERE
+            USER_ID = #{userId}
+    </select>
+
+    <select id="queryExamData" parameterType="Long" resultMap="TElRecordResult">
+        SELECT
+            COUNT(*) AS exam_total,
+            SUM(CASE
+                    WHEN p.USER_SCORE >= p.QUALIFY_SCORE THEN 1
+                    ELSE 0
+                END) AS exam_passed
+        FROM
+            T_EL_PAPER p
+                JOIN
+            T_EL_EXAM e
+            ON
+                e.exam_id = p.exam_id
+        WHERE
+            p.USER_ID = #{userId} and e.EXAM_TYPE = 1
+    </select>
+
+
+
+</mapper>

+ 10 - 0
ui/src/api/training/bccdevice.js

@@ -35,6 +35,16 @@ export function updateDevice(data) {
   })
 }
 
+// 更新培训时长
+export function updateDeviceLearnTime(data) {
+  return request({
+    url: '/training/bccdevice/updateDeviceLearnTime',
+    method: 'put',
+    data: data
+  })
+}
+
+
 // 删除人员-装置级培训关系
 export function delDevice(id) {
   return request({

+ 53 - 0
ui/src/api/training/bccregular.js

@@ -0,0 +1,53 @@
+import request from '@/utils/request'
+
+// 查询装置培训计划列表
+export function listBccregular(query) {
+  return request({
+    url: '/training/bccregular/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询装置培训计划详细
+export function getBccregular(id) {
+  return request({
+    url: '/training/bccregular/' + id,
+    method: 'get'
+  })
+}
+
+// 新增装置培训计划
+export function addBccregular(data) {
+  return request({
+    url: '/training/bccregular',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改装置培训计划
+export function updateBccregular(data) {
+  return request({
+    url: '/training/bccregular',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除装置培训计划
+export function delBccregular(id) {
+  return request({
+    url: '/training/bccregular/' + id,
+    method: 'delete'
+  })
+}
+
+// 导出装置培训计划
+export function exportBccregular(query) {
+  return request({
+    url: '/training/bccregular/export',
+    method: 'get',
+    params: query
+  })
+}

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

@@ -0,0 +1,63 @@
+import request from '@/utils/request'
+
+// 查询岗位培训统计列表
+export function listRecord(query) {
+  return request({
+    url: '/elearn/record/list',
+    method: 'get',
+    params: query
+  })
+}
+
+//更新数据
+export function syncRecord(query) {
+  return request({
+    url: '/elearn/record/syncRecord',
+    method: 'get',
+    params: query
+  })
+}
+
+
+// 查询岗位培训统计详细
+export function getRecord(id) {
+  return request({
+    url: '/elearn/record/' + id,
+    method: 'get'
+  })
+}
+
+// 新增岗位培训统计
+export function addRecord(data) {
+  return request({
+    url: '/elearn/record',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改岗位培训统计
+export function updateRecord(data) {
+  return request({
+    url: '/elearn/record',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除岗位培训统计
+export function delRecord(id) {
+  return request({
+    url: '/elearn/record/' + id,
+    method: 'delete'
+  })
+}
+
+// 导出岗位培训统计
+export function exportRecord(query) {
+  return request({
+    url: '/elearn/record/export',
+    method: 'get',
+    params: query
+  })
+}

+ 106 - 32
ui/src/views/training/bccdevice/index.vue

@@ -74,7 +74,7 @@
             size="mini"
             type="text"
             icon="el-icon-view"
-            @click="handleUpdate(scope.row)"
+            @click="openFileDialog(scope.row)"
           >学习</el-button>
           <el-button
             size="mini"
@@ -164,50 +164,75 @@
       </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 :visible.sync="file.open" width="30%" append-to-body>
+      <el-descriptions class="margin-top" title="学习资料" :column="1" size="" border>
+        <el-descriptions-item label-style="width:180px">
+          <template slot="label">
+            <i class="el-icon-user"></i>
+            资料名
+          </template>
+          {{ file.data.fileName }}
+        </el-descriptions-item>
+        <el-descriptions-item label-style="width:180px">
+          <template slot="label">
+            <i class="el-icon-mobile-phone"></i>
+            学习进度
+          </template>
+          <el-progress :text-inside="true" :stroke-width="20" :percentage="getCountTime()"
+                       status="success"></el-progress>
+        </el-descriptions-item>
+        <el-descriptions-item label-style="width:180px">
+          <template slot="label">
+            <i class="el-icon-mobile-phone"></i>
+            应学习时长(分)
+          </template>
+          {{ file.data.timerNeed }}
+        </el-descriptions-item>
+        <el-descriptions-item label-style="width:180px">
+          <template slot="label">
+            <i class="el-icon-mobile-phone"></i>
+            已学习时长(分)
+          </template>
+          {{ file.data.timer }}
+        </el-descriptions-item>
+      </el-descriptions>
+      <el-button
+        class="mt10"
+        type="primary"
+        icon="el-icon-video-play"
+        @click="handleStudy(file.data)"
+      >开始学习
+      </el-button>
+    </el-dialog>
+    <el-dialog :close-on-click-modal="false" element-loading-background="rgba(0,0,0,0.2)"
+               v-dialogDrag :title="pdf.title"
+               :visible.sync="pdf.open" width="1300px" height="800px" :center="true" append-to-body
+               @close="handleClose">
+      <div style="margin-top: -30px">
+        <iframe id="iFrame" class="iframe-html" :src="pdf.pdfUrl" frameborder="0" width="100%" height="700px"
+                v-if="ppt"></iframe>
+      </div>
+    </el-dialog>
   </div>
 </template>
 
 <script>
-import { listDevice, getDevice, delDevice, addDevice, updateDevice, exportDevice, importTemplate} from "@/api/training/bccdevice";
+import { listDevice, getDevice,updateDeviceLearnTime, delDevice, addDevice, updateDevice, exportDevice, importTemplate} from "@/api/training/bccdevice";
 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 {updateFirstLearnTime} from "@/api/training/bccnew/firstplan";
+var timer = null;
 export default {
   name: "Device",
   components: { Treeselect },
   data() {
     return {
+      file: {
+        open: false,
+        data: {}
+      },
       // 遮罩层
       loading: true,
       // 选中数组
@@ -227,6 +252,16 @@ export default {
       // 部门树选项
       deptOptions: undefined,
       clientHeight:300,
+      pdf: {
+        title: '',
+        pdfUrl: '',
+        numPages: null,
+        open: false,
+        pageNum: 1,
+        pageTotalNum: 1,
+        loadedRatio: 0,
+        loadingFlash: false,
+      },
       // 是否显示弹出层
       open: false,
         // 用户导入参数
@@ -380,6 +415,45 @@ export default {
         }
       });
     },
+    openFileDialog(row) {
+      this.file.open = true;
+      this.file.data = row.trainingbcc
+      console.log(row)
+      if (row.learnTime === '' || row.learnTime == null) {
+        this.file.data.learnTime = 0
+      }
+      if (row.trainingbcc.timerNeed === '' || row.trainingbcc.timerNeed == null) {
+        this.file.data.trainingbcc.timerNeed = 0
+      }
+      console.log(this.file.data)
+    },
+    handleStudy(row) {
+      //office预览
+      this.pdf.loadingFlash = true
+      this.pdf.open = true
+      this.pdf.title = row.fileName
+      this.pdf.pdfUrl = ""
+      this.ppt = true
+      //如果是PDF等直接可以打开的就不调接口,否则调用接口
+      if (row.fileName!=null && row.fileName.endsWith('pdf')) {
+        this.pdf.pdfUrl = process.env.VUE_APP_BASE_API + '/pdf/web/viewer.html?file=' + process.env.VUE_APP_BASE_API + row.fileUrl
+        this.loadingFlash = false
+      }
+      let _this = this;
+      timer = window.setInterval(function () {
+        updateDeviceLearnTime(row).then(res => {
+        })
+      }, 60000);
+    },
+    handleClose() {
+      window.clearInterval(timer);
+      this.getList();
+    },
+    getCountTime() {
+      if (this.file.data.timerNeed === 0)
+        return 0;
+      return (this.file.data.timer / this.file.data.timerNeed * 100).toFixed(2)
+    },
     /** 删除按钮操作 */
     handleDelete(row) {
       const ids = row.id || this.ids;

+ 822 - 0
ui/src/views/training/bccregular/index.vue

@@ -0,0 +1,822 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item :label="$t('年份')" prop="year">
+        <el-date-picker clearable size="small" style="width: 200px"
+                        v-model="queryParams.year"
+                        type="year"
+                        value-format="yyyy"
+                        :placeholder="$t('请选择') + $t('年份')"
+                        @input="handleQuery">
+        </el-date-picker>
+      </el-form-item>
+      <el-form-item :label="$t('课程名称')" prop="item">
+        <el-input
+          v-model="queryParams.item"
+          :placeholder="$t('请输入') + $t('课程名称')"
+          clearable
+          size="small"
+          @input="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">{{ $t('搜索') }}</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">{{ $t('重置') }}</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="['training:regular:add']"
+        >{{ $t('新增') }}</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="['training:regular:edit']"
+        >{{ $t('修改') }}</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="['training:regular:remove']"
+        >{{ $t('删除') }}</el-button>
+      </el-col>
+      <!--<el-col :span="1.5">
+        <el-button
+          type="info"
+          icon="el-icon-upload2"
+          size="mini"
+          @click="handleImport"
+          v-hasPermi="['training:regular:edit']"
+        >导入</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          icon="el-icon-download"
+          size="mini"
+          @click="handleExport"
+          v-hasPermi="['training:regular:export']"
+        >{{ $t('导出') }}</el-button>
+      </el-col>-->
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-row class="colorMark">
+      <svg-icon icon-class="rectangleLightgreen" class="rectangleLightgreen"></svg-icon>{{ $t('需要培训') }}
+      <svg-icon icon-class="rectangleFlesh" class="rectangleFlesh"></svg-icon>{{ $t('指定人员') }}
+      <svg-icon icon-class="rectangleYellow" class="rectangleYellow"></svg-icon>{{ $t('当被此项目涉及到时,如MOC、事件调查,需要培训') }}
+    </el-row>
+
+    <el-table ref="regularTable" v-loading="loading" :data="regularList" @selection-change="handleSelectionChange" :cell-class-name="tableCellClassName" :height="clientHeight" border>
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column :label="$t('年份')" align="center" prop="year" width="50" :show-overflow-tooltip="true"/>
+      <el-table-column :label="$t('课程代码')" align="center" prop="courseCode" width="150" :show-overflow-tooltip="true"/>
+      <el-table-column :label="$t('课程名称')" align="center" prop="item" width="350" :show-overflow-tooltip="true"/>
+      <el-table-column :label="$t('计划培训时间')" align="center" prop="planTrainingdate" width="100">
+        <template slot-scope="scope">
+          <span v-if="scope.row.notPlan === 'false'">{{ scope.row.notTrainingdate }}</span>
+          <span v-else>{{ scope.row.planTrainingdate }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column :label="$t('授课人')" align="center" prop="lecturerName" width="230" :show-overflow-tooltip="true" />
+      <el-table-column :label="$t('课时')" align="center" prop="hour" :show-overflow-tooltip="true"/>
+      <el-table-column v-for="(item, index) in actualpostIdOptions" width="150" :label="item.dictLabel" :key="index" align="center">
+        <template slot-scope="scope">
+          {{scope.row.actualpost[index]}}
+        </template>
+      </el-table-column>
+      <el-table-column :label="$t('备注')" align="center" prop="remarks" width="300" :show-overflow-tooltip="true"/>
+      <el-table-column :label="$t('操作')" 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="['training:regular:edit']"
+          >{{ $t('修改') }}</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['training:regular:remove']"
+          >{{ $t('删除') }}</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  :close-on-click-modal="false" v-dialogDrag :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="130px">
+        <el-form-item :label="$t('年份')" prop="year">
+          <el-date-picker clearable size="small" style="width: 200px"
+                          v-model="form.year"
+                          type="year"
+                          value-format="yyyy"
+                          @change="getLecturer"
+                          :placeholder="$t('请选择') + $t('年份')">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item :label="$t('课程代码')" prop="courseCode">
+          <el-input v-model="form.courseCode" :placeholder="$t('请输入') + $t('课程代码')" />
+        </el-form-item>
+        <el-form-item :label="$t('课程名称')" prop="item">
+          <el-input v-model="form.item" :placeholder="$t('请输入') + $t('课程名称')" />
+        </el-form-item>
+        <el-form-item :label="$t('需参培岗位')" prop="actualpostId">
+          <el-select v-model="actualpostIds" multiple :placeholder="$t('请选择') + $t('需参培岗位')" @change="changeActualpost">
+            <el-option
+              v-for="dict in actualpostOptions"
+              :key="dict.dictValue"
+              :label="dict.dictLabel"
+              :value="dict.dictValue"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item :label="$t('是否存在')+$t('空格') +$t('指定人员')" prop="haveDesignated">
+          <el-checkbox v-model="haveDesignated"></el-checkbox>
+        </el-form-item>
+        <el-form-item :label="$t('指定人员')+$t('空格') + $t('岗位')" prop="designatedPosition" v-if="haveDesignated === true">
+          <el-select v-model="designatedPositions" multiple :placeholder="$t('请选择') + $t('指定岗位')" @change="changeDesignated">
+            <el-option
+              v-for="dict in designatedPositionOptions"
+              :key="dict.dictValue"
+              :label="dict.dictLabel"
+              :value="dict.dictValue"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item :label="$t('指定人员')" prop="designatedStaff" v-if="haveDesignated === true && designatedPositions.length > 0">
+          <el-select v-model="designatedStaffs" filterable multiple :placeholder="$t('请选择') + $t('指定人员')">
+            <el-option
+              v-for="dict in stffmgrOptions"
+              :key="dict.staffid"
+              :label="dict.name"
+              :value="dict.staffid">
+              <span style="float: left">{{ dict.name }}</span>
+              <span style="float: right; color: #8492a6; font-size: 13px">{{ dict.staffid }}</span>
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item :label="$t('是否涉及') + $t('其他部门')" prop="involvedMoc">
+          <el-checkbox v-model="form.involvedMoc" @change="changeInvolved"></el-checkbox>
+        </el-form-item>
+        <el-form-item :label="$t('指定其他部门')" prop="designatedOther" v-if="form.involvedMoc === true">
+          <el-select v-model="otherPositions" multiple :placeholder="$t('请选择') + $t('其他部门')">
+            <el-option
+              v-for="dict in otherPositionOptions"
+              :key="dict.dictValue"
+              :label="dict.dictLabel"
+              :value="dict.dictValue"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item :label="$t('备注')" prop="remarks">
+          <el-input v-model="form.remarks" :placeholder="$t('请输入') + $t('备注')" />
+        </el-form-item>
+        <el-form-item :label="$t('是否') + $t('计划培训时间')" prop="notPlan">
+          <el-checkbox v-model="form.notPlan"></el-checkbox>
+        </el-form-item>
+        <el-form-item :label="$t('计划培训时间')" >
+          <el-date-picker clearable size="small" style="width: 200px"
+                          v-model="form.planTrainingdate"
+                          type="month"
+                          value-format="yyyy-MM"
+                          v-if="form.notPlan === true"
+                          :placeholder="$t('请选择') + $t('计划培训时间')">
+          </el-date-picker>
+          <el-input v-model="form.notTrainingdate" :placeholder="$t('请输入') + $t('计划培训时间')" v-if="form.notPlan === false" />
+        </el-form-item>
+        <el-form-item :label="$t('授课人')" prop="lecturer">
+          <el-select v-model="lecturers" filterable multiple :placeholder="$t('请选择') +$t('授课人')">
+            <el-option
+              v-for="dict in lecturerOptions"
+              :key="dict.staffid"
+              :label="dict.name"
+              :value="dict.staffid">
+              <span style="float: left">{{ dict.name }}</span>
+              <span style="float: right; color: #8492a6; font-size: 13px">{{ dict.staffid }}</span>
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item :label="$t('课时')" prop="hour">
+          <el-input v-model="form.hour" :placeholder="$t('请输入') + $t('课时')" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm" :disabled="submitDisabled">{{ $t('确 定') }}</el-button>
+        <el-button @click="cancel">{{ $t('取 消') }}</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listBccregular, getBccregular, delBccregular, addBccregular, updateBccregular, exportBccregular} from "@/api/training/bccregular";
+import { listStaffmgr, listAllStaffmgr } from "@/api/plant/staffmgr";
+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: "Regular",
+  components: { Treeselect },
+  data() {
+    return {
+      // 遮罩层
+      loading: true,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: false,
+      // 总条数
+      total: 0,
+      // 装置培训计划表格数据
+      regularList: [],
+      // 弹出层标题
+      title: "",
+      // 部门树选项
+      deptOptions: undefined,
+      clientHeight:300,
+      // 是否显示弹出层
+      open: false,
+      // 台账显示岗位字典
+      actualpostIdOptions: [],
+      // 需参培岗位字典
+      actualpostOptions: [],
+      // 授课人字典
+      lecturerOptions: [],
+      // 指定岗位字典
+      designatedPositionOptions: [],
+      // 指定部门字典
+      otherPositionOptions: [],
+      //培训岗位多选
+      actualpostIds: [],
+      //指定人员岗位多选
+      designatedPositions: [],
+      //其他部门多选
+      otherPositions: [],
+      //指定人员id多选
+      designatedStaffs: [],
+      //授课人多选
+      lecturers: [],
+      //是否存在岗位多选
+      haveDesignated: false,
+      //人员表联查
+      stffmgrOptions: undefined,
+      //人员表查询参数
+      staffmgrQueryParams: {
+        actualposts: null
+      },
+      //确认按钮是否可点
+      submitDisabled: false,
+      // 用户导入参数
+      upload: {
+        // 是否显示弹出层(用户导入)
+        open: false,
+        // 弹出层标题(用户导入)
+        title: "",
+        // 是否禁用上传
+        isUploading: false,
+        // 是否更新已经存在的用户数据
+        updateSupport: 0,
+        // 设置上传的请求头部
+        headers: { Authorization: "Bearer " + getToken() },
+        // 上传的地址
+        url: process.env.VUE_APP_BASE_API + "/training/regular/importData"
+      },
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 20,
+        year: this.getNowTime()
+      },
+      // 表单参数
+      form: {},
+      // 表单校验
+      rules: {
+        year: [
+          { required: true, message: this.$t('年份') + this.$t('不能为空'), trigger: "blur" }
+        ],
+        courseCode: [
+          { required: true, message: this.$t('课程代码') + this.$t('不能为空'), trigger: "blur" }
+        ],
+        item: [
+          { required: true, message: this.$t('课程名称') + this.$t('不能为空'), trigger: "blur" }
+        ],
+        deptId: [
+          { required: true, message: this.$t('部门编号')+ this.$t('不能为空'), trigger: "blur" }
+        ],
+      }
+    };
+  },
+  watch: {
+    // 根据名称筛选部门树
+    deptName(val) {
+      this.$refs.tree.filter(val);
+    }
+  },
+  created() {
+    //设置表格高度对应屏幕高度
+    this.$nextTick(() => {
+      this.clientHeight = document.body.clientHeight -250
+    })
+
+    this.getDicts("ACTUALPOST").then(response => {
+      this.actualpostIdOptions = response.data;
+    });
+    this.getDicts("ACTUALPOST").then(response => {
+      this.actualpostOptions = response.data;
+    });
+    this.getDicts("ACTUALPOST").then(response => {
+      this.designatedPositionOptions = response.data;
+    });
+    let _this = this
+    this.getDicts("ACTUALPOST").then(response => {
+      response.data.forEach(function (positionValue, positionkey, arr) {
+        if (positionValue.dictValue === "28" || positionValue.dictValue === "30" || positionValue.dictValue === "32") {
+          _this.otherPositionOptions.push(positionValue)
+        }
+      })
+      this.getStaffmar();
+      this.getLecturer();
+      this.getTreeselect();
+    });
+  },
+  methods: {
+    /** 查询装置培训计划列表 */
+    getList() {
+      this.loading = true;
+      let _this = this
+      listBccregular(this.queryParams).then(response => {
+        this.regularList = response.rows;
+        this.regularList.forEach(function (value,key,arr) {
+          let stffmgrName = "";
+          if (value.lecturer != null) {
+            let staffId = value.lecturer.split(",");
+            staffId.forEach(function (id, index) {
+              _this.stffmgrOptions.forEach(function (item) {
+                if (item.staffid === id) {
+                  if (index === 0) {
+                    stffmgrName = item.name
+                  }else {
+                    stffmgrName = stffmgrName + "," + item.name
+                  }
+                }
+              });
+            });
+          }
+          _this.regularList[key].lecturerName = stffmgrName
+        });
+        this.total = response.total;
+        this.loading = false;
+        this.$nextTick(() => {
+          this.$refs.regularTable.doLayout(); // 解决表格错位
+        });
+      });
+    },
+    /** 获取当前年份 */
+    getNowTime() {
+      var now = new Date();
+      var year = now.getFullYear(); //得到年份
+      var defaultDate = `${year}`;
+      defaultDate = `${year}`
+      return defaultDate;
+    },
+    /** 查询部门下拉树结构 */
+    getTreeselect() {
+      treeselect().then(response => {
+        this.deptOptions = response.data;
+      });
+    },
+    //获取人员表
+    getStaffmar() {
+      listStaffmgr(this.staffmgrQueryParams).then(response => {
+        this.stffmgrOptions = response.rows;
+        this.$nextTick(() => {
+          this.getList();
+        })
+      });
+    },
+    getLecturer(year) {
+      this.staffmgrQueryParams.leftYear = year
+      listAllStaffmgr(this.staffmgrQueryParams).then(response => {
+        this.lecturerOptions = response.rows;
+      });
+    },
+    //根据分数显示颜色提示
+    tableCellClassName({ row, column, rowIndex, columnIndex }) {
+      var postNum = this.actualpostIdOptions.length;
+      for (var i = 0; i < postNum; i++) {
+        if (columnIndex == 7 + i){
+          return this.changeColor(row.actualpost[i])
+        }
+      }
+    },
+    changeColor (value) {
+      if (value === "M") {
+        return 'cellChoose'
+      }else if (value === "|") {
+        return 'cellDesignated'
+      }else if (value === "(M)") {
+        return 'cellInvolvedMoc'
+      }
+    },
+    //需培训岗位变动
+    changeActualpost() {
+      let _this = this
+      this.getDicts("ACTUALPOST").then(response => {
+        this.designatedPositionOptions = response.data;
+        this.actualpostIds.forEach(function (value, key, arr) {
+          _this.designatedPositionOptions.forEach(function (positionValue, positionkey, arr) {
+            if (positionValue.dictValue === value) {
+              _this.designatedPositionOptions.splice(positionkey ,1)
+            }
+          })
+        })
+      });
+    },
+    //指定人员训岗位变动
+    changeDesignated() {
+      if (this.designatedPositions.length > 0) {
+        var designatedId = null;
+        this.designatedPositions.forEach(function (value,key,arr) {
+          if (key != 0) {
+            designatedId = designatedId + "," + value;
+          }else if (key == 0) {
+            designatedId = value;
+          }
+        })
+        this.staffmgrQueryParams.actualposts = designatedId;
+        this.staffmgrQueryParams.leftYear = this.form.year
+        listAllStaffmgr(this.staffmgrQueryParams).then(response => {
+          this.stffmgrOptions = response.rows;
+        });
+
+        let _this = this
+        this.getDicts("ACTUALPOST").then(response => {
+          this.actualpostOptions = response.data;
+          this.designatedPositions.forEach(function (value, key, arr) {
+            _this.actualpostOptions.forEach(function (positionValue, positionkey, arr) {
+              if (positionValue.dictValue === value) {
+                _this.actualpostOptions.splice(positionkey ,1)
+              }
+            })
+          })
+        });
+      }else {
+        this.designatedStaffs = [];
+      }
+    },
+    //是否涉及其他部门变动
+    changeInvolved() {
+      if (this.form.involvedMoc === true) {
+        this.otherPositions = ['28','30','32']
+      }else {
+        this.otherPositions = []
+      }
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        id: null,
+        courseCode: null,
+        item: null,
+        actualpostId: null,
+        remarks: null,
+        delFlag: null,
+        createrCode: null,
+        createdate: null,
+        updaterCode: null,
+        updatedate: null,
+        deptId: null,
+        planTrainingdate: null,
+        actualCompletedate: null,
+        lecturer: null,
+        hour: null,
+        year: null,
+        designatedPosition: null,
+        designatedStaff: null,
+        involvedMoc: null,
+        designatedOther: null,
+        notPlan: null,
+        notTrainingdate: 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.submitDisabled = false;
+      this.form.involvedMoc = false
+      this.form.notPlan = true
+      this.actualpostIds = [];
+      this.lecturers = [];
+      this.haveDesignated = false;
+      this.designatedPositions = [];
+      this.otherPositions = [];
+      this.getDicts("ACTUALPOST").then(response => {
+        this.actualpostOptions = response.data;
+      });
+      this.getDicts("ACTUALPOST").then(response => {
+        this.designatedPositionOptions = response.data;
+      });
+      this.title = this.$t('添加') + this.$t('装置') +this.$t('空格') + this.$t('培训计划');
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      let _this = this
+      this.submitDisabled = false;
+      const id = row.id || this.ids
+      getBccregular(id).then(response => {
+        this.form = response.data;
+        if (this.form.actualpostId != null) {
+          this.actualpostIds = this.form.actualpostId.split(',');
+          this.getDicts("ACTUALPOST").then(response => {
+            this.designatedPositionOptions = response.data;
+            this.actualpostIds.forEach(function (value, key, arr) {
+              _this.designatedPositionOptions.forEach(function (positionValue, positionkey, arr) {
+                if (positionValue.dictValue === value) {
+                  _this.designatedPositionOptions.splice(positionkey ,1)
+                }
+              })
+            })
+          });
+        }else {
+          this.getDicts("ACTUALPOST").then(response => {
+            this.designatedPositionOptions = response.data;
+          })
+          this.actualpostIds = [];
+        }
+        if (this.form.designatedPosition != null) {
+          this.designatedPositions = this.form.designatedPosition.split(',');
+          this.getDicts("ACTUALPOST").then(response => {
+            this.actualpostOptions = response.data;
+            this.designatedPositions.forEach(function (value, key, arr) {
+              _this.actualpostOptions.forEach(function (positionValue, positionkey, arr) {
+                if (positionValue.dictValue === value) {
+                  _this.actualpostOptions.splice(positionkey ,1)
+                }
+              })
+            })
+          });
+          this.haveDesignated = true;
+          var designatedId = null;
+          this.designatedPositions.forEach(function (value,key,arr) {
+            if (key != 0) {
+              designatedId = designatedId + "," + value;
+            }else if (key == 0) {
+              designatedId = value;
+            }
+          })
+          this.staffmgrQueryParams.actualposts = designatedId;
+          this.staffmgrQueryParams.leftYear = this.form.year
+          this.$nextTick(() => {
+            listStaffmgr(this.staffmgrQueryParams).then(response => {
+              this.stffmgrOptions = response.rows;
+            });
+          })
+        }else {
+          this.haveDesignated = false;
+          this.designatedPositions = [];
+          this.getDicts("ACTUALPOST").then(response => {
+            this.actualpostOptions = response.data;
+          })
+        }
+        if (this.form.designatedStaff != null) {
+          this.designatedStaffs = this.form.designatedStaff.split(',');
+        }else {
+          this.designatedStaffs = [];
+        }
+        if (this.form.lecturer != null) {
+          this.lecturers = this.form.lecturer.split(',');
+        }else {
+          this.lecturers =[];
+        }
+        if (response.data.involvedMoc === 'true') {
+          this.form.involvedMoc = true
+        }else {
+          this.form.involvedMoc = false
+        }
+
+        //指定其他部门下拉框内容
+        if (this.form.designatedOther != null) {
+          this.otherPositions = this.form.designatedOther.split(',');
+        }else {
+          this.otherPositions = [];
+        }
+
+        if (response.data.notPlan === 'true') {
+          this.form.notPlan = true
+        }else {
+          this.form.notPlan = false
+        }
+        this.open = true;
+        this.title = this.$t('修改') + this.$t('装置') +this.$t('空格') + this.$t('培训计划');
+      });
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        this.submitDisabled = true;
+        if (valid) {
+          var id = null;
+          this.actualpostIds.forEach(function (value,key,arr) {
+            if (key != 0) {
+              id = id + "," + value;
+            }else if (key == 0) {
+              id = value;
+            }
+          })
+          this.form.actualpostId = id;
+
+          var designatedId = null;
+          this.designatedPositions.forEach(function (value,key,arr) {
+            if (key != 0) {
+              designatedId = designatedId + "," + value;
+            }else if (key == 0) {
+              designatedId = value;
+            }
+          })
+          // 王子文 2022年4月18日 13点31分 修改
+          // 如果 复选框被选中 将指定人信息存入数据传输对象
+          if (this.haveDesignated === true) {
+            this.form.designatedPosition = designatedId;
+          } else {
+            this.form.designatedPosition = null;
+          }
+          // this.form.designatedPosition = designatedId;
+
+          var designatedOther = null;
+          this.otherPositions.forEach(function (value,key,arr) {
+            if (key != 0) {
+              designatedOther = designatedOther + "," + value;
+            }else if (key == 0) {
+              designatedOther = value;
+            }
+          })
+          this.form.designatedOther = designatedOther;
+
+          var staffId = null;
+          this.designatedStaffs.forEach(function (value,key,arr) {
+            if (key != 0) {
+              staffId = staffId + "," + value;
+            }else if (key == 0) {
+              staffId = value;
+            }
+          })
+          this.form.designatedStaff = staffId;
+
+          var lecturerId = null;
+          this.lecturers.forEach(function (value,key,arr) {
+            if (key != 0) {
+              lecturerId = lecturerId + "," + value;
+            }else if (key == 0) {
+              lecturerId = value;
+            }
+          })
+          this.form.lecturer = lecturerId;
+          if (this.form.id != null) {
+            updateBccregular(this.form).then(response => {
+              this.msgSuccess(this.$t('修改成功'));
+              this.open = false;
+              this.submitDisabled = false;
+              this.getList();
+            });
+          } else {
+            addBccregular(this.form).then(response => {
+              this.msgSuccess(this.$t('新增成功'));
+              this.open = false;
+              this.submitDisabled = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$confirm(this.$t('是否确认删除?'), this.$t('警告'), {
+        confirmButtonText: this.$t('确定'),
+        cancelButtonText: this.$t('取消'),
+        type: "warning"
+      }).then(function() {
+        return delBccregular(ids);
+      }).then(() => {
+        this.getList();
+        this.msgSuccess(this.$t('删除成功'));
+      })
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      const queryParams = this.queryParams;
+      this.$confirm(this.$t('是否确认导出所有装置培训计划数据项?'), this.$t('警告'), {
+        confirmButtonText: this.$t('确定'),
+        cancelButtonText: this.$t('取消'),
+        type: "warning"
+      }).then(function() {
+        return exportBccregular(queryParams);
+      }).then(response => {
+        this.download(response.msg);
+      })
+    },
+    /** 导入按钮操作 */
+    handleImport() {
+      this.upload.title = this.$t('用户导入');
+      this.upload.open = true;
+    },
+    // 文件上传中处理
+    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, this.$t('导入结果'), { dangerouslyUseHTMLString: true });
+      this.getList();
+    },
+    // 提交上传文件
+    submitFileForm() {
+      this.$refs.upload.submit();
+    }
+  }
+};
+</script>
+
+<style scoped>
+.colorMark {
+  color: #6f6f6f;
+  text-align: right;
+  font-weight:bold;
+  font-size: 13px;
+  padding-bottom: 5px;
+}
+
+.rectangleLightgreen {
+  width: 40px !important;
+  height: 20px !important;
+}
+.rectangleFlesh {
+  width: 40px !important;
+  height: 20px !important;
+}
+.rectangleYellow {
+  width: 40px !important;
+  height: 20px !important;
+}
+</style>

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

@@ -0,0 +1,343 @@
+<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="staffId">
+        <el-input
+          v-model="queryParams.staffId"
+          placeholder="请输入员工号"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="班组" prop="classes">
+        <el-input
+          v-model="queryParams.classes"
+          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-refresh"
+          size="mini"
+          @click="handleSync"
+        >同步考试数据</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          icon="el-icon-download"
+          size="mini"
+          @click="handleExport"
+          v-hasPermi="['elearn:record:export']"
+        >导出</el-button>
+      </el-col>
+	  <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading" :data="recordList" @selection-change="handleSelectionChange" :height="clientHeight" border>
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="姓名" align="center" prop="name" :show-overflow-tooltip="true"/>
+      <el-table-column label="员工号" align="center" prop="staffId" :show-overflow-tooltip="true"/>
+      <el-table-column label="班组" align="center" prop="classes" :formatter="classesFormat"  :show-overflow-tooltip="true"/>
+
+      <el-table-column label="答题总数" align="center" prop="quTotal" :show-overflow-tooltip="true"/>
+      <el-table-column label="正确数" align="center" prop="quRight" :show-overflow-tooltip="true"/>
+      <el-table-column label="考试次数" align="center" prop="examTotal" :show-overflow-tooltip="true"/>
+      <el-table-column label="考试通过次数" align="center" prop="examPassed" :show-overflow-tooltip="true"/>
+      <el-table-column label="操作" align="center" fixed="right" width="120" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+
+        </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 { listRecord, getRecord,syncRecord, delRecord, addRecord, updateRecord, exportRecord, importTemplate} from "@/api/training/elearn/record";
+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: "Record",
+  components: { Treeselect },
+  data() {
+    return {
+      // 遮罩层
+      loading: true,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: false,
+      // 总条数
+      total: 0,
+      // 岗位培训统计表格数据
+      recordList: [],
+      // 班组字典
+      classesOptions: [],
+      // 弹出层标题
+      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/record/importData"
+        },
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 20,
+        plantCode: null,
+        name: null,
+        staffId: null,
+        classes: null,
+        createrCode: null,
+        createdate: null,
+        updaterCode: null,
+        updatedate: null,
+        remarks: null,
+        deptId: null,
+        quTotal: null,
+        quRight: null,
+        examTotal: null,
+        examPassed: null
+      },
+      // 表单参数
+      form: {},
+      // 表单校验
+      rules: {
+        deptId: [
+          { required: true, message: "部门编号不能为空", trigger: "blur" }
+        ],
+      }
+    };
+  },
+  watch: {
+        // 根据名称筛选部门树
+        deptName(val) {
+            this.$refs.tree.filter(val);
+        }
+   },
+  created() {
+      //设置表格高度对应屏幕高度
+      this.$nextTick(() => {
+          this.clientHeight = document.body.clientHeight -250
+      })
+    this.getList();
+    this.getTreeselect();
+    this.getDicts("TEAM_DIVIDE").then(response => {
+      this.classesOptions = response.data;
+    });
+  },
+  methods: {
+    /** 查询岗位培训统计列表 */
+    getList() {
+      this.loading = true;
+      listRecord(this.queryParams).then(response => {
+        this.recordList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+
+     /** 查询部门下拉树结构 */
+     getTreeselect() {
+          treeselect().then(response => {
+              this.deptOptions = response.data;
+          });
+     },
+    // 班组字典翻译
+    classesFormat(row, column) {
+      return this.selectDictLabel(this.classesOptions, row.classes);
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        id: null,
+        plantCode: null,
+        name: null,
+        staffId: null,
+        classes: null,
+        delFlag: null,
+        createrCode: null,
+        createdate: null,
+        updaterCode: null,
+        updatedate: null,
+        remarks: null,
+        deptId: null,
+        quTotal: null,
+        quRight: null,
+        examTotal: null,
+        examPassed: 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
+      getRecord(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) {
+            updateRecord(this.form).then(response => {
+              this.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addRecord(this.form).then(response => {
+              this.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    handleSync(){
+      syncRecord(this.queryParams).then(response => {
+        this.getList()
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$confirm('是否确认删除?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return delRecord(ids);
+        }).then(() => {
+          this.getList();
+          this.msgSuccess("删除成功");
+        })
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      const queryParams = this.queryParams;
+      this.$confirm('是否确认导出所有岗位培训统计数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return exportRecord(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>

+ 150 - 32
ui/src/views/training/trainingbcc/index.vue

@@ -147,13 +147,24 @@
       <el-table-column :label="$t('课程代码')" align="center" prop="courseid" width="150" :show-overflow-tooltip="true"/>
       <el-table-column :label="$t('是否完成')" align="center" prop="isfinish" width="120">
         <template slot-scope="scope">
-            <el-progress :percentage="scope.row.trainingPercent"></el-progress>
+<!--            <el-progress :percentage="scope.row.trainingPercent"></el-progress>-->
           <span > ({{ scope.row.haveTraining }}/{{ scope.row.mustTraining }})</span>
         </template>
       </el-table-column>
       <el-table-column :label="$t('培训周期')" align="center" prop="period" :show-overflow-tooltip="true"/>
       <el-table-column :label="$t('课时')" align="center" prop="duration" :show-overflow-tooltip="true"/>
       <el-table-column :label="$t('培训人')" align="center" prop="trainer" :show-overflow-tooltip="true"/>
+      <el-table-column label="课件" align="center">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-folder"
+            @click="handleDoc(scope.row)"
+          >上传课件
+          </el-button>
+        </template>
+      </el-table-column>
       <el-table-column :label="$t('培训岗位')" align="center" prop="position" width="250" :show-overflow-tooltip="true" />
       <el-table-column :label="$t('培训开始日期')" align="center" prop="courseStartdate" width="100">
         <template slot-scope="scope">
@@ -264,9 +275,6 @@
               </el-select>
             </el-form-item>
           </el-col>
-
-        </el-row>
-        <el-row>
           <el-col :span="12">
             <el-form-item :label="$t('培训岗位')" prop="position">
               <el-select v-model="form.position" multiple :placeholder="$t('请选择') + $t('培训岗位')" @change="changePosition"  style="width: 400px">
@@ -279,11 +287,12 @@
               </el-select>
             </el-form-item>
           </el-col>
+        </el-row>
+        <el-row>
           <el-col :span="12">
-            <el-form-item :label="$t('是否存在') +$t('指定人员')" prop="haveDesignated" >
-              <el-checkbox v-model="haveDesignated" @change="changeHave"></el-checkbox>
-            </el-form-item>
+
           </el-col>
+
         </el-row>
         <el-row>
           <el-col :span="12">
@@ -298,16 +307,6 @@
             </el-form-item>
           </el-col>
           <el-col :span="12">
-            <el-form-item :label="$t('指定人员') + $t('岗位')" prop="designatedPosition" v-if="haveDesignated === true">
-              <el-select v-model="designatedPositions" multiple :placeholder="$t('请选择') + $t('指定岗位')" @change="changeDesignated" style="width: 400px">
-                <el-option
-                  v-for="dict in designatedPositionOptions"
-                  :key="dict.dictValue"
-                  :label="dict.dictLabel"
-                  :value="dict.dictValue"
-                ></el-option>
-              </el-select>
-            </el-form-item>
           </el-col>
         </el-row>
         <el-row>
@@ -322,18 +321,6 @@
             </el-form-item>
           </el-col>
           <el-col :span="12">
-            <el-form-item :label="$t('指定人员')" prop="designatedStaff" v-if="haveDesignated === true && designatedPositions.length > 0">
-              <el-select v-model="designatedStaffs" filterable multiple :placeholder="$t('请选择') + $t('指定人员')"  style="width: 400px">
-                <el-option
-                  v-for="dict in designatedStaffsOptions"
-                  :key="dict.staffid"
-                  :label="dict.name"
-                  :value="dict.staffid">
-                  <span style="float: left">{{ dict.name }}</span>
-                  <span style="float: right; color: #8492a6; font-size: 13px">{{ dict.staffid }}</span>
-                </el-option>
-              </el-select>
-            </el-form-item>
           </el-col>
         </el-row>
         <el-row>
@@ -415,6 +402,86 @@
         <el-button @click="cancelParticipants">{{ $t('取 消') }}</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
+        ref="doc"
+        :limit="50"
+        :headers="doc.headers"
+        :action="doc.url+'/'+doc.id"
+        :disabled="doc.isUploading"
+        :on-progress="handleFileDocProgress"
+        :on-success="handleFileDocSuccess"
+        :file-list="doc.file"
+        :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" width="220" class-name="small-padding fixed-width">
+          <template slot-scope="scope">
+            <el-button
+              v-if="scope.row.fileName!=null&&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
+              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>
@@ -431,6 +498,7 @@ import "@riophae/vue-treeselect/dist/vue-treeselect.css";
 import { allFileList, listCommonfile, getCommonfile, delCommonfile, addCommonfile, updateCommonfile, exportCommonfile} from "@/api/common/commonfile";
 import {getCompanylevel, updateCompanylevel} from "@/api/training/companylevel";
 import {listExam} from "@/api/training/elearn/exam";
+import {getFirstPlanTmpl} from "@/api/training/bccnew/firstPlanTmpl";
 
 
 export default {
@@ -537,13 +605,13 @@ export default {
         // 设置上传的请求头部
         headers: { Authorization: "Bearer " + getToken() },
         // 上传的地址
-        url: process.env.VUE_APP_BASE_API + "/common/commonfile/uploadFile",
+        url: process.env.VUE_APP_BASE_API + "/training/trainingbcc/uploadFile",
         commonfileList: null,
         queryParams: {
           pId: null,
-          pType: 'training'
+          pType: 'trainingbcc'
         },
-        pType: 'training',
+        pType: 'trainingbcc',
         pId: null
       },
       pdf : {
@@ -1243,6 +1311,56 @@ export default {
       this.personOpen = false;
       this.reset();
     },
+    handleDoc(row) {
+      this.doc.file = null;
+      this.doc.commonfileList = [];
+      this.doc.open = true;
+      this.doc.id = row.id;
+      getTrainingbcc(row.id).then(res => {
+        if (res.data.fileUrl != null)
+          this.doc.commonfileList.push({fileUrl: res.data.fileUrl, fileName: res.data.fileName, id: res.data.id})
+      })
+      this.$nextTick(() => {
+        this.$refs.doc.clearFiles()
+      })
+    },
+    // 上传中处理
+    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.getList();
+      this.doc.commonfileList = [];
+      getTrainingbcc(response.data).then(res => {
+        if (res.data.fileUrl != null) {
+          this.doc.commonfileList.push({fileUrl: res.data.fileUrl, fileName: res.data.fileName, id: res.data.id})
+        }
+      })
+    },
+    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
+    },
+    // 文件下载处理
+    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()
+    },
   }
 };
 </script>

+ 1 - 1
ui/vue.config.js

@@ -37,7 +37,7 @@ module.exports = {
     proxy: {
       // detail: https://cli.vuejs.org/config/#devserver-proxy
       [process.env.VUE_APP_BASE_API]: {
-        target: `http://localhost:8080`,
+        target: `http://localhost:8090`,
         changeOrigin: true,
         pathRewrite: {
           ['^' + process.env.VUE_APP_BASE_API]: ''