Browse Source

LY 装置培训

ly 1 year ago
parent
commit
e53c79b4b4
29 changed files with 6275 additions and 7 deletions
  1. 2 2
      master/pom.xml
  2. 162 0
      master/src/main/java/com/ruoyi/project/training/controller/TTrainingbccController.java
  3. 112 0
      master/src/main/java/com/ruoyi/project/training/controller/TTrainingbccDeviceController.java
  4. 524 0
      master/src/main/java/com/ruoyi/project/training/domain/TTrainingbcc.java
  5. 278 0
      master/src/main/java/com/ruoyi/project/training/domain/TTrainingbccDevice.java
  6. 3 0
      master/src/main/java/com/ruoyi/project/training/elearn/domain/TElExam.java
  7. 67 0
      master/src/main/java/com/ruoyi/project/training/mapper/TTrainingbccDeviceMapper.java
  8. 63 0
      master/src/main/java/com/ruoyi/project/training/mapper/TTrainingbccMapper.java
  9. 61 0
      master/src/main/java/com/ruoyi/project/training/service/ITTrainingbccDeviceService.java
  10. 63 0
      master/src/main/java/com/ruoyi/project/training/service/ITTrainingbccService.java
  11. 93 0
      master/src/main/java/com/ruoyi/project/training/service/impl/TTrainingbccDeviceServiceImpl.java
  12. 168 0
      master/src/main/java/com/ruoyi/project/training/service/impl/TTrainingbccServiceImpl.java
  13. 1 1
      master/src/main/resources/application.yml
  14. 3 0
      master/src/main/resources/mybatis/document/TPlantproglistMapper.xml
  15. 148 0
      master/src/main/resources/mybatis/training/TTrainingbccDeviceMapper.xml
  16. 192 0
      master/src/main/resources/mybatis/training/TTrainingbccMapper.xml
  17. 7 1
      master/src/main/resources/mybatis/training/elearn/TElExamMapper.xml
  18. 53 0
      ui/src/api/training/bccdevice.js
  19. 72 0
      ui/src/api/training/trainingbcc.js
  20. 14 1
      ui/src/router/index.js
  21. 2 0
      ui/src/views/components/PlantProgList/index.vue
  22. 2 2
      ui/src/views/login.vue
  23. 439 0
      ui/src/views/training/bccdevice/index.vue
  24. 2 0
      ui/src/views/training/elearn/paper/list.vue
  25. 437 0
      ui/src/views/training/trainingbcc/deviceList.vue
  26. 1280 0
      ui/src/views/training/trainingbcc/index.vue
  27. 1502 0
      ui/src/views/training/trainingbcc/indexbak.vue
  28. 261 0
      ui/src/views/training/trainingbcc/trainingNew.vue
  29. 264 0
      ui/src/views/training/trainingbcc/trainingNon.vue

+ 2 - 2
master/pom.xml

@@ -119,8 +119,8 @@
             <version>${pagehelper.spring.boot.starter.version}</version>
         </dependency>
 
-        <!--阿里数据库连接池 -->
-        <dependency>
+        <dependency>        <!--阿里数据库连接池 -->
+
             <groupId>com.alibaba</groupId>
             <artifactId>druid-spring-boot-starter</artifactId>
             <version>${druid.version}</version>

+ 162 - 0
master/src/main/java/com/ruoyi/project/training/controller/TTrainingbccController.java

@@ -0,0 +1,162 @@
+package com.ruoyi.project.training.controller;
+
+import java.util.List;
+
+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 com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.project.training.domain.TTrainingbcc;
+import com.ruoyi.project.training.service.ITTrainingbccService;
+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;
+
+/**
+ * 装置培训跟踪bController
+ *
+ * @author ssy
+ * @date 2024-06-19
+ */
+@RestController
+@RequestMapping("/training/trainingbcc")
+public class TTrainingbccController extends BaseController
+{
+    @Autowired
+    private ITTrainingbccService tTrainingbccService;
+    @Resource
+    private TTrainingbccDeviceMapper tTrainingbccDeviceMapper;
+    @Resource
+    private TTrainingbccMapper tTrainingbccMapper;
+    /**
+     * 查询装置培训跟踪b列表
+     */
+    @PreAuthorize("@ss.hasPermi('training:trainingbcc:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(TTrainingbcc tTrainingbcc)
+    {
+        startPage();
+        List<TTrainingbcc> list = tTrainingbccService.selectTTrainingbccList(tTrainingbcc);
+        for (TTrainingbcc t: list
+             ) {
+            TTrainingbccDevice device = new TTrainingbccDevice();
+            device.setRegularId(t.getId());
+            int all = tTrainingbccDeviceMapper.countTraining(device);
+
+            device.setExamState(1l);
+            int finish = tTrainingbccDeviceMapper.countTraining(device);
+            t.setHaveTraining(finish);
+            t.setMustTraining(all);
+            if (all != 0) {
+                String per = String.valueOf(finish* 100 / all);
+                t.setTrainingPercent(per);
+            }else {
+                t.setTrainingPercent("0");
+            }
+        }
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出装置培训跟踪b列表
+     */
+    @PreAuthorize("@ss.hasPermi('training:trainingbcc:export')")
+    @Log(title = "装置培训跟踪b", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(TTrainingbcc tTrainingbcc)
+    {
+        List<TTrainingbcc> list = tTrainingbccService.selectTTrainingbccList(tTrainingbcc);
+        ExcelUtil<TTrainingbcc> util = new ExcelUtil<TTrainingbcc>(TTrainingbcc.class);
+        return util.exportExcel(list, "trainingbcc");
+    }
+
+    /**
+     * 获取装置培训跟踪b详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('training:trainingbcc:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return AjaxResult.success(tTrainingbccService.selectTTrainingbccById(id));
+    }
+
+    /**
+     * 获取装置培训跟踪b详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('training:trainingbcc:query')")
+    @GetMapping(value = "/staffIds/{id}")
+    public AjaxResult getStaffIds(@PathVariable("id") Long id)
+    {
+        TTrainingbcc tTrainingbcc = tTrainingbccService.selectTTrainingbccById(id);
+        TTrainingbccDevice param = new TTrainingbccDevice();
+        param.setRegularId(id);
+        List<TTrainingbccDevice> list = tTrainingbccDeviceMapper.selectTTrainingbccDeviceList(param);
+        String staffIds = "";
+        for (TTrainingbccDevice t : list
+             ) {
+            staffIds = staffIds + "," + t.getStaffId();
+        }
+        tTrainingbcc.setStaffIds(staffIds);
+        return AjaxResult.success(tTrainingbcc);
+    }
+
+
+    /**
+     * 新增装置培训跟踪b
+     */
+    @PreAuthorize("@ss.hasPermi('training:trainingbcc:add')")
+    @Log(title = "装置培训跟踪b", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody TTrainingbcc tTrainingbcc)
+    {
+        return toAjax(tTrainingbccService.insertTTrainingbcc(tTrainingbcc));
+    }
+
+    /**
+     * 修改装置培训跟踪b
+     */
+    @PreAuthorize("@ss.hasPermi('training:trainingbcc:edit')")
+    @Log(title = "装置培训跟踪b", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody TTrainingbcc tTrainingbcc)
+    {
+        return toAjax(tTrainingbccService.updateTTrainingbcc(tTrainingbcc));
+    }
+
+    /**
+     * 修改装置培训跟踪b
+     */
+    @PreAuthorize("@ss.hasPermi('training:trainingbcc:edit')")
+    @Log(title = "装置培训跟踪b", businessType = BusinessType.UPDATE)
+    @PostMapping(value = "/updateStaffIds")
+    public AjaxResult updateStaffIds(@RequestBody TTrainingbcc tTrainingbcc)
+    {
+        return toAjax(tTrainingbccService.updateStaffIds(tTrainingbcc));
+    }
+
+
+    /**
+     * 删除装置培训跟踪b
+     */
+    @PreAuthorize("@ss.hasPermi('training:trainingbcc:remove')")
+    @Log(title = "装置培训跟踪b", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(tTrainingbccService.deleteTTrainingbccByIds(ids));
+    }
+}

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

@@ -0,0 +1,112 @@
+package com.ruoyi.project.training.controller;
+
+import java.util.List;
+
+import com.ruoyi.project.training.domain.TTrainingbcc;
+import com.ruoyi.project.training.service.ITTrainingbccService;
+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.domain.TTrainingbccDevice;
+import com.ruoyi.project.training.service.ITTrainingbccDeviceService;
+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-19
+ */
+@RestController
+@RequestMapping("/training/bccdevice")
+public class TTrainingbccDeviceController extends BaseController
+{
+    @Autowired
+    private ITTrainingbccDeviceService tTrainingbccDeviceService;
+    @Autowired
+    private ITTrainingbccService tTrainingbccService;
+    /**
+     * 查询人员-装置级培训关系列表
+     */
+    @PreAuthorize("@ss.hasPermi('training:device:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(TTrainingbccDevice tTrainingbccDevice)
+    {
+        startPage();
+        List<TTrainingbccDevice> list = tTrainingbccDeviceService.selectTTrainingbccDeviceList(tTrainingbccDevice);
+        for (TTrainingbccDevice t: list
+             ) {
+          TTrainingbcc tTrainingbcc = tTrainingbccService.selectTTrainingbccById(t.getRegularId());
+            t.setTrainingbcc(tTrainingbcc);
+        }
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出人员-装置级培训关系列表
+     */
+    @PreAuthorize("@ss.hasPermi('training:device:export')")
+    @Log(title = "人员-装置级培训关系", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(TTrainingbccDevice tTrainingbccDevice)
+    {
+        List<TTrainingbccDevice> list = tTrainingbccDeviceService.selectTTrainingbccDeviceList(tTrainingbccDevice);
+        ExcelUtil<TTrainingbccDevice> util = new ExcelUtil<TTrainingbccDevice>(TTrainingbccDevice.class);
+        return util.exportExcel(list, "device");
+    }
+
+    /**
+     * 获取人员-装置级培训关系详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('training:device:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return AjaxResult.success(tTrainingbccDeviceService.selectTTrainingbccDeviceById(id));
+    }
+
+    /**
+     * 新增人员-装置级培训关系
+     */
+    @PreAuthorize("@ss.hasPermi('training:device:add')")
+    @Log(title = "人员-装置级培训关系", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody TTrainingbccDevice tTrainingbccDevice)
+    {
+        return toAjax(tTrainingbccDeviceService.insertTTrainingbccDevice(tTrainingbccDevice));
+    }
+
+    /**
+     * 修改人员-装置级培训关系
+     */
+    @PreAuthorize("@ss.hasPermi('training:device:edit')")
+    @Log(title = "人员-装置级培训关系", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody TTrainingbccDevice tTrainingbccDevice)
+    {
+        return toAjax(tTrainingbccDeviceService.updateTTrainingbccDevice(tTrainingbccDevice));
+    }
+
+    /**
+     * 删除人员-装置级培训关系
+     */
+    @PreAuthorize("@ss.hasPermi('training:device:remove')")
+    @Log(title = "人员-装置级培训关系", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(tTrainingbccDeviceService.deleteTTrainingbccDeviceByIds(ids));
+    }
+}

+ 524 - 0
master/src/main/java/com/ruoyi/project/training/domain/TTrainingbcc.java

@@ -0,0 +1,524 @@
+package com.ruoyi.project.training.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;
+
+/**
+ * 装置培训跟踪b对象 t_trainingbcc
+ *
+ * @author ssy
+ * @date 2024-06-19
+ */
+public class TTrainingbcc extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 唯一标识ID */
+    private Long id;
+
+    /** 装置名称 */
+    @Excel(name = "装置名称")
+    private String plantCode;
+
+    /** 培训课程 */
+    @Excel(name = "培训课程")
+    private String course;
+
+    /** 课程代码 */
+    @Excel(name = "课程代码")
+    private String courseid;
+
+    /** 培训周期 */
+    @Excel(name = "培训周期")
+    private String period;
+
+    /** 课时 */
+    @Excel(name = "课时")
+    private String duration;
+
+    /** 培训人 */
+    @Excel(name = "培训人")
+    private String trainer;
+
+    /** 培训岗位 */
+    @Excel(name = "培训岗位")
+    private String position;
+
+    /** 删除状态 */
+    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;
+
+    /** 培训开始日期 */
+    @JsonFormat(pattern = "yyyy-MM-dd" , timezone = "GMT+8")
+    @Excel(name = "培训开始日期", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date courseStartdate;
+
+    /** 培训结束日期 */
+    @JsonFormat(pattern = "yyyy-MM-dd" , timezone = "GMT+8")
+    @Excel(name = "培训结束日期", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date courseEnddate;
+
+    /** 是否完成 */
+    @Excel(name = "是否完成")
+    private Long isfinish;
+
+    /** 确认人 */
+    @Excel(name = "确认人")
+    private String confirmor;
+
+    /** 年份 */
+    @Excel(name = "年份")
+    private String years;
+
+    /** 培训内容 */
+    @Excel(name = "培训内容")
+    private String content;
+
+    /** 未参会人员名单 */
+    @Excel(name = "未参会人员名单")
+    private String nonParticipants;
+
+    /** 部门 */
+    @Excel(name = "部门")
+    private String unit;
+
+    /** 培训分类 */
+    @Excel(name = "培训分类")
+    private String trainingType;
+
+    /** 图片url */
+    @Excel(name = "图片url")
+    private String picUrl;
+
+    /** 装置级培训ID */
+    @Excel(name = "装置级培训ID")
+    private Long regularId;
+
+    /** 指定岗位 */
+    @Excel(name = "指定岗位")
+    private String designatedPosition;
+
+    /** 指定人员 */
+    @Excel(name = "指定人员")
+    private String designatedStaff;
+
+    /** 学习链接 */
+    @Excel(name = "学习链接")
+    private String fileUrl;
+
+    /** 文件名 */
+    @Excel(name = "文件名")
+    private String fileName;
+
+    /** 需要学习时长 */
+    @Excel(name = "需要学习时长")
+    private Long timerNeed;
+
+    private int haveTraining;
+
+    private int mustTraining;
+    private String trainingPercent;
+    /** 考试ID */
+    @Excel(name = "考试ID")
+    private Long examId;
+
+    private String deptName;
+
+    private String staffIds;
+
+    public int getHaveTraining() {
+        return haveTraining;
+    }
+
+    public void setHaveTraining(int haveTraining) {
+        this.haveTraining = haveTraining;
+    }
+
+    public int getMustTraining() {
+        return mustTraining;
+    }
+
+    public void setMustTraining(int mustTraining) {
+        this.mustTraining = mustTraining;
+    }
+
+    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 setCourse(String course)
+    {
+        this.course = course;
+    }
+
+    public String getCourse()
+    {
+        return course;
+    }
+    public void setCourseid(String courseid)
+    {
+        this.courseid = courseid;
+    }
+
+    public String getCourseid()
+    {
+        return courseid;
+    }
+    public void setPeriod(String period)
+    {
+        this.period = period;
+    }
+
+    public String getPeriod()
+    {
+        return period;
+    }
+    public void setDuration(String duration)
+    {
+        this.duration = duration;
+    }
+
+    public String getDuration()
+    {
+        return duration;
+    }
+    public void setTrainer(String trainer)
+    {
+        this.trainer = trainer;
+    }
+
+    public String getTrainer()
+    {
+        return trainer;
+    }
+    public void setPosition(String position)
+    {
+        this.position = position;
+    }
+
+    public String getPosition()
+    {
+        return position;
+    }
+    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 void setDeptId(Long deptId)
+    {
+        this.deptId = deptId;
+    }
+
+    public Long getDeptId()
+    {
+        return deptId;
+    }
+    public void setCourseStartdate(Date courseStartdate)
+    {
+        this.courseStartdate = courseStartdate;
+    }
+
+    public Date getCourseStartdate()
+    {
+        return courseStartdate;
+    }
+    public void setCourseEnddate(Date courseEnddate)
+    {
+        this.courseEnddate = courseEnddate;
+    }
+
+    public Date getCourseEnddate()
+    {
+        return courseEnddate;
+    }
+    public void setIsfinish(Long isfinish)
+    {
+        this.isfinish = isfinish;
+    }
+
+    public Long getIsfinish()
+    {
+        return isfinish;
+    }
+    public void setConfirmor(String confirmor)
+    {
+        this.confirmor = confirmor;
+    }
+
+    public String getConfirmor()
+    {
+        return confirmor;
+    }
+    public void setYears(String years)
+    {
+        this.years = years;
+    }
+
+    public String getYears()
+    {
+        return years;
+    }
+    public void setContent(String content)
+    {
+        this.content = content;
+    }
+
+    public String getContent()
+    {
+        return content;
+    }
+    public void setNonParticipants(String nonParticipants)
+    {
+        this.nonParticipants = nonParticipants;
+    }
+
+    public String getNonParticipants()
+    {
+        return nonParticipants;
+    }
+    public void setUnit(String unit)
+    {
+        this.unit = unit;
+    }
+
+    public String getTrainingPercent() {
+        return trainingPercent;
+    }
+
+    public void setTrainingPercent(String trainingPercent) {
+        this.trainingPercent = trainingPercent;
+    }
+
+    public String getUnit()
+    {
+        return unit;
+    }
+    public void setTrainingType(String trainingType)
+    {
+        this.trainingType = trainingType;
+    }
+
+    public String getTrainingType()
+    {
+        return trainingType;
+    }
+    public void setPicUrl(String picUrl)
+    {
+        this.picUrl = picUrl;
+    }
+
+    public String getPicUrl()
+    {
+        return picUrl;
+    }
+    public void setRegularId(Long regularId)
+    {
+        this.regularId = regularId;
+    }
+
+    public Long getRegularId()
+    {
+        return regularId;
+    }
+    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 setFileUrl(String fileUrl)
+    {
+        this.fileUrl = fileUrl;
+    }
+
+    public String getFileUrl()
+    {
+        return fileUrl;
+    }
+    public void setFileName(String fileName)
+    {
+        this.fileName = fileName;
+    }
+
+    public String getFileName()
+    {
+        return fileName;
+    }
+    public void setTimerNeed(Long timerNeed)
+    {
+        this.timerNeed = timerNeed;
+    }
+
+    public Long getTimerNeed()
+    {
+        return timerNeed;
+    }
+    public void setExamId(Long examId)
+    {
+        this.examId = examId;
+    }
+
+    public Long getExamId()
+    {
+        return examId;
+    }
+
+    public String getDeptName() {
+        return deptName;
+    }
+
+    public void setDeptName(String deptName) {
+        this.deptName = deptName;
+    }
+
+    public String getStaffIds() {
+        return staffIds;
+    }
+
+    public void setStaffIds(String staffIds) {
+        this.staffIds = staffIds;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("id", getId())
+            .append("plantCode", getPlantCode())
+            .append("course", getCourse())
+            .append("courseid", getCourseid())
+            .append("period", getPeriod())
+            .append("duration", getDuration())
+            .append("trainer", getTrainer())
+            .append("position", getPosition())
+            .append("delFlag", getDelFlag())
+            .append("createrCode", getCreaterCode())
+            .append("createdate", getCreatedate())
+            .append("updaterCode", getUpdaterCode())
+            .append("updatedate", getUpdatedate())
+            .append("remarks", getRemarks())
+            .append("deptId", getDeptId())
+            .append("courseStartdate", getCourseStartdate())
+            .append("courseEnddate", getCourseEnddate())
+            .append("isfinish", getIsfinish())
+            .append("confirmor", getConfirmor())
+            .append("years", getYears())
+            .append("content", getContent())
+            .append("nonParticipants", getNonParticipants())
+            .append("unit", getUnit())
+            .append("trainingType", getTrainingType())
+            .append("picUrl", getPicUrl())
+            .append("regularId", getRegularId())
+            .append("designatedPosition", getDesignatedPosition())
+            .append("designatedStaff", getDesignatedStaff())
+            .append("fileUrl", getFileUrl())
+            .append("fileName", getFileName())
+            .append("timerNeed", getTimerNeed())
+            .append("examId", getExamId())
+            .toString();
+    }
+}

+ 278 - 0
master/src/main/java/com/ruoyi/project/training/domain/TTrainingbccDevice.java

@@ -0,0 +1,278 @@
+package com.ruoyi.project.training.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_trainingbcc_device
+ *
+ * @author ssy
+ * @date 2024-06-19
+ */
+public class TTrainingbccDevice extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 唯一标识ID */
+    private Long id;
+
+    /** 人员员工号 */
+    @Excel(name = "人员员工号")
+    private String staffId;
+
+    /** 装置级培训ID */
+    @Excel(name = "装置级培训ID")
+    private Long regularId;
+
+    /** 开始日期 */
+    @JsonFormat(pattern = "yyyy-MM-dd" , timezone = "GMT+8")
+    @Excel(name = "开始日期", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date startDate;
+
+    /** 备注 */
+    @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 String supplementary;
+
+    /** 学习状态 */
+    @Excel(name = "学习状态")
+    private Long learnState;
+
+    /** 考试状态 */
+    @Excel(name = "考试状态")
+    private Long examState;
+
+    /** 考试ID */
+    @Excel(name = "考试ID")
+    private Long examId;
+
+    private Integer examNum;
+
+    @JsonFormat(pattern = "yyyy-MM-dd" , timezone = "GMT+8")
+    private Date examDate;
+
+    private String name;
+
+    /** 学习时长min */
+    @Excel(name = "学习时长min")
+    private Long learnTime;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    private TTrainingbcc trainingbcc;
+
+    public void setId(Long id)
+    {
+        this.id = id;
+    }
+
+    public Long getId()
+    {
+        return id;
+    }
+    public void setStaffId(String staffId)
+    {
+        this.staffId = staffId;
+    }
+
+    public String getStaffId()
+    {
+        return staffId;
+    }
+    public void setRegularId(Long regularId)
+    {
+        this.regularId = regularId;
+    }
+
+    public Long getRegularId()
+    {
+        return regularId;
+    }
+    public void setStartDate(Date startDate)
+    {
+        this.startDate = startDate;
+    }
+
+    public Date getStartDate()
+    {
+        return startDate;
+    }
+    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 setSupplementary(String supplementary)
+    {
+        this.supplementary = supplementary;
+    }
+
+    public String getSupplementary()
+    {
+        return supplementary;
+    }
+    public void setLearnState(Long learnState)
+    {
+        this.learnState = learnState;
+    }
+
+    public Long getLearnState()
+    {
+        return learnState;
+    }
+    public void setExamState(Long examState)
+    {
+        this.examState = examState;
+    }
+
+    public Long getExamState()
+    {
+        return examState;
+    }
+    public void setExamId(Long examId)
+    {
+        this.examId = examId;
+    }
+
+    public Long getExamId()
+    {
+        return examId;
+    }
+    public void setLearnTime(Long learnTime)
+    {
+        this.learnTime = learnTime;
+    }
+
+    public Long getLearnTime()
+    {
+        return learnTime;
+    }
+
+    public TTrainingbcc getTrainingbcc() {
+        return trainingbcc;
+    }
+
+    public void setTrainingbcc(TTrainingbcc trainingbcc) {
+        this.trainingbcc = trainingbcc;
+    }
+
+    public Integer getExamNum() {
+        return examNum;
+    }
+
+    public void setExamNum(Integer examNum) {
+        this.examNum = examNum;
+    }
+
+    public Date getExamDate() {
+        return examDate;
+    }
+
+    public void setExamDate(Date examDate) {
+        this.examDate = examDate;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("id", getId())
+            .append("staffId", getStaffId())
+            .append("regularId", getRegularId())
+            .append("startDate", getStartDate())
+            .append("remarks", getRemarks())
+            .append("delFlag", getDelFlag())
+            .append("createrCode", getCreaterCode())
+            .append("createdate", getCreatedate())
+            .append("updaterCode", getUpdaterCode())
+            .append("updatedate", getUpdatedate())
+            .append("supplementary", getSupplementary())
+            .append("learnState", getLearnState())
+            .append("examState", getExamState())
+            .append("examId", getExamId())
+            .append("learnTime", getLearnTime())
+            .toString();
+    }
+}

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

@@ -89,6 +89,9 @@ public class TElExam extends BaseEntity
     @Excel(name = "所属部门")
     private Long deptId;
 
+    /** 类型 */
+    private Integer examType;
+
     /** 备注 */
     @Excel(name = "备注")
     private String remarks;

+ 67 - 0
master/src/main/java/com/ruoyi/project/training/mapper/TTrainingbccDeviceMapper.java

@@ -0,0 +1,67 @@
+package com.ruoyi.project.training.mapper;
+
+import java.util.List;
+import com.ruoyi.framework.aspectj.lang.annotation.DataScope;
+import com.ruoyi.project.training.domain.TTrainingbccDevice;
+
+/**
+ * 人员-装置级培训关系Mapper接口
+ *
+ * @author ssy
+ * @date 2024-06-19
+ */
+public interface TTrainingbccDeviceMapper
+{
+    /**
+     * 查询人员-装置级培训关系
+     *
+     * @param id 人员-装置级培训关系ID
+     * @return 人员-装置级培训关系
+     */
+    public TTrainingbccDevice selectTTrainingbccDeviceById(Long id);
+
+    /**
+     * 查询人员-装置级培训关系列表
+     *
+     * @param tTrainingbccDevice 人员-装置级培训关系
+     * @return 人员-装置级培训关系集合
+     */
+    @DataScope(deptAlias = "d")
+    public List<TTrainingbccDevice> selectTTrainingbccDeviceList(TTrainingbccDevice tTrainingbccDevice);
+
+    /**
+     * 新增人员-装置级培训关系
+     *
+     * @param tTrainingbccDevice 人员-装置级培训关系
+     * @return 结果
+     */
+    public int insertTTrainingbccDevice(TTrainingbccDevice tTrainingbccDevice);
+
+    /**
+     * 修改人员-装置级培训关系
+     *
+     * @param tTrainingbccDevice 人员-装置级培训关系
+     * @return 结果
+     */
+    public int updateTTrainingbccDevice(TTrainingbccDevice tTrainingbccDevice);
+
+    /**
+     * 删除人员-装置级培训关系
+     *
+     * @param id 人员-装置级培训关系ID
+     * @return 结果
+     */
+    public int deleteTTrainingbccDeviceById(Long id);
+
+    /**
+     * 批量删除人员-装置级培训关系
+     *
+     * @param ids 需要删除的数据ID
+     * @return 结果
+     */
+    public int deleteTTrainingbccDeviceByIds(Long[] ids);
+
+    void deleteTTrainingbccDeviceByStaff(TTrainingbccDevice device);
+
+    int countTraining(TTrainingbccDevice device);
+}

+ 63 - 0
master/src/main/java/com/ruoyi/project/training/mapper/TTrainingbccMapper.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.TTrainingbcc;
+
+/**
+ * 装置培训跟踪bMapper接口
+ *
+ * @author ssy
+ * @date 2024-06-19
+ */
+public interface TTrainingbccMapper
+{
+    /**
+     * 查询装置培训跟踪b
+     *
+     * @param id 装置培训跟踪bID
+     * @return 装置培训跟踪b
+     */
+    public TTrainingbcc selectTTrainingbccById(Long id);
+
+    /**
+     * 查询装置培训跟踪b列表
+     *
+     * @param tTrainingbcc 装置培训跟踪b
+     * @return 装置培训跟踪b集合
+     */
+    @DataScope(deptAlias = "d")
+    public List<TTrainingbcc> selectTTrainingbccList(TTrainingbcc tTrainingbcc);
+
+    /**
+     * 新增装置培训跟踪b
+     *
+     * @param tTrainingbcc 装置培训跟踪b
+     * @return 结果
+     */
+    public int insertTTrainingbcc(TTrainingbcc tTrainingbcc);
+
+    /**
+     * 修改装置培训跟踪b
+     *
+     * @param tTrainingbcc 装置培训跟踪b
+     * @return 结果
+     */
+    public int updateTTrainingbcc(TTrainingbcc tTrainingbcc);
+
+    /**
+     * 删除装置培训跟踪b
+     *
+     * @param id 装置培训跟踪bID
+     * @return 结果
+     */
+    public int deleteTTrainingbccById(Long id);
+
+    /**
+     * 批量删除装置培训跟踪b
+     *
+     * @param ids 需要删除的数据ID
+     * @return 结果
+     */
+    public int deleteTTrainingbccByIds(Long[] ids);
+}

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

@@ -0,0 +1,61 @@
+package com.ruoyi.project.training.service;
+
+import java.util.List;
+import com.ruoyi.project.training.domain.TTrainingbccDevice;
+
+/**
+ * 人员-装置级培训关系Service接口
+ *
+ * @author ssy
+ * @date 2024-06-19
+ */
+public interface ITTrainingbccDeviceService
+{
+    /**
+     * 查询人员-装置级培训关系
+     *
+     * @param id 人员-装置级培训关系ID
+     * @return 人员-装置级培训关系
+     */
+    public TTrainingbccDevice selectTTrainingbccDeviceById(Long id);
+
+    /**
+     * 查询人员-装置级培训关系列表
+     *
+     * @param tTrainingbccDevice 人员-装置级培训关系
+     * @return 人员-装置级培训关系集合
+     */
+    public List<TTrainingbccDevice> selectTTrainingbccDeviceList(TTrainingbccDevice tTrainingbccDevice);
+
+    /**
+     * 新增人员-装置级培训关系
+     *
+     * @param tTrainingbccDevice 人员-装置级培训关系
+     * @return 结果
+     */
+    public int insertTTrainingbccDevice(TTrainingbccDevice tTrainingbccDevice);
+
+    /**
+     * 修改人员-装置级培训关系
+     *
+     * @param tTrainingbccDevice 人员-装置级培训关系
+     * @return 结果
+     */
+    public int updateTTrainingbccDevice(TTrainingbccDevice tTrainingbccDevice);
+
+    /**
+     * 批量删除人员-装置级培训关系
+     *
+     * @param ids 需要删除的人员-装置级培训关系ID
+     * @return 结果
+     */
+    public int deleteTTrainingbccDeviceByIds(Long[] ids);
+
+    /**
+     * 删除人员-装置级培训关系信息
+     *
+     * @param id 人员-装置级培训关系ID
+     * @return 结果
+     */
+    public int deleteTTrainingbccDeviceById(Long id);
+}

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

@@ -0,0 +1,63 @@
+package com.ruoyi.project.training.service;
+
+import java.util.List;
+import com.ruoyi.project.training.domain.TTrainingbcc;
+
+/**
+ * 装置培训跟踪bService接口
+ *
+ * @author ssy
+ * @date 2024-06-19
+ */
+public interface ITTrainingbccService
+{
+    /**
+     * 查询装置培训跟踪b
+     *
+     * @param id 装置培训跟踪bID
+     * @return 装置培训跟踪b
+     */
+    public TTrainingbcc selectTTrainingbccById(Long id);
+
+    /**
+     * 查询装置培训跟踪b列表
+     *
+     * @param tTrainingbcc 装置培训跟踪b
+     * @return 装置培训跟踪b集合
+     */
+    public List<TTrainingbcc> selectTTrainingbccList(TTrainingbcc tTrainingbcc);
+
+    /**
+     * 新增装置培训跟踪b
+     *
+     * @param tTrainingbcc 装置培训跟踪b
+     * @return 结果
+     */
+    public int insertTTrainingbcc(TTrainingbcc tTrainingbcc);
+
+    /**
+     * 修改装置培训跟踪b
+     *
+     * @param tTrainingbcc 装置培训跟踪b
+     * @return 结果
+     */
+    public int updateTTrainingbcc(TTrainingbcc tTrainingbcc);
+
+    /**
+     * 批量删除装置培训跟踪b
+     *
+     * @param ids 需要删除的装置培训跟踪bID
+     * @return 结果
+     */
+    public int deleteTTrainingbccByIds(Long[] ids);
+
+    /**
+     * 删除装置培训跟踪b信息
+     *
+     * @param id 装置培训跟踪bID
+     * @return 结果
+     */
+    public int deleteTTrainingbccById(Long id);
+
+    int updateStaffIds(TTrainingbcc tTrainingbcc);
+}

+ 93 - 0
master/src/main/java/com/ruoyi/project/training/service/impl/TTrainingbccDeviceServiceImpl.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.TTrainingbccDeviceMapper;
+import com.ruoyi.project.training.domain.TTrainingbccDevice;
+import com.ruoyi.project.training.service.ITTrainingbccDeviceService;
+
+/**
+ * 人员-装置级培训关系Service业务层处理
+ *
+ * @author ssy
+ * @date 2024-06-19
+ */
+@Service
+public class TTrainingbccDeviceServiceImpl implements ITTrainingbccDeviceService
+{
+    @Autowired
+    private TTrainingbccDeviceMapper tTrainingbccDeviceMapper;
+
+    /**
+     * 查询人员-装置级培训关系
+     *
+     * @param id 人员-装置级培训关系ID
+     * @return 人员-装置级培训关系
+     */
+    @Override
+    public TTrainingbccDevice selectTTrainingbccDeviceById(Long id)
+    {
+        return tTrainingbccDeviceMapper.selectTTrainingbccDeviceById(id);
+    }
+
+    /**
+     * 查询人员-装置级培训关系列表
+     *
+     * @param tTrainingbccDevice 人员-装置级培训关系
+     * @return 人员-装置级培训关系
+     */
+    @Override
+    public List<TTrainingbccDevice> selectTTrainingbccDeviceList(TTrainingbccDevice tTrainingbccDevice)
+    {
+        return tTrainingbccDeviceMapper.selectTTrainingbccDeviceList(tTrainingbccDevice);
+    }
+
+    /**
+     * 新增人员-装置级培训关系
+     *
+     * @param tTrainingbccDevice 人员-装置级培训关系
+     * @return 结果
+     */
+    @Override
+    public int insertTTrainingbccDevice(TTrainingbccDevice tTrainingbccDevice)
+    {
+        return tTrainingbccDeviceMapper.insertTTrainingbccDevice(tTrainingbccDevice);
+    }
+
+    /**
+     * 修改人员-装置级培训关系
+     *
+     * @param tTrainingbccDevice 人员-装置级培训关系
+     * @return 结果
+     */
+    @Override
+    public int updateTTrainingbccDevice(TTrainingbccDevice tTrainingbccDevice)
+    {
+        return tTrainingbccDeviceMapper.updateTTrainingbccDevice(tTrainingbccDevice);
+    }
+
+    /**
+     * 批量删除人员-装置级培训关系
+     *
+     * @param ids 需要删除的人员-装置级培训关系ID
+     * @return 结果
+     */
+    @Override
+    public int deleteTTrainingbccDeviceByIds(Long[] ids)
+    {
+        return tTrainingbccDeviceMapper.deleteTTrainingbccDeviceByIds(ids);
+    }
+
+    /**
+     * 删除人员-装置级培训关系信息
+     *
+     * @param id 人员-装置级培训关系ID
+     * @return 结果
+     */
+    @Override
+    public int deleteTTrainingbccDeviceById(Long id)
+    {
+        return tTrainingbccDeviceMapper.deleteTTrainingbccDeviceById(id);
+    }
+}

+ 168 - 0
master/src/main/java/com/ruoyi/project/training/service/impl/TTrainingbccServiceImpl.java

@@ -0,0 +1,168 @@
+package com.ruoyi.project.training.service.impl;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import com.alibaba.fastjson.JSON;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.framework.web.controller.BaseController;
+import com.ruoyi.project.training.domain.TTrainingbccDevice;
+import com.ruoyi.project.training.mapper.TTrainingbccDeviceMapper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.ruoyi.project.training.mapper.TTrainingbccMapper;
+import com.ruoyi.project.training.domain.TTrainingbcc;
+import com.ruoyi.project.training.service.ITTrainingbccService;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.Resource;
+
+/**
+ * 装置培训跟踪bService业务层处理
+ *
+ * @author ssy
+ * @date 2024-06-19
+ */
+@Service
+public class TTrainingbccServiceImpl implements ITTrainingbccService
+{
+    @Resource
+    private TTrainingbccMapper tTrainingbccMapper;
+    @Resource
+    private TTrainingbccDeviceMapper tTrainingbccDeviceMapper;
+
+    protected final Logger logger = LoggerFactory.getLogger(BaseController.class);
+    /**
+     * 查询装置培训跟踪b
+     *
+     * @param id 装置培训跟踪bID
+     * @return 装置培训跟踪b
+     */
+    @Override
+    public TTrainingbcc selectTTrainingbccById(Long id)
+    {
+        return tTrainingbccMapper.selectTTrainingbccById(id);
+    }
+
+    /**
+     * 查询装置培训跟踪b列表
+     *
+     * @param tTrainingbcc 装置培训跟踪b
+     * @return 装置培训跟踪b
+     */
+    @Override
+    public List<TTrainingbcc> selectTTrainingbccList(TTrainingbcc tTrainingbcc)
+    {
+        return tTrainingbccMapper.selectTTrainingbccList(tTrainingbcc);
+    }
+
+    /**
+     * 新增装置培训跟踪b
+     *
+     * @param tTrainingbcc 装置培训跟踪b
+     * @return 结果
+     */
+    @Override
+    public int insertTTrainingbcc(TTrainingbcc tTrainingbcc)
+    {
+        return tTrainingbccMapper.insertTTrainingbcc(tTrainingbcc);
+    }
+
+    /**
+     * 修改装置培训跟踪b
+     *
+     * @param tTrainingbcc 装置培训跟踪b
+     * @return 结果
+     */
+    @Override
+    public int updateTTrainingbcc(TTrainingbcc tTrainingbcc)
+    {
+        return tTrainingbccMapper.updateTTrainingbcc(tTrainingbcc);
+    }
+
+    /**
+     * 批量删除装置培训跟踪b
+     *
+     * @param ids 需要删除的装置培训跟踪bID
+     * @return 结果
+     */
+    @Override
+    public int deleteTTrainingbccByIds(Long[] ids)
+    {
+        return tTrainingbccMapper.deleteTTrainingbccByIds(ids);
+    }
+
+    /**
+     * 删除装置培训跟踪b信息
+     *
+     * @param id 装置培训跟踪bID
+     * @return 结果
+     */
+    @Override
+    public int deleteTTrainingbccById(Long id)
+    {
+        return tTrainingbccMapper.deleteTTrainingbccById(id);
+    }
+
+    @Override
+    @Transactional
+    public int updateStaffIds(TTrainingbcc tTrainingbcc) {
+        TTrainingbccDevice param = new TTrainingbccDevice();
+        param.setRegularId(tTrainingbcc.getId());
+        List<TTrainingbccDevice> list = tTrainingbccDeviceMapper.selectTTrainingbccDeviceList(param);
+        List<String> nowStaff = list.stream()
+                .map(TTrainingbccDevice::getStaffId)
+                .collect(Collectors.toList());
+        logger.info(JSON.toJSONString(tTrainingbcc));
+        List<String> newStaff = Arrays.asList(tTrainingbcc.getStaffIds().split(",").clone());
+
+        // 找出a有b没有的元素
+        List<String> needDel = new ArrayList<>();
+        for (String element : nowStaff) {
+            if (!newStaff.contains(element)) {
+                needDel.add(element);
+            }
+        }
+
+        // 找出b有a没有的元素
+        List<String> needAdd = new ArrayList<>();
+        for (String element : newStaff) {
+            if (!nowStaff.contains(element)) {
+                needAdd.add(element);
+            }
+        }
+
+        //删除
+        for (String staff: needDel
+             ) {
+            if (StringUtils.isNotEmpty(staff))  {
+                TTrainingbccDevice device = new TTrainingbccDevice();
+                device.setRegularId(tTrainingbcc.getId());
+                device.setStaffId(staff);
+                tTrainingbccDeviceMapper.deleteTTrainingbccDeviceByStaff(device);
+            }
+
+        }
+        //新增
+        TTrainingbcc trainingbcc = tTrainingbccMapper.selectTTrainingbccById(tTrainingbcc.getId());
+        for (String staff :needAdd
+             ) {
+            if (StringUtils.isNotEmpty(staff))  {
+                TTrainingbccDevice device = new TTrainingbccDevice();
+                device.setStaffId(staff);
+                device.setRegularId(tTrainingbcc.getId());
+                device.setStartDate(trainingbcc.getCourseStartdate());
+                logger.info(JSON.toJSONString(device));
+                tTrainingbccDeviceMapper.insertTTrainingbccDevice(device);
+            }
+
+        }
+
+
+        return 1;
+    }
+}

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

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

+ 3 - 0
master/src/main/resources/mybatis/document/TPlantproglistMapper.xml

@@ -201,6 +201,9 @@
             <if test="filedate != null">filedate = #{filedate},</if>
             <if test="reviewdate != null">reviewdate = #{reviewdate},</if>
             <if test="nextreviewdate != null">nextreviewdate = #{nextreviewdate},</if>
+            <if test="nexteditdate == null">nexteditdate = NULL,</if>
+            <if test="reviewdate == null">reviewdate = NULL,</if>
+            <if test="nextreviewdate == null">nextreviewdate = NULL,</if>
             <if test="nexteditdate != null">nexteditdate = #{nexteditdate},</if>
             <if test="item != null">item = #{item},</if>
             <if test="delFlag != null">del_flag = #{delFlag},</if>

+ 148 - 0
master/src/main/resources/mybatis/training/TTrainingbccDeviceMapper.xml

@@ -0,0 +1,148 @@
+<?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.TTrainingbccDeviceMapper">
+
+    <resultMap type="TTrainingbccDevice" id="TTrainingbccDeviceResult">
+        <result property="id"    column="id"    />
+        <result property="staffId"    column="staff_id"    />
+        <result property="regularId"    column="regular_id"    />
+        <result property="startDate"    column="start_date"    />
+        <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="supplementary"    column="supplementary"    />
+        <result property="learnState"    column="learn_state"    />
+        <result property="examState"    column="exam_state"    />
+        <result property="examId"    column="exam_id"    />
+        <result property="learnTime"    column="learn_time"    />
+        <result property="deptName" column="dept_name" />
+    </resultMap>
+
+    <sql id="selectTTrainingbccDeviceVo">
+        select d.id,s.name , d.staff_id, d.regular_id, d.start_date, d.remarks, d.del_flag, d.creater_code, d.createdate, d.updater_code, d.updatedate, d.supplementary, d.learn_state, d.exam_state, d.exam_id, d.learn_time from t_trainingbcc_device d
+       left join t_staffmgr s on s.staffid = d.staff_id
+</sql>
+
+    <select id="selectTTrainingbccDeviceList" parameterType="TTrainingbccDevice" resultMap="TTrainingbccDeviceResult">
+        <include refid="selectTTrainingbccDeviceVo"/>
+        <where>
+            <if test="staffId != null  and staffId != ''"> and staff_id = #{staffId}</if>
+            <if test="regularId != null "> and regular_id = #{regularId}</if>
+            <if test="startDate != null "> and start_date = #{startDate}</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="supplementary != null  and supplementary != ''"> and supplementary = #{supplementary}</if>
+            <if test="learnState != null "> and learn_state = #{learnState}</if>
+            <if test="examState != null "> and exam_state = #{examState}</if>
+            <if test="examId != null "> and exam_id = #{examId}</if>
+            <if test="learnTime != null "> and learn_time = #{learnTime}</if>
+            and d.del_flag = 0
+        </where>
+        <!-- 数据范围过滤 -->
+        ${params.dataScope}
+    </select>
+
+    <select id="selectTTrainingbccDeviceById" parameterType="Long" resultMap="TTrainingbccDeviceResult">
+        <include refid="selectTTrainingbccDeviceVo"/>
+        where d.id = #{id}
+    </select>
+
+    <insert id="insertTTrainingbccDevice" parameterType="TTrainingbccDevice">
+        <selectKey keyProperty="id" resultType="long" order="BEFORE">
+            SELECT seq_t_trainingbcc_device.NEXTVAL as id FROM DUAL
+        </selectKey>
+        insert into t_trainingbcc_device
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="id != null">id,</if>
+            <if test="staffId != null">staff_id,</if>
+            <if test="regularId != null">regular_id,</if>
+            <if test="startDate != null">start_date,</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="supplementary != null">supplementary,</if>
+            <if test="learnState != null">learn_state,</if>
+            <if test="examState != null">exam_state,</if>
+            <if test="examId != null">exam_id,</if>
+            <if test="learnTime != null">learn_time,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="id != null">#{id},</if>
+            <if test="staffId != null">#{staffId},</if>
+            <if test="regularId != null">#{regularId},</if>
+            <if test="startDate != null">#{startDate},</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="supplementary != null">#{supplementary},</if>
+            <if test="learnState != null">#{learnState},</if>
+            <if test="examState != null">#{examState},</if>
+            <if test="examId != null">#{examId},</if>
+            <if test="learnTime != null">#{learnTime},</if>
+         </trim>
+    </insert>
+
+    <update id="updateTTrainingbccDevice" parameterType="TTrainingbccDevice">
+        update t_trainingbcc_device
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="staffId != null">staff_id = #{staffId},</if>
+            <if test="regularId != null">regular_id = #{regularId},</if>
+            <if test="startDate != null">start_date = #{startDate},</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="supplementary != null">supplementary = #{supplementary},</if>
+            <if test="learnState != null">learn_state = #{learnState},</if>
+            <if test="examState != null">exam_state = #{examState},</if>
+            <if test="examId != null">exam_id = #{examId},</if>
+            <if test="learnTime != null">learn_time = #{learnTime},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <update id="deleteTTrainingbccDeviceById" parameterType="Long">
+        update t_trainingbcc_device set del_flag = 2 where id = #{id}
+    </update>
+
+    <update id="deleteTTrainingbccDeviceByStaff" parameterType="TTrainingbccDevice">
+        update t_trainingbcc_device set del_flag = 2 where staff_id = #{staffId} and regular_id = #{regularId}
+    </update>
+
+
+
+    <update id="deleteTTrainingbccDeviceByIds" parameterType="String">
+        update t_trainingbcc_device set del_flag = 2 where id in
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </update>
+
+    <select id="countTraining" parameterType="TTrainingbccDevice" resultType="int">
+        select count(1) from t_trainingbcc_device
+        <where>
+            <if test="regularId != null "> and regular_id = #{regularId}</if>
+            <if test="examState != null "> and exam_state = #{examState}</if>
+            and del_flag = 0
+        </where>
+
+    </select>
+
+
+</mapper>

+ 192 - 0
master/src/main/resources/mybatis/training/TTrainingbccMapper.xml

@@ -0,0 +1,192 @@
+<?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.TTrainingbccMapper">
+
+    <resultMap type="TTrainingbcc" id="TTrainingbccResult">
+        <result property="id"    column="id"    />
+        <result property="plantCode"    column="plant_code"    />
+        <result property="course"    column="course"    />
+        <result property="courseid"    column="courseid"    />
+        <result property="period"    column="period"    />
+        <result property="duration"    column="duration"    />
+        <result property="trainer"    column="trainer"    />
+        <result property="position"    column="position"    />
+        <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="courseStartdate"    column="course_startdate"    />
+        <result property="courseEnddate"    column="course_enddate"    />
+        <result property="isfinish"    column="isfinish"    />
+        <result property="confirmor"    column="confirmor"    />
+        <result property="years"    column="years"    />
+        <result property="content"    column="content"    />
+        <result property="nonParticipants"    column="non_participants"    />
+        <result property="unit"    column="unit"    />
+        <result property="trainingType"    column="training_type"    />
+        <result property="picUrl"    column="pic_url"    />
+        <result property="regularId"    column="regular_id"    />
+        <result property="designatedPosition"    column="designated_position"    />
+        <result property="designatedStaff"    column="designated_staff"    />
+        <result property="fileUrl"    column="file_url"    />
+        <result property="fileName"    column="file_name"    />
+        <result property="timerNeed"    column="timer_need"    />
+        <result property="examId"    column="exam_id"    />
+        <result property="deptName" column="dept_name" />
+    </resultMap>
+
+    <sql id="selectTTrainingbccVo">
+        select d.id, d.plant_code, d.course, d.courseid, d.period, d.duration, d.trainer, d.position, d.del_flag, d.creater_code, d.createdate, d.updater_code, d.updatedate, d.remarks, d.dept_id, d.course_startdate, d.course_enddate, d.isfinish, d.confirmor, d.years, d.content, d.non_participants, d.unit, d.training_type, d.pic_url, d.regular_id, d.designated_position, d.designated_staff, d.file_url, d.file_name, d.timer_need, d.exam_id  from t_trainingbcc d
+
+    </sql>
+
+    <select id="selectTTrainingbccList" parameterType="TTrainingbcc" resultMap="TTrainingbccResult">
+        <include refid="selectTTrainingbccVo"/>
+        <where>
+            <if test="years != null ">and years = #{years}</if>
+            <if test="plantCode != null  and plantCode != ''"> and plant_code = #{plantCode}</if>
+            <if test="course != null  and course != ''"> and course like concat(concat('%', #{course}), '%')</if>
+            <if test="courseid != null  and courseid != ''"> and courseid = #{courseid}</if>
+            <if test="period != null  and period != ''"> and period = #{period}</if>
+            <if test="duration != null  and duration != ''"> and duration = #{duration}</if>
+            <if test="trainer != null  and trainer != ''"> and trainer = #{trainer}</if>
+            <if test="position != null  and position != ''"> and position = #{position}</if>
+            <if test="trainingType != null and trainingType != ''">and training_type = #{trainingType}</if>
+            and d.del_flag = 0
+        </where>
+        <!-- 数据范围过滤 -->
+        ${params.dataScope}
+    </select>
+
+    <select id="selectTTrainingbccById" parameterType="Long" resultMap="TTrainingbccResult">
+        <include refid="selectTTrainingbccVo"/>
+        where id = #{id}
+    </select>
+
+    <insert id="insertTTrainingbcc" parameterType="TTrainingbcc">
+        insert into t_trainingbcc
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="id != null">id,</if>
+            <if test="plantCode != null">plant_code,</if>
+            <if test="course != null and course != ''">course,</if>
+            <if test="courseid != null">courseid,</if>
+            <if test="period != null">period,</if>
+            <if test="duration != null">duration,</if>
+            <if test="trainer != null">trainer,</if>
+            <if test="position != null">position,</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="courseStartdate != null">course_startdate,</if>
+            <if test="courseEnddate != null">course_enddate,</if>
+            <if test="isfinish != null">isfinish,</if>
+            <if test="confirmor != null">confirmor,</if>
+            <if test="years != null">years,</if>
+            <if test="content != null">content,</if>
+            <if test="nonParticipants != null">non_participants,</if>
+            <if test="unit != null">unit,</if>
+            <if test="trainingType != null">training_type,</if>
+            <if test="picUrl != null">pic_url,</if>
+            <if test="regularId != null">regular_id,</if>
+            <if test="designatedPosition != null">designated_position,</if>
+            <if test="designatedStaff != null">designated_staff,</if>
+            <if test="fileUrl != null">file_url,</if>
+            <if test="fileName != null">file_name,</if>
+            <if test="timerNeed != null">timer_need,</if>
+            <if test="examId != null">exam_id,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="id != null">#{id},</if>
+            <if test="plantCode != null">#{plantCode},</if>
+            <if test="course != null and course != ''">#{course},</if>
+            <if test="courseid != null">#{courseid},</if>
+            <if test="period != null">#{period},</if>
+            <if test="duration != null">#{duration},</if>
+            <if test="trainer != null">#{trainer},</if>
+            <if test="position != null">#{position},</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="courseStartdate != null">#{courseStartdate},</if>
+            <if test="courseEnddate != null">#{courseEnddate},</if>
+            <if test="isfinish != null">#{isfinish},</if>
+            <if test="confirmor != null">#{confirmor},</if>
+            <if test="years != null">#{years},</if>
+            <if test="content != null">#{content},</if>
+            <if test="nonParticipants != null">#{nonParticipants},</if>
+            <if test="unit != null">#{unit},</if>
+            <if test="trainingType != null">#{trainingType},</if>
+            <if test="picUrl != null">#{picUrl},</if>
+            <if test="regularId != null">#{regularId},</if>
+            <if test="designatedPosition != null">#{designatedPosition},</if>
+            <if test="designatedStaff != null">#{designatedStaff},</if>
+            <if test="fileUrl != null">#{fileUrl},</if>
+            <if test="fileName != null">#{fileName},</if>
+            <if test="timerNeed != null">#{timerNeed},</if>
+            <if test="examId != null">#{examId},</if>
+         </trim>
+    </insert>
+
+    <update id="updateTTrainingbcc" parameterType="TTrainingbcc">
+        update t_trainingbcc
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="plantCode != null">plant_code = #{plantCode},</if>
+            <if test="course != null and course != ''">course = #{course},</if>
+            <if test="courseid != null">courseid = #{courseid},</if>
+            <if test="period != null">period = #{period},</if>
+            <if test="duration != null">duration = #{duration},</if>
+            <if test="trainer != null">trainer = #{trainer},</if>
+            <if test="position != null">position = #{position},</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="courseStartdate != null">course_startdate = #{courseStartdate},</if>
+            <if test="courseEnddate != null">course_enddate = #{courseEnddate},</if>
+            <if test="isfinish != null">isfinish = #{isfinish},</if>
+            <if test="confirmor != null">confirmor = #{confirmor},</if>
+            <if test="years != null">years = #{years},</if>
+            <if test="content != null">content = #{content},</if>
+            <if test="nonParticipants != null">non_participants = #{nonParticipants},</if>
+            <if test="unit != null">unit = #{unit},</if>
+            <if test="trainingType != null">training_type = #{trainingType},</if>
+            <if test="picUrl != null">pic_url = #{picUrl},</if>
+            <if test="regularId != null">regular_id = #{regularId},</if>
+            <if test="designatedPosition != null">designated_position = #{designatedPosition},</if>
+            <if test="designatedStaff != null">designated_staff = #{designatedStaff},</if>
+            <if test="fileUrl != null">file_url = #{fileUrl},</if>
+            <if test="fileName != null">file_name = #{fileName},</if>
+            <if test="timerNeed != null">timer_need = #{timerNeed},</if>
+            <if test="examId != null">exam_id = #{examId},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <update id="deleteTTrainingbccById" parameterType="Long">
+        update t_trainingbcc set del_flag = 2 where id = #{id}
+    </update>
+
+    <update id="deleteTTrainingbccByIds" parameterType="String">
+        update t_trainingbcc set del_flag = 2 where id in
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </update>
+
+</mapper>

+ 7 - 1
master/src/main/resources/mybatis/training/elearn/TElExamMapper.xml

@@ -24,19 +24,22 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="deptId"    column="dept_id"    />
         <result property="remarks"    column="remarks"    />
         <result property="deptName" column="dept_name" />
+        <result property="examType"    column="exam_type"    />
     </resultMap>
 
     <sql id="selectTElExamVo">
-        select d.exam_id, d.title, d.content, d.open_type, d.state, d.time_limit, d.exam_start_time, d.exam_end_time, d.total_score, d.total_time, d.qualify_score, d.del_flag, d.creater_code, d.createdate, d.updater_code, d.updatedate, d.dept_id, d.remarks ,s.dept_name from t_el_exam d
+        select d.exam_id,d.exam_type, d.title, d.content, d.open_type, d.state, d.time_limit, d.exam_start_time, d.exam_end_time, d.total_score, d.total_time, d.qualify_score, d.del_flag, d.creater_code, d.createdate, d.updater_code, d.updatedate, d.dept_id, d.remarks ,s.dept_name from t_el_exam d
       left join sys_dept s on s.dept_id = d.dept_id
     </sql>
 
     <select id="selectTElExamList" parameterType="TElExam" resultMap="TElExamResult">
         <include refid="selectTElExamVo"/>
         <where>
+            <if test="examId != null "> and exam_id = #{examId}</if>
             <if test="title != null  and title != ''"> and title = #{title}</if>
             <if test="content != null  and content != ''"> and content = #{content}</if>
             <if test="openType != null "> and open_type = #{openType}</if>
+            <if test="examType != null "> and exam_type = #{examType}</if>
             <if test="state != null "> and state = #{state}</if>
             <if test="timeLimit != null "> and time_limit = #{timeLimit}</if>
             <if test="examStartTime != null "> and exam_start_time = #{examStartTime}</if>
@@ -71,6 +74,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="title != null">title,</if>
             <if test="content != null">content,</if>
             <if test="openType != null">open_type,</if>
+            <if test="examType != null">exam_type,</if>
             <if test="state != null">state,</if>
             <if test="timeLimit != null">time_limit,</if>
             <if test="examStartTime != null">exam_start_time,</if>
@@ -91,6 +95,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="title != null">#{title},</if>
             <if test="content != null">#{content},</if>
             <if test="openType != null">#{openType},</if>
+            <if test="examType != null">#{examType},</if>
             <if test="state != null">#{state},</if>
             <if test="timeLimit != null">#{timeLimit},</if>
             <if test="examStartTime != null">#{examStartTime},</if>
@@ -114,6 +119,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="title != null">title = #{title},</if>
             <if test="content != null">content = #{content},</if>
             <if test="openType != null">open_type = #{openType},</if>
+            <if test="examType != null">exam_type = #{examType},</if>
             <if test="state != null">state = #{state},</if>
             <if test="timeLimit != null">time_limit = #{timeLimit},</if>
             <if test="examStartTime != null">exam_start_time = #{examStartTime},</if>

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

@@ -0,0 +1,53 @@
+import request from '@/utils/request'
+
+// 查询人员-装置级培训关系列表
+export function listDevice(query) {
+  return request({
+    url: '/training/bccdevice/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询人员-装置级培训关系详细
+export function getDevice(id) {
+  return request({
+    url: '/training/bccdevice/' + id,
+    method: 'get'
+  })
+}
+
+// 新增人员-装置级培训关系
+export function addDevice(data) {
+  return request({
+    url: '/training/bccdevice',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改人员-装置级培训关系
+export function updateDevice(data) {
+  return request({
+    url: '/training/bccdevice',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除人员-装置级培训关系
+export function delDevice(id) {
+  return request({
+    url: '/training/bccdevice/' + id,
+    method: 'delete'
+  })
+}
+
+// 导出人员-装置级培训关系
+export function exportDevice(query) {
+  return request({
+    url: '/training/bccdevice/export',
+    method: 'get',
+    params: query
+  })
+}

+ 72 - 0
ui/src/api/training/trainingbcc.js

@@ -0,0 +1,72 @@
+import request from '@/utils/request'
+
+// 查询装置培训跟踪b列表
+export function listTrainingbcc(query) {
+  return request({
+    url: '/training/trainingbcc/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询装置培训跟踪b详细
+export function getTrainingbcc(id) {
+  return request({
+    url: '/training/trainingbcc/' + id,
+    method: 'get'
+  })
+}
+
+// 查询装置培训跟踪b详细
+export function getTrainingbccStaffIds(id) {
+  return request({
+    url: '/training/trainingbcc/staffIds/' + id,
+    method: 'get'
+  })
+}
+
+
+// 新增装置培训跟踪b
+export function addTrainingbcc(data) {
+  return request({
+    url: '/training/trainingbcc',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改装置培训跟踪b
+export function updateTrainingbcc(data) {
+  return request({
+    url: '/training/trainingbcc',
+    method: 'put',
+    data: data
+  })
+}
+
+// 修改装置培训跟踪b
+export function updateTrainingbccStaffIds(data) {
+  return request({
+    url: '/training/trainingbcc/updateStaffIds',
+    method: 'post',
+    data: data
+  })
+}
+
+
+// 删除装置培训跟踪b
+export function delTrainingbcc(id) {
+  return request({
+    url: '/training/trainingbcc/' + id,
+    method: 'delete'
+  })
+}
+
+// 导出装置培训跟踪b
+export function exportTrainingbcc(query) {
+  return request({
+    url: '/training/trainingbcc/export',
+    method: 'get',
+    params: query
+  })
+}

+ 14 - 1
ui/src/router/index.js

@@ -593,6 +593,19 @@ export const constantRoutes = [
       }
     ]
   },
+  {
+    path: '/training',
+    component: Layout,
+    hidden: true,
+    children: [
+      {
+        path: 'deviceList/:id',
+        component: (resolve) => require(['@/views/training/trainingbcc/deviceList'], resolve),
+        name: 'deviceList',
+        meta: { title: '装置培训详情' }
+      }
+    ]
+  },
   {
     path: '/training/elearn',
     component: Layout,
@@ -605,7 +618,7 @@ export const constantRoutes = [
         meta: { title: '准备考试', noCache: true },
         hidden: true
       },{
-        path: 'paper',
+        path: 'paper/:examId',
         component: () => import('@/views/training/elearn/paper/list'),
         name: 'paper',
         meta: { title: '在线考试', noCache: true },

+ 2 - 0
ui/src/views/components/PlantProgList/index.vue

@@ -117,6 +117,7 @@
       </el-table-column>
       <el-table-column :label="$t('下次修订日期')" align="center" sortable="custom" prop="nexteditdate" width="100">
         <template slot-scope="scope">
+          <span v-if="scope.row.nexteditdate == null">按需</span>
           <span style="vertical-align:middle">{{ parseTime(scope.row.nexteditdate, '{y}-{m}-{d}') }}</span>
           <svg-icon  :icon-class="changeColorPiont(scope.row.nexteditdate)"
                     style="font-size: 8px"></svg-icon>
@@ -126,6 +127,7 @@
                        v-if="this.itemNum !== '5'"/>
       <el-table-column :label="$t('回顾日期')" align="center" prop="reviewdate" width="100" v-if="this.itemNum !== '5'">
         <template slot-scope="scope">
+          <span v-if="scope.row.reviewdate == null">NA</span>
           <span>{{ parseTime(scope.row.reviewdate, '{y}-{m}-{d}') }}</span>
         </template>
       </el-table-column>

+ 2 - 2
ui/src/views/login.vue

@@ -260,8 +260,8 @@ export default {
   justify-content: center;
   align-items: center;
   height: 100%;
-  background-image: url("../assets/image/CPMS20210107.jpg");
-  //background-image: url("../assets/image/cpms-test.jpg");
+  //background-image: url("../assets/image/CPMS20210107.jpg");
+  background-image: url("../assets/image/cpms-test.jpg");
   background-size: cover;
 }
 

+ 439 - 0
ui/src/views/training/bccdevice/index.vue

@@ -0,0 +1,439 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="开始日期" prop="startDate">
+        <el-date-picker clearable size="small" style="width: 200px"
+          v-model="queryParams.startDate"
+          type="date"
+          value-format="yyyy-MM-dd"
+          placeholder="选择开始日期">
+        </el-date-picker>
+      </el-form-item>
+
+      <el-form-item label="学习时长min" prop="learnTime">
+        <el-input
+          v-model="queryParams.learnTime"
+          placeholder="请输入学习时长min"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+        >新增</el-button>
+      </el-col>
+
+	  <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading" :data="deviceList" @selection-change="handleSelectionChange" :height="clientHeight" border>
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="开始日期" align="center" prop="startDate" width="100">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.startDate, '{y}-{m}-{d}') }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="参培人" align="center" prop="name" width="100">
+      </el-table-column>
+      <el-table-column label="培训课程" align="center" prop="trainingbcc.course" width="500">
+      </el-table-column>
+      <el-table-column label="是否为补培人员" align="center" prop="supplementary" :show-overflow-tooltip="true">
+        <template v-slot="scope">
+          <span v-if="scope.row.supplementary == 0" size="small" type="success">否</span>
+          <span v-else-if="scope.row.supplementary == 1" size="small" type="info">是</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="学习状态" align="center" prop="learnState" :show-overflow-tooltip="true">
+        <template v-slot="scope">
+          <el-tag v-if="scope.row.learnState == 1" size="small" type="success">已完成</el-tag>
+          <el-tag v-else-if="scope.row.learnState == 0"  size="small" type="info">未完成</el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column label="考试状态" align="center" prop="examState" :show-overflow-tooltip="true">
+        <template v-slot="scope">
+          <el-tag v-if="scope.row.examState == 1" size="small" type="success">合格</el-tag>
+          <el-tag v-else-if="scope.row.examState == 0" size="small" type="info">未完成</el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column label="学习时长min" align="center" prop="learnTime" :show-overflow-tooltip="true"/>
+      <el-table-column label="操作" align="center" fixed="right" width="120" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-view"
+            @click="handleUpdate(scope.row)"
+          >学习</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="hanldeExam(scope.row)"
+          >考试</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 添加或修改人员-装置级培训关系对话框 -->
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="人员员工号" prop="staffId">
+          <el-input v-model="form.staffId" placeholder="请输入人员员工号" />
+        </el-form-item>
+        <el-form-item label="装置级培训ID" prop="regularId">
+          <el-input v-model="form.regularId" placeholder="请输入装置级培训ID" />
+        </el-form-item>
+        <el-form-item label="开始日期" prop="startDate">
+          <el-date-picker clearable size="small" style="width: 200px"
+            v-model="form.startDate"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="选择开始日期">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="备注" prop="remarks">
+          <el-input v-model="form.remarks" placeholder="请输入备注" />
+        </el-form-item>
+        <el-form-item label="删除状态" prop="delFlag">
+          <el-input v-model="form.delFlag" placeholder="请输入删除状态" />
+        </el-form-item>
+        <el-form-item label="创建人" prop="createrCode">
+          <el-input v-model="form.createrCode" placeholder="请输入创建人" />
+        </el-form-item>
+        <el-form-item label="创建时间" prop="createdate">
+          <el-date-picker clearable size="small" style="width: 200px"
+            v-model="form.createdate"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="选择创建时间">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="修改人" prop="updaterCode">
+          <el-input v-model="form.updaterCode" placeholder="请输入修改人" />
+        </el-form-item>
+        <el-form-item label="修改时间" prop="updatedate">
+          <el-date-picker clearable size="small" style="width: 200px"
+            v-model="form.updatedate"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="选择修改时间">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="是否为补培人员" prop="supplementary">
+          <el-input v-model="form.supplementary" placeholder="请输入是否为补培人员" />
+        </el-form-item>
+        <el-form-item label="学习状态" prop="learnState">
+          <el-input v-model="form.learnState" placeholder="请输入学习状态" />
+        </el-form-item>
+        <el-form-item label="考试状态" prop="examState">
+          <el-input v-model="form.examState" placeholder="请输入考试状态" />
+        </el-form-item>
+        <el-form-item label="考试ID" prop="examId">
+          <el-input v-model="form.examId" placeholder="请输入考试ID" />
+        </el-form-item>
+        <el-form-item label="学习时长min" prop="learnTime">
+          <el-input v-model="form.learnTime" placeholder="请输入学习时长min" />
+        </el-form-item>
+          <el-form-item label="归属部门" prop="deptId">
+              <treeselect v-model="form.deptId" :options="deptOptions" :show-count="true" placeholder="请选择归属部门" />
+          </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
+      <!-- 用户导入对话框 -->
+      <el-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body>
+          <el-upload
+                  ref="upload"
+                  :limit="1"
+                  accept=".xlsx, .xls"
+                  :headers="upload.headers"
+                  :action="upload.url + '?updateSupport=' + upload.updateSupport"
+                  :disabled="upload.isUploading"
+                  :on-progress="handleFileUploadProgress"
+                  :on-success="handleFileSuccess"
+                  :auto-upload="false"
+                  drag
+          >
+              <i class="el-icon-upload"></i>
+              <div class="el-upload__text">
+                  将文件拖到此处,或
+                  <em>点击上传</em>
+              </div>
+              <div class="el-upload__tip" slot="tip">
+                  <el-checkbox v-model="upload.updateSupport" />是否更新已经存在的用户数据
+                  <el-link type="info" style="font-size:12px" @click="importTemplate">下载模板</el-link>
+              </div>
+              <div class="el-upload__tip" style="color:red" slot="tip">提示:仅允许导入“xls”或“xlsx”格式文件!</div>
+          </el-upload>
+          <div slot="footer" class="dialog-footer">
+              <el-button type="primary" @click="submitFileForm">确 定</el-button>
+              <el-button @click="upload.open = false">取 消</el-button>
+          </div>
+      </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listDevice, getDevice, 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";
+
+export default {
+  name: "Device",
+  components: { Treeselect },
+  data() {
+    return {
+      // 遮罩层
+      loading: true,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: false,
+      // 总条数
+      total: 0,
+      // 人员-装置级培训关系表格数据
+      deviceList: [],
+      // 弹出层标题
+      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 + "/training/device/importData"
+        },
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 20,
+        staffId: null,
+        regularId: null,
+        startDate: null,
+        remarks: null,
+        createrCode: null,
+        createdate: null,
+        updaterCode: null,
+        updatedate: null,
+        supplementary: null,
+        learnState: null,
+        examState: null,
+        examId: null,
+        learnTime: null
+      },
+      // 表单参数
+      form: {},
+      // 表单校验
+      rules: {
+      }
+    };
+  },
+  watch: {
+        // 根据名称筛选部门树
+        deptName(val) {
+            this.$refs.tree.filter(val);
+        }
+   },
+  created() {
+      //设置表格高度对应屏幕高度
+      this.$nextTick(() => {
+          this.clientHeight = document.body.clientHeight -250
+      })
+    this.getList();
+    this.getTreeselect();
+  },
+  methods: {
+    /** 查询人员-装置级培训关系列表 */
+    getList() {
+      this.loading = true;
+      listDevice(this.queryParams).then(response => {
+        this.deviceList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+     /** 查询部门下拉树结构 */
+     getTreeselect() {
+          treeselect().then(response => {
+              this.deptOptions = response.data;
+          });
+     },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        id: null,
+        staffId: null,
+        regularId: null,
+        startDate: null,
+        remarks: null,
+        delFlag: null,
+        createrCode: null,
+        createdate: null,
+        updaterCode: null,
+        updatedate: null,
+        supplementary: null,
+        learnState: null,
+        examState: null,
+        examId: null,
+        learnTime: 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
+    },
+    hanldeExam(row){
+      this.$router.push({ name: 'paper', params: { examId: row.examId }})
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "添加人员-装置级培训关系";
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      const id = row.id || this.ids
+      getDevice(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) {
+            updateDevice(this.form).then(response => {
+              this.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addDevice(this.form).then(response => {
+              this.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$confirm('是否确认删除?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return delDevice(ids);
+        }).then(() => {
+          this.getList();
+          this.msgSuccess("删除成功");
+        })
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      const queryParams = this.queryParams;
+      this.$confirm('是否确认导出所有人员-装置级培训关系数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return exportDevice(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>

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

@@ -161,6 +161,7 @@ export default {
         },
       // 查询参数
       queryParams: {
+        examId: null,
         pageNum: 1,
         pageSize: 20,
         title: null,
@@ -235,6 +236,7 @@ export default {
 
   },
   created() {
+    this.queryParams.examId = this.$route.params.examId
       //设置表格高度对应屏幕高度
       this.$nextTick(() => {
           this.clientHeight = document.body.clientHeight -250

+ 437 - 0
ui/src/views/training/trainingbcc/deviceList.vue

@@ -0,0 +1,437 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="开始日期" prop="startDate">
+        <el-date-picker clearable size="small" style="width: 200px"
+          v-model="queryParams.startDate"
+          type="date"
+          value-format="yyyy-MM-dd"
+          placeholder="选择开始日期">
+        </el-date-picker>
+      </el-form-item>
+
+      <el-form-item label="学习时长min" prop="learnTime">
+        <el-input
+          v-model="queryParams.learnTime"
+          placeholder="请输入学习时长min"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+        >新增</el-button>
+      </el-col>
+
+	  <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading" :data="deviceList" @selection-change="handleSelectionChange" :height="clientHeight" border>
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="开始日期" align="center" prop="startDate" width="100">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.startDate, '{y}-{m}-{d}') }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="培训课程" align="center" prop="trainingbcc.course" width="500">
+      </el-table-column>
+      <el-table-column label="参培人" align="center" prop="name" width="100">
+      </el-table-column>
+      <el-table-column label="是否为补培人员" align="center" prop="supplementary" :show-overflow-tooltip="true">
+        <template v-slot="scope">
+          <span v-if="scope.row.supplementary == 0" size="small" type="success">否</span>
+          <span v-else-if="scope.row.supplementary == 1" size="small" type="info">是</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="学习状态" align="center" prop="learnState" :show-overflow-tooltip="true">
+        <template v-slot="scope">
+          <el-tag v-if="scope.row.learnState == 1" size="small" type="success">已完成</el-tag>
+          <el-tag v-else-if="scope.row.learnState == 0"  size="small" type="info">未完成</el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column label="学习时长min" align="center" prop="learnTime" :show-overflow-tooltip="true"/>
+
+      <el-table-column label="考试状态" align="center" prop="examState" :show-overflow-tooltip="true">
+        <template v-slot="scope">
+          <el-tag v-if="scope.row.examState == 1" size="small" type="success">合格</el-tag>
+          <el-tag v-else-if="scope.row.examState == 0" size="small" type="info">未完成</el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column label="考试次数" align="center" prop="examNum" :show-overflow-tooltip="true"/>
+
+      <el-table-column label="操作" align="center" fixed="right" width="120" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="hanldeExamPaper(scope.row)"
+          >考试成绩</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 添加或修改人员-装置级培训关系对话框 -->
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="人员员工号" prop="staffId">
+          <el-input v-model="form.staffId" placeholder="请输入人员员工号" />
+        </el-form-item>
+        <el-form-item label="装置级培训ID" prop="regularId">
+          <el-input v-model="form.regularId" placeholder="请输入装置级培训ID" />
+        </el-form-item>
+        <el-form-item label="开始日期" prop="startDate">
+          <el-date-picker clearable size="small" style="width: 200px"
+            v-model="form.startDate"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="选择开始日期">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="备注" prop="remarks">
+          <el-input v-model="form.remarks" placeholder="请输入备注" />
+        </el-form-item>
+        <el-form-item label="删除状态" prop="delFlag">
+          <el-input v-model="form.delFlag" placeholder="请输入删除状态" />
+        </el-form-item>
+        <el-form-item label="创建人" prop="createrCode">
+          <el-input v-model="form.createrCode" placeholder="请输入创建人" />
+        </el-form-item>
+        <el-form-item label="创建时间" prop="createdate">
+          <el-date-picker clearable size="small" style="width: 200px"
+            v-model="form.createdate"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="选择创建时间">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="修改人" prop="updaterCode">
+          <el-input v-model="form.updaterCode" placeholder="请输入修改人" />
+        </el-form-item>
+        <el-form-item label="修改时间" prop="updatedate">
+          <el-date-picker clearable size="small" style="width: 200px"
+            v-model="form.updatedate"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="选择修改时间">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="是否为补培人员" prop="supplementary">
+          <el-input v-model="form.supplementary" placeholder="请输入是否为补培人员" />
+        </el-form-item>
+        <el-form-item label="学习状态" prop="learnState">
+          <el-input v-model="form.learnState" placeholder="请输入学习状态" />
+        </el-form-item>
+        <el-form-item label="考试状态" prop="examState">
+          <el-input v-model="form.examState" placeholder="请输入考试状态" />
+        </el-form-item>
+        <el-form-item label="考试ID" prop="examId">
+          <el-input v-model="form.examId" placeholder="请输入考试ID" />
+        </el-form-item>
+        <el-form-item label="学习时长min" prop="learnTime">
+          <el-input v-model="form.learnTime" placeholder="请输入学习时长min" />
+        </el-form-item>
+          <el-form-item label="归属部门" prop="deptId">
+              <treeselect v-model="form.deptId" :options="deptOptions" :show-count="true" placeholder="请选择归属部门" />
+          </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
+      <!-- 用户导入对话框 -->
+      <el-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body>
+          <el-upload
+                  ref="upload"
+                  :limit="1"
+                  accept=".xlsx, .xls"
+                  :headers="upload.headers"
+                  :action="upload.url + '?updateSupport=' + upload.updateSupport"
+                  :disabled="upload.isUploading"
+                  :on-progress="handleFileUploadProgress"
+                  :on-success="handleFileSuccess"
+                  :auto-upload="false"
+                  drag
+          >
+              <i class="el-icon-upload"></i>
+              <div class="el-upload__text">
+                  将文件拖到此处,或
+                  <em>点击上传</em>
+              </div>
+              <div class="el-upload__tip" slot="tip">
+                  <el-checkbox v-model="upload.updateSupport" />是否更新已经存在的用户数据
+                  <el-link type="info" style="font-size:12px" @click="importTemplate">下载模板</el-link>
+              </div>
+              <div class="el-upload__tip" style="color:red" slot="tip">提示:仅允许导入“xls”或“xlsx”格式文件!</div>
+          </el-upload>
+          <div slot="footer" class="dialog-footer">
+              <el-button type="primary" @click="submitFileForm">确 定</el-button>
+              <el-button @click="upload.open = false">取 消</el-button>
+          </div>
+      </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listDevice, getDevice, 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";
+
+export default {
+  name: "Device",
+  components: { Treeselect },
+  data() {
+    return {
+      // 遮罩层
+      loading: true,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: false,
+      // 总条数
+      total: 0,
+      // 人员-装置级培训关系表格数据
+      deviceList: [],
+      // 弹出层标题
+      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 + "/training/device/importData"
+        },
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 20,
+        staffId: null,
+        regularId: null,
+        startDate: null,
+        remarks: null,
+        createrCode: null,
+        createdate: null,
+        updaterCode: null,
+        updatedate: null,
+        supplementary: null,
+        learnState: null,
+        examState: null,
+        examId: null,
+        learnTime: null
+      },
+      // 表单参数
+      form: {},
+      // 表单校验
+      rules: {
+      }
+    };
+  },
+  watch: {
+        // 根据名称筛选部门树
+        deptName(val) {
+            this.$refs.tree.filter(val);
+        }
+   },
+  created() {
+    this.queryParams.regularId = this.$route.params.id
+      //设置表格高度对应屏幕高度
+      this.$nextTick(() => {
+          this.clientHeight = document.body.clientHeight -250
+      })
+    this.getList();
+    this.getTreeselect();
+  },
+  methods: {
+    /** 查询人员-装置级培训关系列表 */
+    getList() {
+      this.loading = true;
+      listDevice(this.queryParams).then(response => {
+        this.deviceList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+     /** 查询部门下拉树结构 */
+     getTreeselect() {
+          treeselect().then(response => {
+              this.deptOptions = response.data;
+          });
+     },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        id: null,
+        staffId: null,
+        regularId: null,
+        startDate: null,
+        remarks: null,
+        delFlag: null,
+        createrCode: null,
+        createdate: null,
+        updaterCode: null,
+        updatedate: null,
+        supplementary: null,
+        learnState: null,
+        examState: null,
+        examId: null,
+        learnTime: 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
+    },
+    hanldeExam(row){
+      this.$router.push({ name: 'paper', params: { examId: row.examId }})
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "添加人员-装置级培训关系";
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      const id = row.id || this.ids
+      getDevice(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) {
+            updateDevice(this.form).then(response => {
+              this.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addDevice(this.form).then(response => {
+              this.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$confirm('是否确认删除?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return delDevice(ids);
+        }).then(() => {
+          this.getList();
+          this.msgSuccess("删除成功");
+        })
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      const queryParams = this.queryParams;
+      this.$confirm('是否确认导出所有人员-装置级培训关系数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return exportDevice(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>

+ 1280 - 0
ui/src/views/training/trainingbcc/index.vue

@@ -0,0 +1,1280 @@
+<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="years">
+        <el-date-picker clearable size="small" style="width: 200px"
+                        v-model="queryParams.years"
+                        type="year"
+                        value-format="yyyy"
+                        :placeholder="$t('请选择') + $t('年份')"
+                        @change="handleQuery" >
+        </el-date-picker>
+      </el-form-item>
+      <el-form-item :label="$t('培训课程')" prop="course">
+        <el-input
+          v-model="queryParams.course"
+          :placeholder="$t('请输入') + $t('培训课程')"
+          clearable
+          size="small"
+          @input="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item :label="$t('培训类型')" prop="trainingType" label-width="50">
+        <el-select v-model="queryParams.trainingType" @change="handleQuery"    :placeholder="$t('请选择') + $t('培训类型')" clearable size="small">
+          <el-option
+            v-for="dict in trainingTypeOptions"
+            :key="dict.dictValue"
+            :label="dict.dictLabel"
+            :value="dict.dictValue"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item :label="$t('是否完成')" prop="isfinish" label-width="50">
+        <el-select v-model="queryParams.isfinish" @change="handleQuery"    :placeholder="$t('请选择') + $t('是否完成')" clearable size="small">
+          <el-option
+            v-for="dict in isfinishOptions"
+            :key="dict.dictValue"
+            :label="dict.dictLabel"
+            :value="dict.dictValue"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item :label="$t('未参培情况')" prop="isNon" label-width="50">
+        <el-select v-model="queryParams.isNon" @change="handleQuery"    :placeholder="$t('请选择') + $t('是否未参培')" clearable size="small">
+          <el-option
+            key="0"
+            label="全部"
+            value="0"
+          />
+          <el-option
+            key="1"
+            label="未参培"
+            value="1"
+          />
+          <el-option
+            key="2"
+            label="已完成"
+            value="2"
+          />
+          <el-option
+            key="3"
+            label="未完成"
+            value="3"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item :label="$t('培训开始日期')" label-width="60">
+        <el-date-picker
+          v-model="chooseDate"
+          @change="handleQuery"
+          type="daterange"
+          align="right"
+          unlink-panels
+          :range-separator="$t('至')"
+          :start-placeholder="$t('开始日期')"
+          :end-placeholder="$t('结束日期')"
+          value-format="yyyy-MM-dd"
+          :picker-options="pickerOptions">
+        </el-date-picker>
+      </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:training: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:training: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:training:remove']"
+        >{{ $t('删除') }}</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          icon="el-icon-download"
+          size="mini"
+          @click="handleExport"
+          v-hasPermi="['training:training:export']"
+        >{{ $t('导出') }}</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-row>
+      <el-col :span="24">
+        <el-button type="primary" plain @click="selectCourse('10')">定期类</el-button>
+        <el-button type="primary" plain @click="selectCourse('12')">
+          EHS类培训、学习及信息通告
+        </el-button>
+        <el-button type="primary" plain @click="selectCourse('14')">
+          程序和操作手册培训更新培训
+        </el-button>
+        <el-button type="primary" plain @click="selectCourse('16')">事件报告和调查</el-button>
+        <el-button type="primary" plain @click="selectCourse('20')">MOC培训</el-button>
+      </el-col>
+    </el-row>
+    <el-table v-loading="loading" :data="trainingList" @selection-change="handleSelectionChange" :cell-style="tableCellStyle" :height="clientHeight" border>
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column :label="$t('年份')" align="center" prop="years" :show-overflow-tooltip="true"/>
+      <el-table-column :label="$t('培训课程')" align="center" prop="course" width="250" :show-overflow-tooltip="true"/>
+      <el-table-column :label="$t('培训类型')" align="center" prop="trainingType" width="120" :formatter="trainingTypeFormat"/>
+      <el-table-column :label="$t('培训内容')" align="center" prop="content" width="250" :show-overflow-tooltip="true" />
+      <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>
+          <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="$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">
+          <span>{{ parseTime(scope.row.courseStartdate, '{y}-{m}-{d}') }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column :label="$t('培训结束日期')" align="center" prop="courseEnddate" width="100">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.courseEnddate, '{y}-{m}-{d}') }}</span>
+        </template>
+      </el-table-column>
+<!--      <el-table-column :label="$t('未参培人员名单')" align="center" prop="nonParticipants" width="200" :show-overflow-tooltip="true" />-->
+      <el-table-column :label="$t('备注')" align="center" prop="remarks" :show-overflow-tooltip="true"/>
+      <el-table-column :label="$t('操作')" align="center" fixed="right" width="270" 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:training:edit']"
+          >{{ $t('修改') }}</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleStaffmgr(scope.row)"
+            v-hasPermi="['training:training:edit']"
+          >人员名单</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleDetail(scope.row)"
+            v-hasPermi="['training:training:edit']"
+          >培训详情</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+
+    <!-- 添加或修改培训计划对话框 -->
+    <el-dialog  :close-on-click-modal="false" v-dialogDrag :title="title" :visible.sync="open" width="80%" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="110px">
+        <el-row>
+          <el-col :span="12">
+            <el-form-item :label="$t('培训课程')" prop="course">
+              <el-input v-model="form.course" :placeholder="$t('请输入') + $t('培训课程')" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item :label="$t('培训类型')" prop="trainingType">
+              <el-select v-model="form.trainingType" :placeholder="$t('请选择') + $t('培训类型')">
+                <el-option
+                  v-for="dict in trainingTypeOptions"
+                  :key="dict.dictValue"
+                  :label="dict.dictLabel"
+                  :value="dict.dictValue"
+                ></el-option>
+              </el-select>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="12">
+            <el-form-item :label="$t('培训内容')" prop="content">
+              <el-input v-model="form.content" :placeholder="$t('请输入') + $t('培训内容')" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item :label="$t('课程代码')" prop="courseid">
+              <el-input v-model="form.courseid" :placeholder="$t('请输入') + $t('课程代码')" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="12">
+            <el-form-item :label="$t('培训周期')" prop="period">
+              <el-input v-model="form.period" :placeholder="$t('请输入') + $t('培训周期')" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item :label="$t('课时')" prop="duration">
+              <el-input v-model="form.duration" :placeholder="$t('请输入') + $t('课时')" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="12">
+            <el-form-item :label="$t('培训人')" prop="trainer">
+              <el-select v-model="form.trainer" 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-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">
+                <el-option
+                  v-for="dict in positionOptions"
+                  :key="dict.dictValue"
+                  :label="dict.dictLabel"
+                  :value="dict.dictValue"
+                ></el-option>
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <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">
+            <el-form-item :label="$t('年份')" prop="years">
+              <el-date-picker clearable size="small" style="width: 200px"
+                              v-model="form.years"
+                              type="years"
+                              value-format="yyyy"
+                              @change="handleStaff"
+                              :placeholder="$t('请选择') + $t('年份')">
+              </el-date-picker>
+            </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>
+          <el-col :span="12">
+            <el-form-item :label="$t('培训开始日期')" prop="courseStartdate">
+              <el-date-picker clearable size="small" style="width: 200px"
+                              v-model="form.courseStartdate"
+                              type="date"
+                              value-format="yyyy-MM-dd"
+                              :placeholder="$t('请选择') + $t('培训开始日期')">
+              </el-date-picker>
+            </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>
+          <el-col :span="12">
+            <el-form-item :label="$t('培训结束日期')" prop="courseEnddate">
+              <el-date-picker clearable size="small" style="width: 200px"
+                              v-model="form.courseEnddate"
+                              type="date"
+                              value-format="yyyy-MM-dd"
+                              :placeholder="$t('请选择') + $t('培训结束日期')">
+              </el-date-picker>
+            </el-form-item >
+          </el-col>
+          <el-col :span="12">
+            <el-form-item :label="$t('是否完成')" prop="isfinish">
+              <el-select v-model="form.isfinish" :placeholder="$t('请选择') + $t('是否完成')">
+                <el-option
+                  v-for="dict in isfinishOptions"
+                  :key="dict.dictValue"
+                  :label="dict.dictLabel"
+                  :value="parseInt(dict.dictValue)"
+                ></el-option>
+              </el-select>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="12">
+            <el-form-item label="培训考试" prop="examId">
+              <el-select v-model="form.examId" filterable  :placeholder="$t('请选择') + $t('培训考试')">
+                <el-option
+                  v-for="dict in examOptions"
+                  :key="dict.examId"
+                  :label="dict.title"
+                  :value="dict.examId">
+                </el-option>
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item :label="$t('备注')" prop="remarks">
+              <el-input v-model="form.remarks" :placeholder="$t('请输入') + $t('备注')" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+      </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>
+
+    <!-- 添加参与公司级培训人员名单对话框 -->
+    <el-dialog  :close-on-click-modal="false" v-dialogDrag title="培训人员名单" :visible.sync="personOpen" width="1500px" append-to-body>
+      <el-form ref="personForm" :model="personForm"  label-width="80px">
+
+        <el-form-item :label="$t('课程名称')" prop="item">
+          <el-input v-model="personForm.course" disabled />
+        </el-form-item>
+        <el-form-item :label="$t('实际岗位')">
+          <el-checkbox-group v-model="checkboxPost" size="medium" @change="postChange">
+            <el-checkbox-button v-for="post in positionOptions" :label="post.dictValue" :key="post.dictValue">{{post.dictLabel}}</el-checkbox-button>
+          </el-checkbox-group>
+        </el-form-item>
+      </el-form>
+      <div class="staff_checked">
+        <el-transfer v-model="checked" :data="selectPersonOptions" @change="staffChange" :left-default-checked="leftList" filterable
+                     :titles="['无需参培人员', '需要参培人员']"
+        >
+          <span slot-scope="{ option }">{{ option.label }}
+            <span style="float: right; color: #8492a6; font-size: 12px; padding-left: 10px;padding-right: 15px;">{{ option.staffid }}</span>
+            <span style="float: right; color: #8492a6; font-size: 12px; padding-left: 10px;">{{ option.actualpost }}</span>
+          </span>
+        </el-transfer>
+      </div>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitParticipants">{{ $t('确 定') }}</el-button>
+        <el-button @click="cancelParticipants">{{ $t('取 消') }}</el-button>
+      </div>
+    </el-dialog>
+
+  </div>
+</template>
+
+<script>
+import { listTrainingbcc,getTrainingbccStaffIds,updateTrainingbccStaffIds, getTrainingbcc, delTrainingbcc, addTrainingbcc, updateTrainingbcc, exportTrainingbcc } from "@/api/training/trainingbcc";
+import nonAdd from './trainingNon'
+import newAdd from './trainingNew'
+import {listStaffmgrAll, listAllStaffmgr, listStaffmgr, selectTimeStaffmgr} 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";
+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";
+
+
+export default {
+  name: "Training",
+  components: { Treeselect, nonAdd, newAdd},
+  data() {
+    return {
+      // 遮罩层
+      loading: true,
+      positionVisible: false,
+      showFlag: false,
+      //确认按钮是否可点
+      submitDisabled: false,
+      //左侧选框默认选择
+      leftList: [],
+      // 选中数组
+      ids: [],
+      //人员筛选按钮选择数据
+      checkboxPost: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: false,
+      // 总条数
+      total: 0,
+      // 培训计划表格数据
+      trainingList: [],
+      positionIds: [],
+      trainers: [],
+      units: [],
+      nonParticipants: [],
+      // 弹出层标题
+      title: "",
+      // 部门树选项
+      deptOptions: undefined,
+      clientHeight:300,
+      // 是否显示弹出层
+      open: false,
+      personOpen: false,
+      // 装置名称字典
+      plantCodeOptions: [],
+      // 部门字典
+      unitOptions: [],
+      examOptions: [],
+      // 培训岗位字典
+      positionOptions: [],
+      //选择人员数据
+      checked: [],
+      trainingTypeOptions: [],
+      // 是否完成字典
+      isfinishOptions: [],
+      // 指定岗位字典
+      designatedPositionOptions: [],
+      //指定人员岗位多选
+      designatedPositions: [],
+      //指定人员id多选
+      designatedStaffs: [],
+      selectPersonOptions: [],
+      //是否存在岗位多选
+      haveDesignated: '',
+      //人员表联查
+      stffmgrOptions: undefined,
+      //人员表联查-包含离职
+      stffmgrAllOptions: undefined,
+      //指定人员选项
+      designatedStaffsOptions: [],
+      // 用户导入参数
+      upload: {
+        downloadAction: process.env.VUE_APP_BASE_API + '/common/template',
+        //下载模板类型
+        type: "training",
+        // 是否显示弹出层(用户导入)
+        open: false,
+        // 弹出层标题(用户导入)
+        title: "",
+        // 是否禁用上传
+        isUploading: false,
+        // 是否更新已经存在的用户数据
+        updateSupport: 0,
+        // 设置上传的请求头部
+        headers: { Authorization: "Bearer " + getToken() },
+        // 上传的地址
+        url: process.env.VUE_APP_BASE_API + "/training/training/importData"
+      },
+      //未参会人员弹窗是否打开
+      nonVisible: false,
+      //新员工弹窗是否打开
+      newVisible: false,
+      // 报告附件参数
+      doc: {
+        file: "",
+        // 是否显示弹出层(报告附件)
+        open: false,
+        // 弹出层标题(报告附件)
+        title: "",
+        // 是否禁用上传
+        isUploading: false,
+        // 是否更新已经存在的用户数据
+        updateSupport: 0,
+        // 报告附件上传位置编号
+        ids: 0,
+        // 设置上传的请求头部
+        headers: { Authorization: "Bearer " + getToken() },
+        // 上传的地址
+        url: process.env.VUE_APP_BASE_API + "/common/commonfile/uploadFile",
+        commonfileList: null,
+        queryParams: {
+          pId: null,
+          pType: 'training'
+        },
+        pType: 'training',
+        pId: null
+      },
+      pdf : {
+        title: '',
+        pdfUrl: '',
+        numPages: null,
+        open: false,
+        pageNum: 1,
+        pageTotalNum: 1,
+        loadedRatio: 0,
+      },
+      pic: {
+        imageUrl: '',
+        fileList: [],
+        // 设置上传的请求头部
+        headers: { Authorization: "Bearer " + getToken() },
+        // 上传的地址
+        url: process.env.VUE_APP_BASE_API + "/training/training/uploadFile",
+      },
+      photoList: [],
+      dialogImageUrl: '',
+      dialogVisible: false,
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 20,
+        course: null,
+        position: [],
+        years: this.getNowTime(),
+        isfinish: null,
+        startDate: null,
+        endDate: null,
+        trainingType: null,
+        isNon: null,
+      },
+      trainingId: null,
+      //地址
+      downloadAction: process.env.VUE_APP_BASE_API + '/training/training/trainingReport',
+      //人员表查询参数
+      staffmgrQueryParams: {},
+      searchStaffmgr: "",
+      //日期快速选择
+      pickerOptions: {
+        shortcuts: [{
+          text: this.$t('最近一周'),
+          onClick(picker) {
+            const end = new Date();
+            const start = new Date();
+            start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
+            picker.$emit('pick', [start, end]);
+          }
+        }, {
+          text: this.$t('最近一个月'),
+          onClick(picker) {
+            const end = new Date();
+            const start = new Date();
+            start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
+            picker.$emit('pick', [start, end]);
+          }
+        }, {
+          text: this.$t('最近三个月'),
+          onClick(picker) {
+            const end = new Date();
+            const start = new Date();
+            start.setTime(start.getTime() - 3600 * 1000 * 24 * 90);
+            picker.$emit('pick', [start, end]);
+          }
+        }]
+      },
+      //日期选择器
+      chooseDate: [],
+      // 表单参数
+      form: {},
+      personForm: {},
+      // 表单校验
+      rules: {
+        course: [
+          { required: true, message: this.$t('培训课程') + this.$t('不能为空'), trigger: "blur" }
+        ],
+        trainingType: [
+          { required: true, message: this.$t('培训类型') + this.$t('不能为空'), trigger: "blur" }
+        ],
+        trainer: [
+          { required: true, message: this.$t('培训人') + this.$t('不能为空'), trigger: "blur" }
+        ],
+        unit: [
+          { required: true, message: this.$t('部门') + this.$t('不能为空'), trigger: "blur" }
+        ],
+        position: [
+          { required: true, message: this.$t('培训岗位') + this.$t('不能为空'), trigger: "blur" }
+        ],
+        years: [
+          { required: true, message: this.$t('年份') + this.$t('不能为空'), trigger: "blur" }
+        ],
+        courseStartdate: [
+          { required: true, message: this.$t('培训开始日期') + this.$t('不能为空'), trigger: "blur" }
+        ],
+        isfinish: [
+          { 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() {
+    const queryName = this.$route.query && this.$route.query.status;
+    if (queryName == '未参培'){
+      this.queryParams.isNon = "1"
+    }
+    if (queryName == '已完成'){
+      this.queryParams.isNon = "2"
+    }
+    if (queryName == '未完成'){
+      this.queryParams.isNon = "3"
+    }
+
+    this.getStaffmar();
+    this.getStaffmarAll();
+    listExam({ pageNum: 1, pageSize: 1000,  examType: 2 }).then(response => {
+      this.examOptions = response.rows;
+    });
+
+    //设置表格高度对应屏幕高度
+    this.$nextTick(() => {
+      this.clientHeight = (document.body.clientHeight - 80) * 0.8
+    })
+    this.getTreeselect();
+    this.getDicts("PLANT_DIVIDE").then(response => {
+      this.plantCodeOptions = response.data;
+    });
+    this.getDicts("ACTUALPOST").then(response => {
+      this.positionOptions = response.data;
+      this.designatedPositionOptions = response.data;
+      const allData = response.data
+      const data = [];
+      for (let i = 0; i < allData.length; i++) {
+        data.push({
+          key: allData[i].dictValue,
+          label: allData[i].dictLabel,
+        });
+      }
+      this.positionOpt = response.data;
+    });
+    this.getDicts("YES_NO_EN").then(response => {
+      this.isfinishOptions = response.data;
+    });
+    this.getDicts("STAFF_UNIT").then(response => {
+      this.unitOptions = response.data;
+    });
+    this.getDicts("TRAINING_TYPE_BCC").then(response => {
+      this.trainingTypeOptions = response.data;
+    });
+  },
+  methods: {
+    /** 查询培训计划列表 */
+    getList() {
+      let _this = this
+      this.loading = true;
+      listTrainingbcc(this.queryParams).then(response => {
+        this.trainingList = response.rows;
+        this.trainingList.forEach(function (value,key,arr) {
+          var positionid = null;
+          var positionName = null;
+          let unitid = null;
+          let unitName = null;
+          if (value.position != null) {
+            positionid = value.position.split(',');
+            positionid.forEach(function (value, key, arr) {
+              if (key != 0) {
+                positionName = positionName + "," + _this.selectDictLabel(_this.positionOptions, value);
+              }else if (key == 0) {
+                positionName = _this.selectDictLabel(_this.positionOptions, value);
+              }
+            })
+          }
+
+          if (value.unit != null) {
+            unitid = value.unit.split(',');
+            unitid.forEach(function (value, key, arr) {
+              if (key != 0) {
+                unitName = unitName + "," + _this.selectDictLabel(_this.unitOptions, value);
+              }else if (key == 0) {
+                unitName = _this.selectDictLabel(_this.unitOptions, value);
+              }
+            })
+          }
+          _this.trainingList[key].positionid = value.position;
+          _this.trainingList[key].position = positionName;
+          _this.trainingList[key].unitid = value.unit;
+          _this.trainingList[key].unit = unitName;
+
+          var parentName = null;
+          if (value.trainer != null) {
+            let staffId = value.trainer.split(",");
+            staffId.forEach(function (id, index) {
+              _this.stffmgrAllOptions.forEach(function (item) {
+                if (item.staffid === id) {
+                  if (index === 0) {
+                    parentName = item.name
+                  }else {
+                    parentName = parentName + "," + item.name
+                  }
+                }
+              });
+            });
+          }
+          _this.trainingList[key].trainer = parentName;
+        })
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    /** 获取当前年份 */
+    getNowTime() {
+      var now = new Date();
+      var year = now.getFullYear(); //得到年份
+      var defaultDate = `${year}`;
+      defaultDate = `${year}`
+      return defaultDate;
+    },
+    closeChildDialog () {
+      this.showFlag = false
+      this.getList();
+    },
+    /** 查询部门下拉树结构 */
+    getTreeselect() {
+      treeselect().then(response => {
+        this.deptOptions = response.data;
+      });
+    },
+    // 装置名称字典翻译
+    plantCodeFormat(row, column) {
+      return this.selectDictLabel(this.plantCodeOptions, row.plantCode);
+    },
+    // 部门字典翻译
+    unitFormat(row, column) {
+      return this.selectDictLabel(this.unitOptions, row.unit);
+    },
+    // 培训类型翻译
+    trainingTypeFormat(row, column) {
+      return this.selectDictLabel(this.trainingTypeOptions, row.trainingType);
+    },
+    // 培训岗位字典翻译
+    positionFormat(row, column) {
+      return this.selectDictLabel(this.positionOptions, row.position);
+    },
+    // 是否完成字典翻译
+    isfinishFormat(row, column) {
+      return this.selectDictLabel(this.isfinishOptions, row.isfinish);
+    },
+    //获取人员表
+    getStaffmar(year) {
+      this.staffmgrQueryParams.leftYear = year
+      listAllStaffmgr(this.staffmgrQueryParams).then(response => {
+        this.stffmgrOptions = response.rows;
+        //
+        const allData = response.rows
+        const data = [];
+        for (let i = 0; i < allData.length; i++) {
+          data.push({
+            key: allData[i].staffid,
+            label: allData[i].name,
+            staffid: allData[i].staffid,
+            actualpost: this.selectDictLabel(this.positionOptions, allData[i].actualpost)
+          });
+        }
+        this.selectPersonOptions = data;
+
+      });
+    },
+    //年份选择change事件
+    handleStaff(val){
+      this.getStaffmar(val)
+    },
+    //获取人员表--包含离职
+    getStaffmarAll() {
+      listStaffmgrAll(this.staffmgrQueryParams).then(response => {
+        this.stffmgrAllOptions = response.rows;
+        this.getList();
+      });
+    },
+    //遍历人员表
+    forEachStaffmar(id) {
+      let stffmgrName = "";
+      this.stffmgrOptions.forEach(function (item) {
+        if (item.staffid === id) {
+          stffmgrName = item.name
+        }
+      });
+      return stffmgrName
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        id: null,
+        plantCode: null,
+        course: null,
+        courseid: null,
+        period: null,
+        duration: null,
+        trainer: null,
+        positionId: [],
+        position: null,
+        content: null,
+        unit : null,
+        years: null,
+        courseStartdate: null,
+        courseEnddate: null,
+        isfinish: null,
+        delFlag: null,
+        createrCode: null,
+        createdate: null,
+        updaterCode: null,
+        updatedate: null,
+        remarks: null,
+        deptId: null,
+        startDate: null,
+        endDate: null,
+        nonParticipants: null,
+        trainingType: null,
+        picUrl: null,
+        mustTraining: null,
+        haveTraining: null
+      };
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.queryParams.startDate = this.chooseDate[0];
+      this.queryParams.endDate = this.chooseDate[1];
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.chooseDate = "";
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    //根据分数显示颜色提示
+    tableCellStyle({ row, column, rowIndex, columnIndex }) {
+      if (columnIndex == 6 && row.isfinish == 0){
+        return "color: rgba(255, 26, 26, 0.98) "
+      }
+    },
+    //培训岗位变动
+    changePosition() {
+      let _this = this
+      this.getDicts("ACTUALPOST").then(response => {
+        this.designatedPositionOptions = response.data;
+        this.form.position.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;
+        listStaffmgr(this.staffmgrQueryParams).then(response => {
+          this.designatedStaffsOptions = response.rows;
+        });
+
+        let _this = this
+        this.getDicts("ACTUALPOST").then(response => {
+          this.positionOptions = response.data;
+          this.designatedPositions.forEach(function (value, key, arr) {
+            _this.positionOptions.forEach(function (positionValue, positionkey, arr) {
+              if (positionValue.dictValue === value) {
+                _this.positionOptions.splice(positionkey ,1)
+              }
+            })
+          })
+        });
+      }else {
+        this.designatedStaffs = [];
+      }
+    },
+    //指定人员按钮变动
+    changeHave() {
+      if (this.haveDesignated === false) {
+        this.designatedPositions = []
+        this.designatedStaffs = []
+      }
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.submitDisabled = false;
+      this.haveDesignated = false;
+      this.designatedPositions = [];
+      this.getDicts("ACTUALPOST").then(response => {
+        this.positionOptions = response.data;
+      });
+      this.getDicts("ACTUALPOST").then(response => {
+        this.designatedPositionOptions = response.data;
+      });
+      this.form.trainingType = this.queryParams.trainingType
+      this.title = this.$t('新增') + this.$t('空格') + this.$t('培训计划');
+      this.getStaffmar()
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      let _this = this
+      this.submitDisabled = false;
+      const id = row.id || this.ids
+      getTrainingbcc(id).then(response => {
+        this.form = response.data;
+        this.getStaffmar(response.data.years)
+        if (this.form.position != null) {
+          this.form.position = this.form.position.split(',');
+          this.getDicts("ACTUALPOST").then(response => {
+            this.designatedPositionOptions = response.data;
+            this.form.position.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.form.position = [];
+        }
+        if (this.form.designatedPosition != null) {
+          this.designatedPositions = this.form.designatedPosition.split(',');
+          this.getDicts("ACTUALPOST").then(response => {
+            this.positionOptions = response.data;
+            this.designatedPositions.forEach(function (value, key, arr) {
+              _this.positionOptions.forEach(function (positionValue, positionkey, arr) {
+                if (positionValue.dictValue === value) {
+                  _this.positionOptions.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.$nextTick(() => {
+            listAllStaffmgr(this.staffmgrQueryParams).then(response => {
+              this.designatedStaffsOptions = response.rows;
+            });
+          })
+        }else {
+          this.haveDesignated = false;
+          this.designatedPositions = [];
+          this.getDicts("ACTUALPOST").then(response => {
+            this.positionOptions = response.data;
+          })
+        }
+        if (this.form.designatedStaff != null) {
+          this.designatedStaffs = this.form.designatedStaff.split(',');
+        }else {
+          this.designatedStaffs = [];
+        }
+        if (this.form.unit != null) {
+          this.form.unit = this.form.unit.split(',');
+          /*this.changeUnit(this.form.unit)*/
+        }else {
+          this.form.unit = [];
+        }
+        if (this.form.nonParticipants != null) {
+          this.nonParticipants = this.form.nonParticipants.split(",");
+        }
+        if (this.form.picUrl!= null){
+          this.photoList =[]
+          let fileList = this.form.picUrl.split(",")
+          for (let i = 0; i < fileList.length; i++) {
+            let item = {url: process.env.VUE_APP_BASE_API +fileList[i],response: {msg: fileList[i]} }
+            this.photoList.push(item)
+          }
+        }
+        if (this.form.trainer != null) {
+          this.form.trainer = this.form.trainer.split(',');
+        }else {
+          this.form.trainer = [];
+        }
+        this.open = true;
+        this.title = this.$t('修改')  + this.$t('培训计划');
+      });
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.submitDisabled = true;
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          var trainerId = null;
+          this.form.trainer.forEach(function (value,key,arr) {
+            if (key != 0) {
+              trainerId = trainerId + "," + value;
+            }else if (key == 0) {
+              trainerId = value;
+            }
+          })
+
+          var id = null;
+          this.form.position.forEach(function (value,key,arr) {
+            if (key != 0) {
+              id = id + "," + value;
+            }else if (key == 0) {
+              id = value;
+            }
+          })
+
+          var designatedId = null;
+          this.designatedPositions.forEach(function (value,key,arr) {
+            if (key != 0) {
+              designatedId = designatedId + "," + value;
+            }else if (key == 0) {
+              designatedId = value;
+            }
+          })
+          this.form.designatedPosition = designatedId;
+
+          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 u = null;
+          this.form.unit.forEach(function (value,key,arr) {
+            if (key != 0) {
+              u = u + "," + value;
+            }else if (key == 0) {
+              u = value;
+            }
+          })
+
+          var parentId = null;
+          this.nonParticipants.forEach(function (value,key,arr) {
+            if (key != 0) {
+              parentId = parentId + "," + value;
+            }else if (key == 0) {
+              parentId = value;
+            }
+          })
+          this.form.trainer = trainerId;
+          this.form.position = id;
+          this.form.unit = u;
+          // this.form.nonParticipants = parentId;
+          if (this.form.id != null) {
+            updateTrainingbcc(this.form).then(response => {
+              this.msgSuccess(this.$t('修改成功'));
+              this.open = false;
+              this.submitDisabled = false;
+              this.getList();
+            });
+          } else {
+            addTrainingbcc(this.form).then(response => {
+              this.msgSuccess(this.$t('新增成功'));
+              this.open = false;
+              this.submitDisabled = false;
+              this.getList();
+            });
+          }
+        } else {
+          this.submitDisabled = false;
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    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 delTrainingbcc(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 exportTrainingbcc(queryParams);
+      }).then(response => {
+        this.download(response.msg);
+      })
+    },
+
+    /** 参会人员名单按钮操作 */
+    handleStaffmgr(row) {
+      this.leftList = [];
+      const id = row.id || this.ids
+      getTrainingbccStaffIds(id).then(response => {
+        this.personForm = response.data;
+        if (response.data.staffIds != null) {
+          this.checked = response.data.staffIds.split(",");
+        }else {
+          this.checked = [];
+        }
+        this.personOpen = true;
+      });
+    },
+    handleDetail(row){
+      this.$router.push({ name: 'deviceList', params: { id: row.id }})
+    },
+    //岗位筛选变动
+    postChange() {
+      this.leftList = [];
+      if (this.checkboxPost.length > 0) {
+        this.staffmgrQueryParams.actualposts = this.checkboxPost.toString();
+        this.$nextTick(() => {
+          selectTimeStaffmgr(this.staffmgrQueryParams).then(response => {
+            const allData = response.rows
+            const data = [];
+            for (let i = 0; i < allData.length; i++) {
+              data[i] = allData[i].staffid
+            }
+            this.leftList = data;
+          })
+        })
+      }
+    },
+
+    //选择参会人员变动
+    staffChange() {
+      this.personForm.staffIds = this.checked.toString()
+    },
+
+    selectCourse(val) {
+      this.queryParams.trainingType = val
+      this.handleQuery()
+    },
+    /** 参会人员提交按钮 */
+    submitParticipants() {
+      this.$refs["personForm"].validate(valid => {
+        if (valid) {
+          updateTrainingbccStaffIds(this.personForm).then(response => {
+            this.msgSuccess(this.$t('修改成功'));
+            this.personOpen = false;
+            this.checkboxPost = [];
+            this.getList();
+          });
+        }
+      });
+    },
+    // 选择参会人员取消按钮
+    cancelParticipants() {
+      this.personOpen = false;
+      this.reset();
+    },
+  }
+};
+</script>
+<style scoped>
+.staff_checked >>> .el-transfer-panel {
+  width : 600px;
+}
+.el-transfer-panel__item.el-checkbox {
+  width: 553px !important;
+}
+.avatar-uploader .el-upload {
+  border: 1px dashed #d9d9d9;
+  border-radius: 6px;
+  cursor: pointer;
+  position: relative;
+  overflow: hidden;
+}
+.avatar-uploader .el-upload:hover {
+  border-color: #409EFF;
+}
+.avatar-uploader-icon {
+  font-size: 28px;
+  color: #8c939d;
+  width: 178px;
+  height: 178px;
+  line-height: 178px;
+  text-align: center;
+}
+.avatar {
+  width: 178px;
+  height: 178px;
+  display: block;
+}
+
+</style>

+ 1502 - 0
ui/src/views/training/trainingbcc/indexbak.vue

@@ -0,0 +1,1502 @@
+<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('年份')"
+                        @change="handleQuery" >
+        </el-date-picker>
+      </el-form-item>
+      <el-form-item :label="$t('培训课程')" prop="course">
+        <el-input
+          v-model="queryParams.course"
+          :placeholder="$t('请输入') + $t('培训课程')"
+          clearable
+          size="small"
+          @input="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item :label="$t('培训类型')" prop="trainingType" label-width="50">
+        <el-select v-model="queryParams.trainingType" @change="handleQuery"    :placeholder="$t('请选择') + $t('培训类型')" clearable size="small">
+          <el-option
+            v-for="dict in trainingTypeOptions"
+            :key="dict.dictValue"
+            :label="dict.dictLabel"
+            :value="dict.dictValue"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item :label="$t('是否完成')" prop="isfinish" label-width="50">
+        <el-select v-model="queryParams.isfinish" @change="handleQuery"    :placeholder="$t('请选择') + $t('是否完成')" clearable size="small">
+          <el-option
+            v-for="dict in isfinishOptions"
+            :key="dict.dictValue"
+            :label="dict.dictLabel"
+            :value="dict.dictValue"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item :label="$t('未参培情况')" prop="isNon" label-width="50">
+        <el-select v-model="queryParams.isNon" @change="handleQuery"    :placeholder="$t('请选择') + $t('是否未参培')" clearable size="small">
+          <el-option
+            key="0"
+            label="全部"
+            value="0"
+          />
+          <el-option
+            key="1"
+            label="未参培"
+            value="1"
+          />
+          <el-option
+            key="2"
+            label="已完成"
+            value="2"
+          />
+          <el-option
+            key="3"
+            label="未完成"
+            value="3"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item :label="$t('培训开始日期')" label-width="60">
+        <el-date-picker
+          v-model="chooseDate"
+          @change="handleQuery"
+          type="daterange"
+          align="right"
+          unlink-panels
+          :range-separator="$t('至')"
+          :start-placeholder="$t('开始日期')"
+          :end-placeholder="$t('结束日期')"
+          value-format="yyyy-MM-dd"
+          :picker-options="pickerOptions">
+        </el-date-picker>
+      </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:training: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:training: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:training: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:training:edit']"
+          >{{ $t('导入') }}</el-button>
+      </el-col>-->
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          icon="el-icon-download"
+          size="mini"
+          @click="handleExport"
+          v-hasPermi="['training:training:export']"
+        >{{ $t('导出') }}</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-row>
+      <el-col :span="24">
+        <el-button type="primary" plain @click="selectCourse('10')">定期类</el-button>
+        <el-button type="primary" plain @click="selectCourse('12')">{{ $t('程序指导书更新类') }}</el-button>
+        <el-button type="primary" plain @click="selectCourse('14')">{{ $t('事件报告和调查') }}</el-button>
+        <el-button type="primary" plain @click="selectCourse('16')">GIS/GSA</el-button>
+        <el-button type="primary" plain @click="selectCourse('20')">BYC EHS月报</el-button>
+      </el-col>
+    </el-row>
+    <el-table v-loading="loading" :data="trainingList" @selection-change="handleSelectionChange" :cell-style="tableCellStyle" :height="clientHeight" border>
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column :label="$t('年份')" align="center" prop="year" :show-overflow-tooltip="true"/>
+      <el-table-column :label="$t('培训课程')" align="center" prop="course" width="250" :show-overflow-tooltip="true"/>
+      <el-table-column :label="$t('培训类型')" align="center" prop="trainingType" width="120" :formatter="trainingTypeFormat"/>
+      <el-table-column :label="$t('培训内容')" align="center" prop="content" width="250" :show-overflow-tooltip="true" />
+      <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">
+          <span v-if="scope.row.isfinish === 1">{{ isfinishFormat(scope.row,)}}</span>
+          <span v-if="scope.row.isfinish === 0">{{ isfinishFormat(scope.row,)}} ({{ 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="$t('部门')" align="center" prop="unit" :show-overflow-tooltip="true" />
+      <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">
+          <span>{{ parseTime(scope.row.courseStartdate, '{y}-{m}-{d}') }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column :label="$t('培训结束日期')" align="center" prop="courseEnddate" width="100">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.courseEnddate, '{y}-{m}-{d}') }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column :label="$t('未参培人员名单')" align="center" prop="nonParticipants" width="200" :show-overflow-tooltip="true" />
+      <el-table-column :label="$t('备注')" align="center" prop="remarks" :show-overflow-tooltip="true"/>
+      <el-table-column :label="$t('操作')" align="center" fixed="right" width="270" 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:training:edit']"
+          >{{ $t('修改') }}</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleStaffmgr(scope.row)"
+            v-hasPermi="['training:training:edit']"
+          >人员名单</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-news"
+            @click="handleNew(scope.row)"
+          >{{ $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"
+    />
+    <form ref="downloadFileForm" :action="downloadAction" target="FORMSUBMIT">
+      <input name="trainingId" :value=this.trainingId hidden />
+    </form>
+    <!-- 弹窗, 新增 / 修改 -->
+    <non-add v-if="nonVisible" ref="nonAdd" @refreshDataList="getList" :showFlag="showFlag" @closeChildDialog="closeChildDialog"></non-add>
+    <new-add v-if="newVisible" ref="newAdd" @refreshDataList="getList" :showFlag="showFlag" @closeChildDialog="closeChildDialog"></new-add>
+
+    <!-- 添加或修改培训计划对话框 -->
+    <el-dialog  :close-on-click-modal="false" v-dialogDrag :title="title" :visible.sync="open" width="800px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="110px">
+        <el-row>
+          <el-col :span="12">
+            <el-form-item :label="$t('培训课程')" prop="course">
+              <el-input v-model="form.course" :placeholder="$t('请输入') + $t('培训课程')" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item :label="$t('培训类型')" prop="trainingType">
+              <el-select v-model="form.trainingType" :placeholder="$t('请选择') + $t('培训类型')">
+                <el-option
+                  v-for="dict in trainingTypeOptions"
+                  :key="dict.dictValue"
+                  :label="dict.dictLabel"
+                  :value="dict.dictValue"
+                ></el-option>
+              </el-select>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="12">
+            <el-form-item :label="$t('培训内容')" prop="content">
+              <el-input v-model="form.content" :placeholder="$t('请输入') + $t('培训内容')" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item :label="$t('课程代码')" prop="courseid">
+              <el-input v-model="form.courseid" :placeholder="$t('请输入') + $t('课程代码')" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="12">
+            <el-form-item :label="$t('培训周期')" prop="period">
+              <el-input v-model="form.period" :placeholder="$t('请输入') + $t('培训周期')" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item :label="$t('课时')" prop="duration">
+              <el-input v-model="form.duration" :placeholder="$t('请输入') + $t('课时')" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="12">
+            <el-form-item :label="$t('培训人')" prop="trainer">
+              <el-select v-model="form.trainer" 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-col>
+          <el-col :span="12">
+            <el-form-item :label="$t('部门')" prop="unit">
+              <el-select v-model="form.unit" multiple :placeholder="$t('请选择') + $t('部门')" >
+                <el-option
+                  v-for="dict in unitOptions"
+                  :key="dict.dictValue"
+                  :label="dict.dictLabel"
+                  :value="dict.dictValue"
+                ></el-option>
+              </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">
+                <el-option
+                  v-for="dict in positionOptions"
+                  :key="dict.dictValue"
+                  :label="dict.dictLabel"
+                  :value="dict.dictValue"
+                ></el-option>
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item :label="$t('是否存在') +$t('指定人员')" prop="haveDesignated" label-width="140px">
+              <el-checkbox v-model="haveDesignated" @change="changeHave"></el-checkbox>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="12">
+            <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="handleStaff"
+                              :placeholder="$t('请选择') + $t('年份')">
+              </el-date-picker>
+            </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">
+                <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>
+          <el-col :span="12">
+            <el-form-item :label="$t('培训开始日期')" prop="courseStartdate">
+              <el-date-picker clearable size="small" style="width: 200px"
+                              v-model="form.courseStartdate"
+                              type="date"
+                              value-format="yyyy-MM-dd"
+                              :placeholder="$t('请选择') + $t('培训开始日期')">
+              </el-date-picker>
+            </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('指定人员')">
+                <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>
+          <el-col :span="12">
+            <el-form-item :label="$t('培训结束日期')" prop="courseEnddate">
+              <el-date-picker clearable size="small" style="width: 200px"
+                              v-model="form.courseEnddate"
+                              type="date"
+                              value-format="yyyy-MM-dd"
+                              :placeholder="$t('请选择') + $t('培训结束日期')">
+              </el-date-picker>
+            </el-form-item >
+          </el-col>
+          <el-col :span="12">
+            <el-form-item :label="$t('是否完成')" prop="isfinish">
+              <el-select v-model="form.isfinish" :placeholder="$t('请选择') + $t('是否完成')">
+                <el-option
+                  v-for="dict in isfinishOptions"
+                  :key="dict.dictValue"
+                  :label="dict.dictLabel"
+                  :value="parseInt(dict.dictValue)"
+                ></el-option>
+              </el-select>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="12">
+            <el-form-item :label="$t('备注')" prop="remarks">
+              <el-input v-model="form.remarks" :placeholder="$t('请输入') + $t('备注')" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item :label="$t('归属部门')" prop="deptId">
+              <treeselect v-model="form.deptId" :options="deptOptions" :show-count="true" :placeholder="$t('请选择') + $t('归属部门')" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-form-item :label="$t('图片')" v-if="this.form.trainingType == '12'" prop="picUrl">
+          <el-upload
+            :action="pic.url"
+            :headers="pic.headers"
+            :file-list="photoList"
+            :limit="5"
+            :on-success="handleAvatarSuccess"
+            :on-exceed="handleExceed"
+            :before-upload="beforeAvatarUpload"
+            list-type="picture-card"
+            :on-preview="handlePictureCardPreview"
+            :on-remove="handleRemove">
+            <i class="el-icon-plus"></i>
+          </el-upload>
+          <el-dialog  :close-on-click-modal="false" v-dialogDrag :visible.sync="dialogVisible" append-to-body>
+            <img width="100%" :src="dialogImageUrl" alt="">
+          </el-dialog>
+        </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>
+
+    <!-- 添加参与公司级培训人员名单对话框 -->
+    <el-dialog  :close-on-click-modal="false" v-dialogDrag title="培训人员名单" :visible.sync="personOpen" width="1500px" append-to-body>
+      <el-form ref="form" :model="personForm" :rules="rules" label-width="80px">
+
+        <el-form-item :label="$t('课程名称')" prop="item">
+          <el-input v-model="personForm.item" disabled />
+        </el-form-item>
+        <el-form-item :label="$t('实际岗位')">
+          <el-checkbox-group v-model="checkboxPost" size="medium" @change="postChange">
+            <el-checkbox-button v-for="post in actualpostOptions" :label="post.key" :key="post.key">{{post.label}}</el-checkbox-button>
+          </el-checkbox-group>
+        </el-form-item>
+        <el-form-item :label="$t('人员姓名')">
+          <el-select v-model="searchStaffmgr" filterable :placeholder="$t('请选择') + $t('人员')">
+            <el-option
+              v-for="dict in stffmgrOptions"
+              :key="dict.staffid"
+              :label="dict.label"
+              :value="dict.staffid">
+              <span style="float: left">{{ dict.label }}</span>
+              <span style="float: right; color: #8492a6; font-size: 13px">{{ dict.staffid }}</span>
+            </el-option>
+          </el-select>
+          <el-button type="primary" @click="insertSearchStaffmgr" style="margin-left: 15px;">{{ $t('添加') }}</el-button>
+        </el-form-item>
+      </el-form>
+      <div class="staff_checked">
+        <el-transfer v-model="checked" :data="stffmgrOptions" @change="staffChange" :left-default-checked="leftList" >
+          <span slot-scope="{ option }">{{ option.label }}
+            <span style="float: right; color: #8492a6; font-size: 12px; padding-left: 10px;padding-right: 15px;">{{ option.staffid }}</span>
+            <span style="float: right; color: #8492a6; font-size: 12px; padding-left: 10px;">{{ option.actualpost }}</span>
+          </span>
+        </el-transfer>
+      </div>
+      <div slot="footer" class="dialog-footer">
+<!--        <el-button type="primary" @click="submitParticipants">{{ $t('确 定') }}</el-button>-->
+<!--        <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="700px" append-to-body>
+      <el-upload
+        ref="doc"
+        :limit="50"
+        :headers="doc.headers"
+        :action="doc.url + '?pType=' + doc.pType + '&pId=' + doc.pId"
+        :disabled="doc.isUploading"
+        :on-progress="handleFileDocProgress"
+        :on-success="handleFileDocSuccess"
+        :auto-upload="true"
+        drag
+      >
+        <i class="el-icon-upload"></i>
+        <div class="el-upload__text">
+          {{ $t('将文件拖到此处,或') }}
+          <em>{{ $t('点击上传') }}</em>
+        </div>
+      </el-upload>
+      <el-table :data="doc.commonfileList" border>
+        <el-table-column :label="$t('文件名')" align="center" prop="fileName" :show-overflow-tooltip="true">
+          <template slot-scope="scope">
+            <a  class="link-type"  @click="handleDownload(scope.row)">
+              <span>{{ scope.row.fileName }}</span>
+            </a>
+          </template>
+        </el-table-column>
+        <el-table-column :label="$t('大小(Kb)')" align="center" prop="fileSize" :show-overflow-tooltip="true" width="80" />
+        <el-table-column :label="$t('上传人')" align="center" prop="creator" :show-overflow-tooltip="true" width="120"/>
+        <el-table-column :label="$t('操作')" align="center" width="120" class-name="small-padding fixed-width">
+          <template slot-scope="scope">
+            <el-button
+              v-if="scope.row.fileName.endsWith('pdf')"
+              size="mini"
+              type="text"
+              icon="el-icon-view"
+              @click="handleSee(scope.row)"
+            >{{ $t('预览') }}</el-button>
+            <el-button
+              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)"
+            >{{ $t('删除') }}</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      <el-dialog  :close-on-click-modal="false" v-dialogDrag :title="pdf.title" :visible.sync="pdf.open" width="1300px" append-to-body>
+        <div style="margin-top: -60px;float: right;margin-right: 40px;">
+          <el-button size="mini" type="text" @click="openPdf">{{$t('新页面打开PDF')}}</el-button></div>
+        <div style="margin-top: -30px">
+          <iframe :src="pdf.pdfUrl" frameborder="0" width="100%" height="700px"></iframe>
+        </div>
+      </el-dialog>
+      <div slot="footer" class="dialog-footer">
+        <!--        <el-button type="primary" @click="submitFileForm">{{ $t('确 定') }}</el-button>-->
+        <el-button @click="doc.open = false">{{ $t('返 回') }}</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listTrainingbcc, getTrainingbcc, delTrainingbcc, addTrainingbcc, updateTrainingbcc, exportTrainingbcc } from "@/api/training/trainingbcc";
+import nonAdd from './trainingNon'
+import newAdd from './trainingNew'
+import {listStaffmgrAll, listAllStaffmgr, listStaffmgr, selectTimeStaffmgr} 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";
+import { allFileList, listCommonfile, getCommonfile, delCommonfile, addCommonfile, updateCommonfile, exportCommonfile} from "@/api/common/commonfile";
+import {getCompanylevel} from "@/api/training/companylevel";
+
+
+export default {
+  name: "Training",
+  components: { Treeselect, nonAdd, newAdd},
+  data() {
+    return {
+      // 遮罩层
+      loading: true,
+      positionVisible: false,
+      showFlag: false,
+      //确认按钮是否可点
+      submitDisabled: false,
+      //左侧选框默认选择
+      leftList: [],
+      // 选中数组
+      ids: [],
+      //人员筛选按钮选择数据
+      checkboxPost: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: false,
+      // 总条数
+      total: 0,
+      // 培训计划表格数据
+      trainingList: [],
+      positionIds: [],
+      trainers: [],
+      units: [],
+      nonParticipants: [],
+      // 弹出层标题
+      title: "",
+      // 部门树选项
+      deptOptions: undefined,
+      clientHeight:300,
+      // 是否显示弹出层
+      open: false,
+      personOpen: false,
+      // 装置名称字典
+      plantCodeOptions: [],
+      // 部门字典
+      unitOptions: [],
+      // 培训岗位字典
+      positionOptions: [],
+      positionOpt: [],
+      trainingTypeOptions: [],
+      // 是否完成字典
+      isfinishOptions: [],
+      // 指定岗位字典
+      designatedPositionOptions: [],
+      //指定人员岗位多选
+      designatedPositions: [],
+      //指定人员id多选
+      designatedStaffs: [],
+      //是否存在岗位多选
+      haveDesignated: '',
+      //人员表联查
+      stffmgrOptions: undefined,
+      //人员表联查-包含离职
+      stffmgrAllOptions: undefined,
+      //指定人员选项
+      designatedStaffsOptions: [],
+      // 用户导入参数
+      upload: {
+        downloadAction: process.env.VUE_APP_BASE_API + '/common/template',
+        //下载模板类型
+        type: "training",
+        // 是否显示弹出层(用户导入)
+        open: false,
+        // 弹出层标题(用户导入)
+        title: "",
+        // 是否禁用上传
+        isUploading: false,
+        // 是否更新已经存在的用户数据
+        updateSupport: 0,
+        // 设置上传的请求头部
+        headers: { Authorization: "Bearer " + getToken() },
+        // 上传的地址
+        url: process.env.VUE_APP_BASE_API + "/training/training/importData"
+      },
+      //未参会人员弹窗是否打开
+      nonVisible: false,
+      //新员工弹窗是否打开
+      newVisible: false,
+      // 报告附件参数
+      doc: {
+        file: "",
+        // 是否显示弹出层(报告附件)
+        open: false,
+        // 弹出层标题(报告附件)
+        title: "",
+        // 是否禁用上传
+        isUploading: false,
+        // 是否更新已经存在的用户数据
+        updateSupport: 0,
+        // 报告附件上传位置编号
+        ids: 0,
+        // 设置上传的请求头部
+        headers: { Authorization: "Bearer " + getToken() },
+        // 上传的地址
+        url: process.env.VUE_APP_BASE_API + "/common/commonfile/uploadFile",
+        commonfileList: null,
+        queryParams: {
+          pId: null,
+          pType: 'training'
+        },
+        pType: 'training',
+        pId: null
+      },
+      pdf : {
+        title: '',
+        pdfUrl: '',
+        numPages: null,
+        open: false,
+        pageNum: 1,
+        pageTotalNum: 1,
+        loadedRatio: 0,
+      },
+      pic: {
+        imageUrl: '',
+        fileList: [],
+        // 设置上传的请求头部
+        headers: { Authorization: "Bearer " + getToken() },
+        // 上传的地址
+        url: process.env.VUE_APP_BASE_API + "/training/training/uploadFile",
+      },
+      photoList: [],
+      dialogImageUrl: '',
+      dialogVisible: false,
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 20,
+        course: null,
+        position: [],
+        year: this.getNowTime(),
+        isfinish: null,
+        startDate: null,
+        endDate: null,
+        trainingType: null,
+        isNon: null,
+      },
+      trainingId: null,
+      //地址
+      downloadAction: process.env.VUE_APP_BASE_API + '/training/training/trainingReport',
+      //人员表查询参数
+      staffmgrQueryParams: {},
+      searchStaffmgr: "",
+      //日期快速选择
+      pickerOptions: {
+        shortcuts: [{
+          text: this.$t('最近一周'),
+          onClick(picker) {
+            const end = new Date();
+            const start = new Date();
+            start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
+            picker.$emit('pick', [start, end]);
+          }
+        }, {
+          text: this.$t('最近一个月'),
+          onClick(picker) {
+            const end = new Date();
+            const start = new Date();
+            start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
+            picker.$emit('pick', [start, end]);
+          }
+        }, {
+          text: this.$t('最近三个月'),
+          onClick(picker) {
+            const end = new Date();
+            const start = new Date();
+            start.setTime(start.getTime() - 3600 * 1000 * 24 * 90);
+            picker.$emit('pick', [start, end]);
+          }
+        }]
+      },
+      //日期选择器
+      chooseDate: [],
+      // 表单参数
+      form: {},
+      personForm: {},
+      // 表单校验
+      rules: {
+        course: [
+          { required: true, message: this.$t('培训课程') + this.$t('不能为空'), trigger: "blur" }
+        ],
+        trainingType: [
+          { required: true, message: this.$t('培训类型') + this.$t('不能为空'), trigger: "blur" }
+        ],
+        trainer: [
+          { required: true, message: this.$t('培训人') + this.$t('不能为空'), trigger: "blur" }
+        ],
+        unit: [
+          { required: true, message: this.$t('部门') + this.$t('不能为空'), trigger: "blur" }
+        ],
+        position: [
+          { required: true, message: this.$t('培训岗位') + this.$t('不能为空'), trigger: "blur" }
+        ],
+        year: [
+          { required: true, message: this.$t('年份') + this.$t('不能为空'), trigger: "blur" }
+        ],
+        courseStartdate: [
+          { required: true, message: this.$t('培训开始日期') + this.$t('不能为空'), trigger: "blur" }
+        ],
+        isfinish: [
+          { 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() {
+    const queryName = this.$route.query && this.$route.query.status;
+    if (queryName == '未参培'){
+      this.queryParams.isNon = "1"
+    }
+    if (queryName == '已完成'){
+      this.queryParams.isNon = "2"
+    }
+    if (queryName == '未完成'){
+      this.queryParams.isNon = "3"
+    }
+
+    this.getStaffmar();
+    this.getStaffmarAll();
+    //设置表格高度对应屏幕高度
+    this.$nextTick(() => {
+      this.clientHeight = (document.body.clientHeight - 80) * 0.8
+    })
+    this.getTreeselect();
+    this.getDicts("PLANT_DIVIDE").then(response => {
+      this.plantCodeOptions = response.data;
+    });
+    this.getDicts("ACTUALPOST").then(response => {
+      this.positionOptions = response.data;
+      this.designatedPositionOptions = response.data;
+      const allData = response.data
+      const data = [];
+      for (let i = 0; i < allData.length; i++) {
+        data.push({
+          key: allData[i].dictValue,
+          label: allData[i].dictLabel,
+        });
+      }
+      this.positionOpt = response.data;
+    });
+    this.getDicts("YES_NO_EN").then(response => {
+      this.isfinishOptions = response.data;
+    });
+    this.getDicts("STAFF_UNIT").then(response => {
+      this.unitOptions = response.data;
+    });
+    this.getDicts("TRAINING_TYPE_BCC").then(response => {
+      this.trainingTypeOptions = response.data;
+    });
+  },
+  methods: {
+    /** 查询培训计划列表 */
+    getList() {
+      let _this = this
+      this.loading = true;
+      listTrainingbcc(this.queryParams).then(response => {
+        this.trainingList = response.rows;
+        this.trainingList.forEach(function (value,key,arr) {
+          var positionid = null;
+          var positionName = null;
+          let unitid = null;
+          let unitName = null;
+          if (value.position != null) {
+            positionid = value.position.split(',');
+            positionid.forEach(function (value, key, arr) {
+              if (key != 0) {
+                positionName = positionName + "," + _this.selectDictLabel(_this.positionOptions, value);
+              }else if (key == 0) {
+                positionName = _this.selectDictLabel(_this.positionOptions, value);
+              }
+            })
+          }
+
+          if (value.unit != null) {
+            unitid = value.unit.split(',');
+            unitid.forEach(function (value, key, arr) {
+              if (key != 0) {
+                unitName = unitName + "," + _this.selectDictLabel(_this.unitOptions, value);
+              }else if (key == 0) {
+                unitName = _this.selectDictLabel(_this.unitOptions, value);
+              }
+            })
+          }
+          _this.trainingList[key].positionid = value.position;
+          _this.trainingList[key].position = positionName;
+          _this.trainingList[key].unitid = value.unit;
+          _this.trainingList[key].unit = unitName;
+
+          var parentName = null;
+          if (value.trainer != null) {
+            let staffId = value.trainer.split(",");
+            staffId.forEach(function (id, index) {
+              _this.stffmgrAllOptions.forEach(function (item) {
+                if (item.staffid === id) {
+                  if (index === 0) {
+                    parentName = item.name
+                  }else {
+                    parentName = parentName + "," + item.name
+                  }
+                }
+              });
+            });
+          }
+          _this.trainingList[key].trainer = parentName;
+        })
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    /** 获取当前年份 */
+    getNowTime() {
+      var now = new Date();
+      var year = now.getFullYear(); //得到年份
+      var defaultDate = `${year}`;
+      defaultDate = `${year}`
+      return defaultDate;
+    },
+    closeChildDialog () {
+      this.showFlag = false
+      this.getList();
+    },
+    /** 查询部门下拉树结构 */
+    getTreeselect() {
+      treeselect().then(response => {
+        this.deptOptions = response.data;
+      });
+    },
+    // 装置名称字典翻译
+    plantCodeFormat(row, column) {
+      return this.selectDictLabel(this.plantCodeOptions, row.plantCode);
+    },
+    // 部门字典翻译
+    unitFormat(row, column) {
+      return this.selectDictLabel(this.unitOptions, row.unit);
+    },
+    // 培训类型翻译
+    trainingTypeFormat(row, column) {
+      return this.selectDictLabel(this.trainingTypeOptions, row.trainingType);
+    },
+    // 培训岗位字典翻译
+    positionFormat(row, column) {
+      return this.selectDictLabel(this.positionOptions, row.position);
+    },
+    // 是否完成字典翻译
+    isfinishFormat(row, column) {
+      return this.selectDictLabel(this.isfinishOptions, row.isfinish);
+    },
+    //获取人员表
+    getStaffmar(year) {
+      this.staffmgrQueryParams.leftYear = year
+      listAllStaffmgr(this.staffmgrQueryParams).then(response => {
+        this.stffmgrOptions = response.rows;
+      });
+    },
+    //年份选择change事件
+    handleStaff(val){
+      this.getStaffmar(val)
+    },
+    //获取人员表--包含离职
+    getStaffmarAll() {
+      listStaffmgrAll(this.staffmgrQueryParams).then(response => {
+        this.stffmgrAllOptions = response.rows;
+        this.getList();
+      });
+    },
+    //遍历人员表
+    forEachStaffmar(id) {
+      let stffmgrName = "";
+      this.stffmgrOptions.forEach(function (item) {
+        if (item.staffid === id) {
+          stffmgrName = item.name
+        }
+      });
+      return stffmgrName
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        id: null,
+        plantCode: null,
+        course: null,
+        courseid: null,
+        period: null,
+        duration: null,
+        trainer: null,
+        positionId: [],
+        position: null,
+        content: null,
+        unit : null,
+        year: null,
+        courseStartdate: null,
+        courseEnddate: null,
+        isfinish: null,
+        delFlag: null,
+        createrCode: null,
+        createdate: null,
+        updaterCode: null,
+        updatedate: null,
+        remarks: null,
+        deptId: null,
+        startDate: null,
+        endDate: null,
+        nonParticipants: null,
+        trainingType: null,
+        picUrl: null,
+        mustTraining: null,
+        haveTraining: null
+      };
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.queryParams.startDate = this.chooseDate[0];
+      this.queryParams.endDate = this.chooseDate[1];
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.chooseDate = "";
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    //根据分数显示颜色提示
+    tableCellStyle({ row, column, rowIndex, columnIndex }) {
+      if (columnIndex == 6 && row.isfinish == 0){
+        return "color: rgba(255, 26, 26, 0.98) "
+      }
+    },
+    //培训岗位变动
+    changePosition() {
+      let _this = this
+      this.getDicts("ACTUALPOST").then(response => {
+        this.designatedPositionOptions = response.data;
+        this.form.position.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;
+        listStaffmgr(this.staffmgrQueryParams).then(response => {
+          this.designatedStaffsOptions = response.rows;
+        });
+
+        let _this = this
+        this.getDicts("ACTUALPOST").then(response => {
+          this.positionOptions = response.data;
+          this.designatedPositions.forEach(function (value, key, arr) {
+            _this.positionOptions.forEach(function (positionValue, positionkey, arr) {
+              if (positionValue.dictValue === value) {
+                _this.positionOptions.splice(positionkey ,1)
+              }
+            })
+          })
+        });
+      }else {
+        this.designatedStaffs = [];
+      }
+    },
+    //指定人员按钮变动
+    changeHave() {
+      if (this.haveDesignated === false) {
+        this.designatedPositions = []
+        this.designatedStaffs = []
+      }
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.submitDisabled = false;
+      this.haveDesignated = false;
+      this.designatedPositions = [];
+      this.getDicts("ACTUALPOST").then(response => {
+        this.positionOptions = response.data;
+      });
+      this.getDicts("ACTUALPOST").then(response => {
+        this.designatedPositionOptions = response.data;
+      });
+      this.form.trainingType = this.queryParams.trainingType
+      this.title = this.$t('新增') + this.$t('空格') + this.$t('培训计划');
+      this.getStaffmar()
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      let _this = this
+      this.submitDisabled = false;
+      const id = row.id || this.ids
+      getTrainingbcc(id).then(response => {
+        this.form = response.data;
+        this.getStaffmar(response.data.year)
+        if (this.form.position != null) {
+          this.form.position = this.form.position.split(',');
+          this.getDicts("ACTUALPOST").then(response => {
+            this.designatedPositionOptions = response.data;
+            this.form.position.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.form.position = [];
+        }
+        if (this.form.designatedPosition != null) {
+          this.designatedPositions = this.form.designatedPosition.split(',');
+          this.getDicts("ACTUALPOST").then(response => {
+            this.positionOptions = response.data;
+            this.designatedPositions.forEach(function (value, key, arr) {
+              _this.positionOptions.forEach(function (positionValue, positionkey, arr) {
+                if (positionValue.dictValue === value) {
+                  _this.positionOptions.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.$nextTick(() => {
+            listAllStaffmgr(this.staffmgrQueryParams).then(response => {
+              this.designatedStaffsOptions = response.rows;
+            });
+          })
+        }else {
+          this.haveDesignated = false;
+          this.designatedPositions = [];
+          this.getDicts("ACTUALPOST").then(response => {
+            this.positionOptions = response.data;
+          })
+        }
+        if (this.form.designatedStaff != null) {
+          this.designatedStaffs = this.form.designatedStaff.split(',');
+        }else {
+          this.designatedStaffs = [];
+        }
+        if (this.form.unit != null) {
+          this.form.unit = this.form.unit.split(',');
+          /*this.changeUnit(this.form.unit)*/
+        }else {
+          this.form.unit = [];
+        }
+        if (this.form.nonParticipants != null) {
+          this.nonParticipants = this.form.nonParticipants.split(",");
+        }
+        if (this.form.picUrl!= null){
+          this.photoList =[]
+          let fileList = this.form.picUrl.split(",")
+          for (let i = 0; i < fileList.length; i++) {
+            let item = {url: process.env.VUE_APP_BASE_API +fileList[i],response: {msg: fileList[i]} }
+            this.photoList.push(item)
+          }
+        }
+        if (this.form.trainer != null) {
+          this.form.trainer = this.form.trainer.split(',');
+        }else {
+          this.form.trainer = [];
+        }
+        this.open = true;
+        this.title = this.$t('修改')  + this.$t('培训计划');
+      });
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.submitDisabled = true;
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          var trainerId = null;
+          this.form.trainer.forEach(function (value,key,arr) {
+            if (key != 0) {
+              trainerId = trainerId + "," + value;
+            }else if (key == 0) {
+              trainerId = value;
+            }
+          })
+
+          var id = null;
+          this.form.position.forEach(function (value,key,arr) {
+            if (key != 0) {
+              id = id + "," + value;
+            }else if (key == 0) {
+              id = value;
+            }
+          })
+
+          var designatedId = null;
+          this.designatedPositions.forEach(function (value,key,arr) {
+            if (key != 0) {
+              designatedId = designatedId + "," + value;
+            }else if (key == 0) {
+              designatedId = value;
+            }
+          })
+          this.form.designatedPosition = designatedId;
+
+          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 u = null;
+          this.form.unit.forEach(function (value,key,arr) {
+            if (key != 0) {
+              u = u + "," + value;
+            }else if (key == 0) {
+              u = value;
+            }
+          })
+
+          var parentId = null;
+          this.nonParticipants.forEach(function (value,key,arr) {
+            if (key != 0) {
+              parentId = parentId + "," + value;
+            }else if (key == 0) {
+              parentId = value;
+            }
+          })
+          this.form.trainer = trainerId;
+          this.form.position = id;
+          this.form.unit = u;
+          // this.form.nonParticipants = parentId;
+          if (this.form.id != null) {
+            updateTrainingbcc(this.form).then(response => {
+              this.msgSuccess(this.$t('修改成功'));
+              this.open = false;
+              this.submitDisabled = false;
+              this.getList();
+            });
+          } else {
+            addTrainingbcc(this.form).then(response => {
+              this.msgSuccess(this.$t('新增成功'));
+              this.open = false;
+              this.submitDisabled = false;
+              this.getList();
+            });
+          }
+        } else {
+          this.submitDisabled = false;
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    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 delTrainingbcc(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 exportTrainingbcc(queryParams);
+      }).then(response => {
+        this.download(response.msg);
+      })
+    },
+    /** 导入按钮操作 */
+    handleImport() {
+      this.upload.title = this.$t('用户导入');
+      this.upload.open = true;
+    },
+    /** 下载模板操作 */
+    importTemplate() {
+      this.$refs['downloadFileForm'].submit()
+    },
+    // 文件上传中处理
+    handleFileUploadProgress(event, file, fileList) {
+      this.upload.isUploading = true;
+    },
+    // 文件上传成功处理
+    handleFileSuccess(response, file, fileList) {
+      this.upload.open = false;
+      this.upload.isUploading = false;
+      this.$refs.upload.clearFiles();
+
+      if (response.data[0] != null) {
+        this.$alert(this.$t('成功导入') + response.msg + this.$t('条数据') + "," + this.$t('第') + response.data + this.$t('行数据出现错误导入失败')+"。", this.$t('导入结果'), { dangerouslyUseHTMLString: true });
+      }else {
+        this.$alert(this.$t('成功导入') + response.msg + this.$t('条数据'), this.$t('导入结果'), { dangerouslyUseHTMLString: true });
+      }
+
+      this.getList();
+    },
+    // 提交上传文件
+    submitFileForm() {
+      this.$refs.upload.submit();
+    },
+    /** 报告附件按钮操作 */
+    handleDoc(row) {
+      this.doc.id = row.id;
+      this.doc.title = row.course;
+      this.doc.open = true;
+      this.doc.queryParams.pId = row.id
+      this.doc.pId = row.id
+      this.getFileList()
+      this.$nextTick(() => {
+        this.$refs.doc.clearFiles()
+      })
+    },
+    /** 未参培人员名单按钮操作 */
+    handleDocNon(row) {
+      this.nonVisible = true
+      this.$nextTick(() => {
+        this.$refs.nonAdd.init(row)
+      })
+    },
+    /** 新员工补培按钮操作 */
+    handleNew(row) {
+      this.newVisible = true
+      this.$nextTick(() => {
+        this.$refs.newAdd.init(row)
+      })
+    },
+    /** 参会人员名单按钮操作 */
+    handleStaffmgr(row) {
+      this.leftList = [];
+      const id = row.id || this.ids
+      getTrainingbcc(id).then(response => {
+        this.personForm = response.data;
+        this.personOpen = true;
+      });
+    },
+    //岗位筛选变动
+    postChange() {
+      this.leftList = [];
+      if (this.checkboxPost.length > 0) {
+        this.staffmgrQueryParams.actualposts = this.checkboxPost.toString();
+        this.$nextTick(() => {
+          selectTimeStaffmgr(this.staffmgrQueryParams).then(response => {
+            const allData = response.rows
+            const data = [];
+            for (let i = 0; i < allData.length; i++) {
+              data[i] = allData[i].staffid
+            }
+            this.leftList = data;
+          })
+        })
+      }
+    },
+    /** 参会人员人名搜索添加按钮 */
+    insertSearchStaffmgr() {
+      const data = [];
+      for (let i = 0; i < this.leftList.length; i++) {
+        data.push(this.leftList[i])
+      }
+      data.push(this.searchStaffmgr)
+      this.leftList = data
+      this.$nextTick(() => {
+        this.searchStaffmgr = "";
+      })
+    },
+    //选择参会人员变动
+    staffChange() {
+      this.form.staffId = this.checked.toString()
+    },
+    getFileList (){
+      allFileList(this.doc.queryParams).then(response => {
+        this.doc.commonfileList = response;
+      });
+    },
+    //附件上传中处理
+    handleFileDocProgress(event, file, fileList) {
+      this.doc.file = file;
+      this.doc.isUploading = true;
+    },
+    //附件上传成功处理
+    handleFileDocSuccess(response, file, fileList) {
+      this.doc.isUploading = false;
+      this.$alert(response.msg, this.$t('导入结果'), { dangerouslyUseHTMLString: true });
+      this.getFileList()
+    },
+    //pdf预览
+    openPdf(){
+      window.open(this.pdf.pdfUrl);//path是文件的全路径地址
+    },
+    handleSee (row){
+      this.pdf.open =true
+      this.pdf.title = row.fileName
+      this.pdf.pdfUrl = process.env.VUE_APP_BASE_API +'/pdf/web/viewer.html?file=' + process.env.VUE_APP_BASE_API + row.fileUrl
+    },
+    /** 删除按钮操作 */
+    handleDeleteDoc(row) {
+      const ids = row.id || this.ids;
+      this.$confirm(this.$t('是否确认删除?'), this.$t('警告'), {
+        confirmButtonText: this.$t('确定'),
+        cancelButtonText: this.$t('取消'),
+        type: "warning"
+      }).then(function() {
+        return delCommonfile(ids);
+      }).then(() => {
+        this.getFileList()
+        this.msgSuccess(this.$t('删除成功'));
+      })
+    },
+    // 文件下载处理
+    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()
+    },
+    changeUnit(val) {
+      let unitArr = []
+      unitArr = val
+      let flag = false
+      for (let i = 0; i < unitArr.length; i++) {
+        if (unitArr[i] == 10) {
+          this.positionVisible = true
+          flag =true
+          break
+        }
+      }
+      if (!flag) {
+        this.positionVisible = false
+        this.form.position = null
+      }
+    },
+    selectCourse(val) {
+      this.queryParams.trainingType = val
+      this.handleQuery()
+    },
+    /** 生成签名按钮操作 */
+    getReport(row) {
+      this.trainingId = row.id
+      console.log(row.id)
+      this.$nextTick(() => {
+        this.$refs['downloadFileForm'].submit()
+      })
+    },
+    handleExceed(files, fileList) {
+      this.$message.warning(this.$t('当前限制选择 5 个文件'));
+    },
+    handleRemove(file, fileList) {
+      this.form.picUrl = fileList.map((obj)=>{return obj.response.msg}).join(",");
+      console.log(this.form.picUrl)
+    },
+    handleAvatarSuccess(res, file, fileList) {
+      console.log(fileList)
+      this.photoList = fileList
+      this.form.picUrl = fileList.map((obj)=>{return obj.response.msg}).join(",");
+      console.log(this.form.picUrl)
+    },
+    handlePictureCardPreview(file) {
+      this.dialogImageUrl = file.url;
+      this.dialogVisible = true;
+    },
+    beforeAvatarUpload(file) {
+      const isJPG = file.type === 'image/jpeg' || file.type === 'image/png'
+      const isLt2M = file.size / 1024 / 1024 < 2
+
+      if (!isJPG) {
+        this.$message.error(this.$t('上传图片只能是 JPG/PNG 格式!'));
+      }
+      if (!isLt2M) {
+        this.$message.error(this.$t('上传头像图片大小不能超过 2MB!'));
+      }
+      return isJPG && isLt2M;
+    }
+  }
+};
+</script>
+<style>
+.avatar-uploader .el-upload {
+  border: 1px dashed #d9d9d9;
+  border-radius: 6px;
+  cursor: pointer;
+  position: relative;
+  overflow: hidden;
+}
+.avatar-uploader .el-upload:hover {
+  border-color: #409EFF;
+}
+.avatar-uploader-icon {
+  font-size: 28px;
+  color: #8c939d;
+  width: 178px;
+  height: 178px;
+  line-height: 178px;
+  text-align: center;
+}
+.avatar {
+  width: 178px;
+  height: 178px;
+  display: block;
+}
+</style>

+ 261 - 0
ui/src/views/training/trainingbcc/trainingNew.vue

@@ -0,0 +1,261 @@
+<template>
+  <el-dialog  :close-on-click-modal="false" v-dialogDrag
+    :title="$t('新员工补培')"
+
+    :visible.sync="visible"
+    @close="closeDialog">
+    <el-form :inline="true" :model="queryParams" @keyup.enter.native="getDataList()">
+      <el-form-item>
+        <el-button v-hasPermi="['training:training:trainingNon']" type="primary" @click="add()">{{ $t('新增') }}</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-table :data="trainingNonList" border>
+      <el-table-column :label="$t('新员工补培')" align="center" header-align="center" prop="staffId" :show-overflow-tooltip="true">
+        <template slot-scope="scope">
+          <el-select v-model="scope.row.staffId" v-if="scope.row.isEdit" filterable :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>
+          <span v-else>{{scope.row.name}}</span>
+        </template>
+      </el-table-column>
+      <el-table-column :label="$t('培训日期')" align="center" header-align="center" prop="trainingDate">
+        <template slot-scope="scope">
+          <el-date-picker
+            v-if="scope.row.isEdit"
+            v-model="scope.row.trainingDate"
+            type="date"
+            value-format="yyyy-MM-dd"
+            :placeholder="$t('日期')">
+          </el-date-picker>
+          <span v-else>{{ parseTime(scope.row.trainingDate, '{y}-{m}-{d}') }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column :label="$t('补培讲师')" align="center" header-align="center" prop="trainingStaff" :show-overflow-tooltip="true">
+        <template slot-scope="scope">
+          <el-select v-model="scope.row.trainingStaff" v-if="scope.row.isEdit" filterable :placeholder="$t('请选择') + $t('补培讲师')">
+            <el-option
+              v-for="dict in trainingstaffOptions"
+              :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>
+          <span v-else>{{scope.row.staffName}}</span>
+        </template>
+      </el-table-column>
+      <el-table-column :label="$t('备注')" align="center" header-align="center" prop="remarks" :show-overflow-tooltip="true">
+        <template slot-scope="scope">
+          <el-input v-if="scope.row.isEdit" v-model="scope.row.remarks"></el-input>
+          <span v-else>{{scope.row.remarks}}</span>
+        </template>
+      </el-table-column>
+      <el-table-column :label="$t('操作')" align="center" fixed="right" width="120" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button v-hasPermi="['training:training:trainingNon']" type="text" size="small" v-if="scope.row.isEdit" @click="save(scope.row)">{{ $t('保存') }}</el-button>
+          <el-button type="text" size="small" v-if="scope.row.isEdit" @click="cancel(scope.row, scope.$index)">{{ $t('取消') }}</el-button>
+          <el-button v-hasPermi="['training:training:trainingNon']" v-if="!scope.row.isEdit" @click="edit(scope.row)" type="text" size="mini">{{ $t('编辑') }}</el-button>
+          <el-button v-hasPermi="['training:training:trainingNon']" v-if="!scope.row.isEdit" type="text" size="small" @click="deleteHandle(scope.row)">{{ $t('删除') }}</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+  </el-dialog>
+</template>
+
+<script>
+import { listTrainingNon, getTrainingNon, delTrainingNon, addTrainingNon, updateTrainingNon, exportTrainingNon, importTemplate} from "@/api/training/trainingNon";
+import { listStaffmgr,listAllStaffmgr, selectByStaffId } from "@/api/plant/staffmgr";
+
+export default {
+  name: "TrainingNew",
+  props: {
+    // 接受父级组件的显示标记,用于被watch
+    showFlag: {
+      type: Boolean
+    }
+  },
+  data() {
+    return {
+      visible: false,
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 20,
+        trainingId: '',
+        isNew: 1
+      },
+      //人员表查询参数
+      staffmgrQueryParams: {
+        staffid: null,
+        unit: null,
+        actualposts: null
+      },
+      trainingStaffQueryParams: {},
+      // 培训计划未参加人员表格数据
+      trainingNonList: [],
+      //人员表联查
+      stffmgrOptions: undefined,
+      trainingstaffOptions: undefined,
+      //指定人员名单
+      designatedStaffs: [],
+      // 总条数
+      total: 0,
+      // 表单参数
+      form: {},
+    }
+  },
+  watch: {
+    // 观察父级组件的showFlag,并将showFlag的最新值设置给dialogVisible
+    showFlag (newVal, oldVal) {
+      this.visible = newVal
+    }
+  },
+  methods: {
+    init (row) {
+      this.queryParams.trainingId = row.id || 0
+      this.staffmgrQueryParams.leftYear = row.year
+      this.trainingStaffQueryParams.leftYear = row.year
+      this.staffmgrQueryParams.units = row.unitid
+      this.staffmgrQueryParams.actualposts = row.positionid
+      if (row.designatedStaff != null) {
+        this.designatedStaffs = row.designatedStaff.split(',')
+      }else {
+        this.designatedStaffs = []
+      }
+      this.getStaffmar()
+      this.visible = true
+    },
+    //获取人员表
+    getStaffmar() {
+      listAllStaffmgr(this.staffmgrQueryParams).then(response => {
+        this.stffmgrOptions = response.rows;
+        if (this.designatedStaffs.length > 0) {
+          selectByStaffId(this.designatedStaffs).then(response => {
+            this.stffmgrOptions = this.stffmgrOptions.concat(response.data)
+          })
+        }
+      });
+      listAllStaffmgr(this.trainingStaffQueryParams).then(response => {
+        this.trainingstaffOptions = response.rows;
+      });
+      this.$nextTick(() => {
+        this.getList();
+      })
+    },
+    /** 查询培训计划未参加人员列表 */
+    getList() {
+      this.loading = true;
+      listTrainingNon(this.queryParams).then(response => {
+        this.total = response.total;
+          response.rows.forEach(element => {
+            element["isEdit"] = false
+          });
+          response.rows.forEach(element => {
+            element["isAdd"] = false
+          });
+          this.trainingNonList = response.rows;
+
+        this.loading = false;
+      });
+    },
+    /**
+     * 关闭弹出框事件,触发父级组件的getList方法
+     */
+    closeDialog () {
+      this.$emit('closeChildDialog')
+    },
+      // 取消
+    cancel(row, index) {
+      // 如果是新增的数据
+      if (row.isAdd) {
+        this.trainingNonList.splice(index, 1)
+      } else {
+        // 不是新增的数据  还原数据
+        for (const i in row.oldRow) {
+          row[i] = row.oldRow[i]
+        }
+        row.isEdit = false
+      }
+    },
+    edit(row) {
+      // 备份原始数据
+      row['oldRow'] = JSON.parse(JSON.stringify(row));
+      this.$nextTick(() => {
+        row.isEdit = true;
+      })
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        id: null,
+        delFlag: null,
+        createrCode: null,
+        createdate: null,
+        updaterCode: null,
+        updatedate: null,
+        remarks: null,
+        trainingDate: null,
+        staffId: null,
+        trainingId: null,
+        trainingStaff: null,
+        isNew: 1
+      };
+      this.resetForm("form");
+    },
+    add() {
+      this.trainingNonList.push({
+        trainingId: this.queryParams.trainingId,
+        staffId: '',
+        trainingDate: '',
+        isNew: 1,
+        isEdit: true,
+        isAdd: true
+      });
+    },
+    save(row) {
+      row.isEdit = false;
+      var that = this;
+      that.loading = true;
+      this.form = row;
+      this.form.trainingId = this.queryParams.trainingId;
+      this.form.isNew = 1;
+      if (row.isAdd == true) {
+        addTrainingNon(this.form).then(response => {
+          this.msgSuccess(this.$t('新增成功'));
+          this.open = false;
+          this.getList();
+        });
+      }else {
+        updateTrainingNon(this.form).then(response => {
+          this.msgSuccess(this.$t('修改成功'));
+          this.open = false;
+          this.getList();
+        });
+      }
+    },
+    /** 删除按钮操作 */
+    deleteHandle(row) {
+      const ids = row.id || this.ids;
+      this.$confirm(this.$t('是否确认删除?'), this.$t('警告'), {
+        confirmButtonText: this.$t('确定'),
+        cancelButtonText: this.$t('取消'),
+        type: "warning"
+        }).then(function() {
+          return delTrainingNon(ids);
+        }).then(() => {
+          this.getList();
+          this.msgSuccess(this.$t('删除成功'));
+        })
+    },
+  }
+};
+</script>

+ 264 - 0
ui/src/views/training/trainingbcc/trainingNon.vue

@@ -0,0 +1,264 @@
+<template>
+  <el-dialog  :close-on-click-modal="false" v-dialogDrag
+    :title="$t('未参会人员名单')"
+
+    :visible.sync="visible"
+    @close="closeDialog">
+    <el-form :inline="true" :model="queryParams" @keyup.enter.native="getDataList()">
+      <el-form-item>
+        <el-button v-hasPermi="['training:training:trainingNon']" type="primary" @click="add()">{{ $t('新增') }}</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-table :data="trainingNonList" border>
+      <el-table-column :label="$t('未参会人员姓名')" align="center" header-align="center" prop="staffId" :show-overflow-tooltip="true">
+        <template slot-scope="scope">
+          <el-select v-model="scope.row.staffId" v-if="scope.row.isEdit" filterable :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>
+          <span v-else>{{scope.row.name}}</span>
+        </template>
+      </el-table-column>
+      <el-table-column :label="$t('培训日期')" align="center" header-align="center" prop="trainingDate">
+        <template slot-scope="scope">
+          <el-date-picker
+            v-if="scope.row.isEdit"
+            v-model="scope.row.trainingDate"
+            type="date"
+            value-format="yyyy-MM-dd"
+            :placeholder="$t('日期')">
+          </el-date-picker>
+          <span v-else>{{ parseTime(scope.row.trainingDate, '{y}-{m}-{d}') }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column :label="$t('补培讲师')" align="center" header-align="center" prop="trainingStaff" :show-overflow-tooltip="true">
+        <template slot-scope="scope">
+          <el-select v-model="scope.row.trainingStaff" v-if="scope.row.isEdit" filterable :placeholder="$t('请选择') + $t('补培讲师')">
+            <el-option
+              v-for="dict in trainingstaffOptions"
+              :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>
+          <span v-else>{{scope.row.staffName}}</span>
+        </template>
+      </el-table-column>
+      <el-table-column :label="$t('备注')" align="center" header-align="center" prop="remarks" :show-overflow-tooltip="true">
+        <template slot-scope="scope">
+          <el-input v-if="scope.row.isEdit" v-model="scope.row.remarks"></el-input>
+          <span v-else>{{scope.row.remarks}}</span>
+        </template>
+      </el-table-column>
+      <el-table-column :label="$t('操作')" align="center" fixed="right" width="120" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button v-hasPermi="['training:training:trainingNon']" type="text" size="small" v-if="scope.row.isEdit" @click="save(scope.row)">{{ $t('保存') }}</el-button>
+          <el-button type="text" size="small" v-if="scope.row.isEdit" @click="cancel(scope.row, scope.$index)">{{ $t('取消') }}</el-button>
+          <el-button v-hasPermi="['training:training:trainingNon']" v-if="!scope.row.isEdit" @click="edit(scope.row)" type="text" size="mini">{{ $t('编辑') }}</el-button>
+          <el-button v-hasPermi="['training:training:trainingNon']" v-if="!scope.row.isEdit" type="text" size="small" @click="deleteHandle(scope.row)">{{ $t('删除') }}</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+  </el-dialog>
+</template>
+
+<script>
+import { listTrainingNon, getTrainingNon, delTrainingNon, addTrainingNon, updateTrainingNon, exportTrainingNon, importTemplate} from "@/api/training/trainingNon";
+import { listStaffmgr,listAllStaffmgr, selectByStaffId } from "@/api/plant/staffmgr";
+
+export default {
+  name: "TrainingNon",
+  props: {
+    // 接受父级组件的显示标记,用于被watch
+    showFlag: {
+      type: Boolean
+    }
+  },
+  data() {
+    return {
+      visible: false,
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 20,
+        trainingId: '',
+        isNew: 0
+      },
+      //人员表查询参数
+      staffmgrQueryParams: {
+        staffid: null,
+        unit: null,
+        actualposts: null,
+        leftYear: null
+      },
+      trainingStaffQueryParams: {
+        leftYear: null
+      },
+      // 培训计划未参加人员表格数据
+      trainingNonList: [],
+      //人员表联查
+      stffmgrOptions: undefined,
+      trainingstaffOptions: undefined,
+      //指定人员名单
+      designatedStaffs: [],
+      // 总条数
+      total: 0,
+      // 表单参数
+      form: {},
+    }
+  },
+  watch: {
+    // 观察父级组件的showFlag,并将showFlag的最新值设置给dialogVisible
+    showFlag (newVal, oldVal) {
+      this.visible = newVal
+    }
+  },
+  methods: {
+    init (row) {
+      this.queryParams.trainingId = row.id || 0
+      this.staffmgrQueryParams.leftYear = row.year
+      this.trainingStaffQueryParams.leftYear = row.year
+      this.staffmgrQueryParams.units = row.unitid
+      this.staffmgrQueryParams.actualposts = row.positionid
+      if (row.designatedStaff != null) {
+        this.designatedStaffs = row.designatedStaff.split(',')
+      }else {
+        this.designatedStaffs = []
+      }
+      this.getStaffmar()
+      this.visible = true
+    },
+    //获取人员表
+    getStaffmar() {
+      listAllStaffmgr(this.staffmgrQueryParams).then(response => {
+        this.stffmgrOptions = response.rows;
+        if (this.designatedStaffs.length > 0) {
+          selectByStaffId(this.designatedStaffs).then(response => {
+            this.stffmgrOptions = this.stffmgrOptions.concat(response.data)
+          })
+        }
+      });
+      listAllStaffmgr(this.trainingStaffQueryParams).then(response => {
+        this.trainingstaffOptions = response.rows;
+      });
+      this.$nextTick(() => {
+        this.getList();
+      })
+    },
+    /** 查询培训计划未参加人员列表 */
+    getList() {
+      this.loading = true;
+      listTrainingNon(this.queryParams).then(response => {
+        this.total = response.total;
+          response.rows.forEach(element => {
+            element["isEdit"] = false
+          });
+          response.rows.forEach(element => {
+            element["isAdd"] = false
+          });
+          this.trainingNonList = response.rows;
+
+        this.loading = false;
+      });
+    },
+    /**
+     * 关闭弹出框事件,触发父级组件的getList方法
+     */
+    closeDialog () {
+      this.$emit('closeChildDialog')
+    },
+      // 取消
+    cancel(row, index) {
+      // 如果是新增的数据
+      if (row.isAdd) {
+        this.trainingNonList.splice(index, 1)
+      } else {
+        // 不是新增的数据  还原数据
+        for (const i in row.oldRow) {
+          row[i] = row.oldRow[i]
+        }
+        row.isEdit = false
+      }
+    },
+    edit(row) {
+      // 备份原始数据
+      row['oldRow'] = JSON.parse(JSON.stringify(row));
+      this.$nextTick(() => {
+        row.isEdit = true;
+      })
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        id: null,
+        delFlag: null,
+        createrCode: null,
+        createdate: null,
+        updaterCode: null,
+        updatedate: null,
+        remarks: null,
+        trainingDate: null,
+        staffId: null,
+        trainingId: null,
+        trainingStaff: null,
+        isNew: 0
+      };
+      this.resetForm("form");
+    },
+    add() {
+      this.trainingNonList.push({
+        trainingId: this.queryParams.trainingId,
+        staffId: '',
+        trainingDate: '',
+        isNew: 0,
+        isEdit: true,
+        isAdd: true
+      });
+    },
+    save(row) {
+      row.isEdit = false;
+      var that = this;
+      that.loading = true;
+      this.form = row;
+      this.form.trainingId = this.queryParams.trainingId;
+      this.form.isNew = 0;
+      if (row.isAdd == true) {
+        addTrainingNon(this.form).then(response => {
+          this.msgSuccess(this.$t('新增成功'));
+          this.open = false;
+          this.getList();
+        });
+      }else {
+        updateTrainingNon(this.form).then(response => {
+          this.msgSuccess(this.$t('修改成功'));
+          this.open = false;
+          this.getList();
+        });
+      }
+    },
+    /** 删除按钮操作 */
+    deleteHandle(row) {
+      const ids = row.id || this.ids;
+      this.$confirm(this.$t('是否确认删除?'), this.$t('警告'), {
+        confirmButtonText: this.$t('确定'),
+        cancelButtonText: this.$t('取消'),
+        type: "warning"
+        }).then(function() {
+          return delTrainingNon(ids);
+        }).then(() => {
+          this.getList();
+          this.msgSuccess(this.$t('删除成功'));
+        })
+    },
+  }
+};
+</script>