Parcourir la source

ly 培训优化

ly il y a 2 jours
Parent
commit
fdddb7046b
20 fichiers modifiés avec 589 ajouts et 308 suppressions
  1. 1 1
      master/src/main/java/com/ruoyi/framework/task/ImageCompressionTask.java
  2. 28 13
      master/src/main/java/com/ruoyi/framework/task/trainingbcc/TrainingMatrixTask.java
  3. 90 21
      master/src/main/java/com/ruoyi/framework/task/trainingbcc/TrainingbccTask.java
  4. 10 3
      master/src/main/java/com/ruoyi/project/document/controller/TPlantproglistController.java
  5. 211 201
      master/src/main/java/com/ruoyi/project/training/controller/TTrainingMatrixController.java
  6. 2 8
      master/src/main/java/com/ruoyi/project/training/controller/TTrainingParticipantsController.java
  7. 59 1
      master/src/main/java/com/ruoyi/project/training/controller/TTrainingbccController.java
  8. 91 38
      master/src/main/java/com/ruoyi/project/training/elearn/service/impl/TElPaperServiceImpl.java
  9. 1 1
      master/src/main/resources/application.yml
  10. 1 1
      master/src/main/resources/mybatis/system/SysUserMapper.xml
  11. 8 8
      master/src/main/resources/mybatis/training/TTrainingNonMapper.xml
  12. BIN
      master/src/main/resources/static/template/training/trainingMatrix.xlsx
  13. BIN
      master/src/main/resources/static/word/training/signMOC.docx
  14. BIN
      master/src/main/resources/static/word/training/signMOCbcc.docx
  15. BIN
      master/src/main/resources/static/word/training/signbcc.docx
  16. 11 2
      ui/src/views/training/bccregular/regular.vue
  17. 13 0
      ui/src/views/training/companylevel/index.vue
  18. 46 7
      ui/src/views/training/matrix/index.vue
  19. 11 2
      ui/src/views/training/regular/index.vue
  20. 6 1
      ui/src/views/training/trainingbcc/index.vue

+ 1 - 1
master/src/main/java/com/ruoyi/framework/task/ImageCompressionTask.java

@@ -44,7 +44,7 @@ public class ImageCompressionTask extends BaseController {
             logger.info("📁 开始压缩文件夹: {}", directories);
             ImageCompressor.CompressionResult result = ImageCompressor.compressDirectories(
                 directories, 200, 1, 100,
-                new String[]{"jpg", "jpeg", "png", "bmp", "gif"},
+                new String[]{"jpg", "jpeg", "png", "bmp"},
                 true  // 启用详细日志
             );
 

+ 28 - 13
master/src/main/java/com/ruoyi/framework/task/trainingbcc/TrainingMatrixTask.java

@@ -60,10 +60,10 @@ public class TrainingMatrixTask extends BaseController
     /**
      * 每年矩阵新增培训
      * 功能:基于fq_year字段的培训频率控制
-     * 
+     *
      * 判断逻辑:根据最新一次regular记录的年份,计算距离当前年份的年数,
      * 如果年数 >= fq_year,则需要添加培训
-     * 
+     *
      * 注意:不再使用frequency字段,完全基于fq_year字段控制
      */
     public void trainingMatrixTask()
@@ -81,7 +81,7 @@ public class TrainingMatrixTask extends BaseController
         for (TTrainingMatrix matrix: list
         ) {
             int addFlag = 0;
-            
+
             // 新增:基于fq_year字段的判断逻辑
             if (matrix.getFqYear() != null && !matrix.getFqYear().isEmpty()) {
                 try {
@@ -91,11 +91,11 @@ public class TrainingMatrixTask extends BaseController
                         tr.setItem(matrix.getItem());
                         // 查询该培训项目的所有regular记录,按年份排序(使用不带数据权限的方法)
                         List<TTrainingbccRegular> allRegulars = tTrainingbccRegularService.selectTTrainingbccRegularListWithoutScope(tr);
-                        
+
                         if (allRegulars.isEmpty()) {
                             // 如果没有任何记录,则添加培训
                             addFlag = 1;
-                            logger.info("培训项目:" + matrix.getItem() + ",fq_year=" + fqYear + 
+                            logger.info("培训项目:" + matrix.getItem() + ",fq_year=" + fqYear +
                                       ",无任何历史记录,需要添加培训");
                         } else {
                             // 找到最新的一次培训记录年份
@@ -109,20 +109,20 @@ public class TrainingMatrixTask extends BaseController
                                 })
                                 .max()
                                 .orElse(0);
-                            
+
                             // 计算距离最新培训的年数
                             int yearsSinceLastTraining = currentYear - latestYear;
-                            
-                            logger.info("培训项目:" + matrix.getItem() + ",fq_year=" + fqYear + 
+
+                            logger.info("培训项目:" + matrix.getItem() + ",fq_year=" + fqYear +
                                       ",最新培训年份=" + latestYear + ",距离最新培训年数=" + yearsSinceLastTraining);
-                            
+
                             // 如果距离最新培训的年数 >= fq_year,则需要添加培训
                             if (yearsSinceLastTraining >= fqYear) {
                                 addFlag = 1;
-                                logger.info("根据fq_year=" + fqYear + ",距离最新培训" + yearsSinceLastTraining + 
+                                logger.info("根据fq_year=" + fqYear + ",距离最新培训" + yearsSinceLastTraining +
                                           "年,需要添加培训:" + matrix.getItem());
                             } else {
-                                logger.info("培训项目:" + matrix.getItem() + ",fq_year=" + fqYear + 
+                                logger.info("培训项目:" + matrix.getItem() + ",fq_year=" + fqYear +
                                           ",距离最新培训" + yearsSinceLastTraining + "年,无需添加培训");
                             }
                         }
@@ -131,12 +131,12 @@ public class TrainingMatrixTask extends BaseController
                     logger.warn("fq_year字段值不是有效数字:" + matrix.getFqYear() + ",培训项目:" + matrix.getItem());
                 }
             }
-            
+
             // 如果fq_year字段为空或无效,则不添加培训
             if (addFlag == 0) {
                 logger.info("培训项目:" + matrix.getItem() + ",fq_year字段为空或无效,跳过添加");
             }
-            
+
             if (addFlag == 1) {
                 TTrainingbccRegular tTrainingRegular = new TTrainingbccRegular();
                 tTrainingRegular.setDeptId(matrix.getDeptId());
@@ -164,6 +164,21 @@ public class TrainingMatrixTask extends BaseController
                 tTraining.setIsfinish(Long.parseLong("0"));
                 tTraining.setDeptId(tTrainingRegular.getDeptId());
                 tTraining.setRegularId(tTrainingRegular.getId());
+                //添加学习时间
+                String hourText = matrix.getHour();
+                if (hourText != null && !hourText.trim().isEmpty() && !hourText.contains("按需")) {
+                    try {
+                        // 解析课时文本,支持 "1.5h"、"1.5小时"、"1.5" 等格式
+                        String cleanText = hourText.toLowerCase().replaceAll("[^0-9.]", "");
+                        if (!cleanText.isEmpty()) {
+                            double hours = Double.parseDouble(cleanText);
+                            int minutes = (int) Math.round(hours * 60); // 转换为分钟
+                            tTraining.setTimerNeed((long) minutes);
+                        }
+                    } catch (NumberFormatException e) {
+                        logger.warn("无法解析课时: " + hourText);
+                    }
+                }
                 trainingbccService.insertTTrainingbcc(tTraining);
                 Long trainingId = tTraining.getId();
                 //新增人员-装置级关系

+ 90 - 21
master/src/main/java/com/ruoyi/framework/task/trainingbcc/TrainingbccTask.java

@@ -1,14 +1,11 @@
 package com.ruoyi.framework.task.trainingbcc;
 
+import com.github.stuxuhai.jpinyin.PinyinException;
+import com.github.stuxuhai.jpinyin.PinyinFormat;
+import com.github.stuxuhai.jpinyin.PinyinHelper;
 import com.ruoyi.common.jpush.JiGuangPushService;
+import com.ruoyi.common.sendEmail.IMailService;
 import com.ruoyi.framework.web.controller.BaseController;
-import com.ruoyi.project.plant.domain.TConfInfo;
-import com.ruoyi.project.plant.domain.TConfRoom;
-import com.ruoyi.project.plant.mapper.TConfInfoMapper;
-import com.ruoyi.project.plant.mapper.TConfRoomMapper;
-import com.ruoyi.project.plant.service.ITConfInfoService;
-import com.ruoyi.project.plant.service.ITConfRoomService;
-import com.ruoyi.project.plant.service.ITStaffmgrService;
 import com.ruoyi.project.system.domain.SysUser;
 import com.ruoyi.project.system.mapper.SysUserMapper;
 import com.ruoyi.project.training.domain.TTrainingbcc;
@@ -19,11 +16,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
 import javax.annotation.Resource;
-import java.time.DayOfWeek;
-import java.time.LocalDateTime;
-import java.time.LocalTime;
-import java.time.ZoneId;
-import java.time.temporal.TemporalAdjusters;
+import java.text.SimpleDateFormat;
 import java.util.Date;
 import java.util.List;
 
@@ -41,10 +34,10 @@ public class TrainingbccTask extends BaseController
     private ITTrainingbccService tTrainingbccService;
     @Resource
     private SysUserMapper sysUserMapper;
-    @Autowired
-    private ITStaffmgrService tStaffmgrService;
     @Resource
     private JiGuangPushService jiGuangPushService;
+    @Autowired
+    private IMailService mailService;
 
     public void trainingbccTask()
     {
@@ -67,12 +60,22 @@ public class TrainingbccTask extends BaseController
                     if (t.getTrainingType().equals("10")) { //定期培训
                         if ( day <= 7 && day > -2) {
                             SysUser staff = sysUserMapper.selectUserByStaffId(d.getStaffId());
-                            jiGuangPushService.send("装置培训-定期培训", "您有装置培训尚未完成", staff.getUserId().toString());
+                            if (staff != null && staff.getEmail() != null && !staff.getEmail().trim().isEmpty()) {
+                                // 发送推送
+                                jiGuangPushService.send("装置培训-定期培训", "您有装置培训尚未完成", staff.getUserId().toString());
+                                // 发送邮件
+                                sendTrainingMail(t, staff, "10");
+                            }
                         }
                     }else {//非定期培训
                         if ( day <= 3 && day > -2) {
                             SysUser staff = sysUserMapper.selectUserByStaffId(d.getStaffId());
-                            jiGuangPushService.send("装置培训", "您有装置培训尚未完成", staff.getUserId().toString());
+                            if (staff != null && staff.getEmail() != null && !staff.getEmail().trim().isEmpty()) {
+                                // 发送推送
+                                jiGuangPushService.send("装置培训", "您有装置培训尚未完成", staff.getUserId().toString());
+                                // 发送邮件
+                                sendTrainingMail(t, staff, "非定期");
+                            }
                         }
                     }
                 }
@@ -81,9 +84,75 @@ public class TrainingbccTask extends BaseController
 
     }
 
+    /**
+     * 发送培训提醒邮件
+     */
+    private void sendTrainingMail(TTrainingbcc trainingbcc, SysUser sysUser, String trainingType) {
+        try {
+            String nickName = sysUser.getNickName();
+            String nickNameEN = PinyinHelper.convertToPinyinString(nickName.trim(), " ", PinyinFormat.WITHOUT_TONE);
+            String userName = sysUser.getUserName();
+            String email = sysUser.getEmail();
+            String courseName = trainingbcc.getCourse();
+            String courseEndDate = new SimpleDateFormat("yyyy-MM-dd").format(trainingbcc.getCourseEnddate());
+            String jumpUrl = "/dsdtTraining/device/";
+            
+            // 根据培训类型设置不同的提醒内容
+            String reminderContent;
+            String reminderContentEN;
+            if ("10".equals(trainingType)) {
+                reminderContent = "您有装置培训-定期培训尚未完成";
+                reminderContentEN = "You have unfinished regular device training";
+            } else {
+                reminderContent = "您有装置培训尚未完成";
+                reminderContentEN = "You have unfinished device training";
+            }
+            
+            //写html开始内容
+            String start = "<!DOCTYPE html><html><head><meta charset=\"utf-8\"><title></title></head><body><div style=\"background-color:#ECECEC; padding: 35px;\">" +
+                    "<table cellpadding=\"0\" align=\"center\"" +
+                    "style=\"width: 600px; margin: 0px auto; text-align: left; position: relative; border-top-left-radius: 5px; border-top-right-radius: 5px; border-bottom-right-radius: 5px; border-bottom-left-radius: 5px; font-size: 14px; font-family:微软雅黑, 黑体; line-height: 1.5; box-shadow: rgb(153, 153, 153) 0px 0px 5px; border-collapse: collapse; background-position: initial initial; background-repeat: initial initial;background:#fff;\">" +
+                    "<tbody><tr><th valign=\"middle\" style=\"height: 25px; line-height: 25px; padding: 15px 35px; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: #42a3d3; background-color: #49bcff; border-top-left-radius: 5px; border-top-right-radius: 5px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px;\">" +
+                    "<font face=\"微软雅黑\" size=\"5\" style=\"color: rgb(255, 255, 255); \">CPMS管理系统 </font><font face=\"微软雅黑\" size=\"3\" style=\"color: rgb(255, 255, 255); \">CPMS System</font></th></tr>";
+            
+            //表html中间内容
+            String prime = "";
+            String center = "<tr><td><div style=\"padding:25px 35px 40px; background-color:#fff;\"><h2 style=\"margin: 5px 0px; \">" +
+                    "<font color=\"#333333\" style=\"line-height: 20px; \"><font style=\"line-height: 22px; \" size=\"4\">" +
+                    "亲爱的nickName</font><br><font style=\"line-height: 22px; \" size=\"4\">" +
+                    "Dear nickNameEN(userName)</font></font></h2>" +
+                    "<p>reminderContent,详情如下:<br>" +
+                    "reminderContentEN:<br>" +
+                    "培训课程:<b>courseName</b><br>" +
+                    "截止时间:<b>courseEndDate</b><br>" +
+                    "请登录<a href=\"https://cpms.basf-ypc.net.cn/cpms/index.html#jumpUrl\">CPMS管理系统</a>查看。<br>" +
+                    "Please log in the <a href=\"https://cpms.basf-ypc.net.cn/cpms/index.html#jumpUrl\">CPMS</a> to handle it.</p>" +
+                    "<p align=\"right\">date</p>" +
+                    "<div style=\"width:700px;margin:0 auto;\">" +
+                    "<div style=\"padding:10px 10px 0;border-top:1px solid #ccc;color:#747474;margin-bottom:20px;line-height:1.3em;font-size:12px;\">" +
+                    "<p>此为系统邮件,请勿回复<br>This e-Mail is an automatic reminder sent by CPMS, please do not reply</p>" +
+                    "</div></div></div></td></tr>";
+            
+            String one = center.replaceFirst("nickName", nickName);
+            String two = one.replaceFirst("nickNameEN", nickNameEN);
+            String three = two.replaceFirst("userName", userName);
+            String four = three.replaceFirst("reminderContent", reminderContent);
+            String five = four.replaceFirst("reminderContentEN", reminderContentEN);
+            String six = five.replaceFirst("courseName", courseName);
+            String seven = six.replaceFirst("courseEndDate", courseEndDate);
+            String result = seven.replaceFirst("date", String.valueOf(new Date())).replaceFirst("jumpUrl", jumpUrl).replaceFirst("jumpUrl", jumpUrl);
+            prime = prime + result;
+            
+            //写html结尾内容
+            String end = "</tbody></table></div></body></html>";
+            //拼接html
+            String html = start + prime + end;
+            
+            String subject = "CPMS:" + reminderContent;
+            mailService.sendHtmlMail(email, subject, html);
+        } catch (PinyinException e) {
+            e.printStackTrace();
+        }
+    }
 
-
-
-
-
-}
+}

+ 10 - 3
master/src/main/java/com/ruoyi/project/document/controller/TPlantproglistController.java

@@ -257,11 +257,18 @@ public class TPlantproglistController extends BaseController
                 if (staffmgr != null && StringUtils.isNotEmpty(staffmgr.getStaffid())) {
                     tTraining.setTrainer(staffmgr.getStaffid());
                 } else {
-                    // 如果找不到对应的员工,使用原值
-                    tTraining.setTrainer(trainerName);
+                    // 如果找不到对应的员工,使用matrix中的授课人
+                    if (StringUtils.isNotEmpty(matrix.getLecturer())) {
+                        tTraining.setTrainer(matrix.getLecturer());
+                    }
+                    // 如果都没有,就不赋值(保持为null)
                 }
             } else {
-                tTraining.setTrainer(trainerName);
+                // 如果责任者为空,使用matrix中的授课人
+                if (StringUtils.isNotEmpty(matrix.getLecturer())) {
+                    tTraining.setTrainer(matrix.getLecturer());
+                }
+                // 如果都没有,就不赋值(保持为null)
             }
             // 设置培训开始时间为发布时日期
             tTraining.setCourseStartdate(currentDate);

+ 211 - 201
master/src/main/java/com/ruoyi/project/training/controller/TTrainingMatrixController.java

@@ -62,6 +62,11 @@ public class TTrainingMatrixController extends BaseController {
     private ITTrainingbccService trainingbccService;
     @Autowired
     private ITTrainingbccDeviceService trainingbccDeviceService;
+    @Autowired
+    private ITTrainingDeviceService tTrainingDeviceService;
+
+    @Autowired
+    private ITTrainingService tTrainingService;
     /**
      * 查询培训矩阵列表
      */
@@ -160,6 +165,9 @@ public class TTrainingMatrixController extends BaseController {
     public AjaxResult batchAddTraining(@PathVariable Long[] ids) {
         for (int i = 0; i < ids.length; i++) {
             TTrainingMatrix tm = tTrainingMatrixService.selectTTrainingMatrixById(ids[i]);
+            if (tm.getDeptId() == 103l) {
+                continue;
+            }
             TTrainingRegular tr = new TTrainingRegular();
             tr.setDeptId(tm.getDeptId());
             tr.setActualpostId(tm.getActualpostId());
@@ -171,6 +179,92 @@ public class TTrainingMatrixController extends BaseController {
             Calendar cal = Calendar.getInstance();
             tr.setYear(String.valueOf(cal.get(Calendar.YEAR)));
             int doInsert = tTrainingRegularService.insertTTrainingRegular(tr);
+            //新增培训计划定期类
+            TTraining tTraining = new TTraining();
+            tTraining.setTrainingType("10");
+            tTraining.setYear(tr.getYear());
+            tTraining.setCourse(tr.getItem());
+            tTraining.setCourseid(tr.getCourseCode());
+            tTraining.setDuration(tr.getHour());
+            tTraining.setTrainer(tr.getLecturer());
+            tTraining.setPosition(tr.getActualpostId());
+            tTraining.setIsfinish(Long.parseLong("0"));
+            tTraining.setDeptId(tr.getDeptId());
+            tTraining.setRegularId(tr.getId());
+            tTrainingService.insertTTraining(tTraining);
+            Long trainingId = tTraining.getId();
+            //新增人员-装置级关系
+            // 参培岗位人员
+            if (tr.getActualpostId() != null) {
+                logger.info("参培岗位人员");
+                TStaffmgr staffmgr = new TStaffmgr();
+                staffmgr.setActualposts(tr.getActualpostId());
+                List<TStaffmgr> staffmgrs = tStaffmgrService.selectAllTStaffmgrList(staffmgr);
+                try {
+                    //判断离职
+                    if (!org.apache.commons.lang.StringUtils.isEmpty(tr.getYear())) {
+                        Iterator<TStaffmgr> iterator = staffmgrs.iterator();
+                        while (iterator.hasNext()) {
+                            TStaffmgr t = iterator.next();
+                            if (t.getDelFlag() == 9){
+                                iterator.remove();
+                            }
+                        }
+                    }
+                }catch (Exception e) {
+                    logger.error(e.toString());
+                }
+                for (TStaffmgr s : staffmgrs) {
+                    TTrainingDevice tTrainingDevice = new TTrainingDevice();
+                    tTrainingDevice.setStaffId(s.getStaffid());
+                    tTrainingDevice.setRegularId(trainingId);
+                    tTrainingDevice.setStartDate(tr.getPlanTrainingdate());
+                    tTrainingDevice.setSupplementary("0");
+                    tTrainingDeviceService.insertTTrainingDevice(tTrainingDevice);
+                }
+            }
+            //指定岗位人员
+            if (tr.getDesignatedStaff() != null) {
+                logger.info("指定岗位人员");
+                String[] designatedStaffs = tr.getDesignatedStaff().split(",");
+                for (String staffId : designatedStaffs) {
+                    TTrainingDevice tTrainingDevice = new TTrainingDevice();
+                    tTrainingDevice.setStaffId(staffId);
+                    tTrainingDevice.setRegularId(trainingId);
+                    tTrainingDevice.setStartDate(tr.getPlanTrainingdate());
+                    tTrainingDevice.setSupplementary("0");
+                    tTrainingDeviceService.insertTTrainingDevice(tTrainingDevice);
+                }
+            }
+            //涉及其他部门
+            if (tr.getInvolvedMoc().equals("true")){
+                logger.info("涉及MOC人员");
+                TStaffmgr staffmgrMoc = new TStaffmgr();
+                staffmgrMoc.setActualposts(tr.getDesignatedOther());
+                List<TStaffmgr> staffmgrsMoc = tStaffmgrService.selectAllTStaffmgrList(staffmgrMoc);
+                try {
+                    //判断离职
+                    if (!org.apache.commons.lang.StringUtils.isEmpty(tr.getYear())) {
+                        Iterator<TStaffmgr> iterator = staffmgrsMoc.iterator();
+                        while (iterator.hasNext()) {
+                            TStaffmgr t = iterator.next();
+                            if (t.getDelFlag() == 9){
+                                iterator.remove();
+                            }
+                        }
+                    }
+                }catch (Exception e) {
+                    logger.error(e.toString());
+                }
+                for (TStaffmgr s : staffmgrsMoc) {
+                    TTrainingDevice tTrainingDevice = new TTrainingDevice();
+                    tTrainingDevice.setStaffId(s.getStaffid());
+                    tTrainingDevice.setRegularId(trainingId);
+                    tTrainingDevice.setStartDate(tr.getPlanTrainingdate());
+                    tTrainingDevice.setSupplementary("0");
+                    tTrainingDeviceService.insertTTrainingDevice(tTrainingDevice);
+                }
+            }
         }
         for (int i = 0; i < ids.length; i++) {
             TTrainingMatrix matrix = tTrainingMatrixService.selectTTrainingMatrixById(ids[i]);
@@ -220,11 +314,8 @@ public class TTrainingMatrixController extends BaseController {
                         Iterator<TStaffmgr> iterator = staffmgrs.iterator();
                         while (iterator.hasNext()) {
                             TStaffmgr t = iterator.next();
-                            if (t.getLeftDate() != null && t.getDelFlag() == 9){
-                                if (t.getLeftDate().getTime() - tTrainingRegular.getPlanTrainingdate().getTime() < 0l ) {
-                                    logger.debug(t.getName() + "离职时间小于培训时间");
-                                    iterator.remove();
-                                }
+                            if (t.getDelFlag() == 9){
+                                iterator.remove();
                             }
                         }
                     }
@@ -270,11 +361,8 @@ public class TTrainingMatrixController extends BaseController {
                         Iterator<TStaffmgr> iterator = staffmgrsMoc.iterator();
                         while (iterator.hasNext()) {
                             TStaffmgr t = iterator.next();
-                            if (t.getLeftDate() != null && t.getDelFlag() == 9){
-                                if (t.getLeftDate().getTime() - tTrainingRegular.getPlanTrainingdate().getTime() > 0l ) {
-                                    logger.debug(t.getName() + "离职时间小于培训时间");
-                                    iterator.remove();
-                                }
+                            if (t.getDelFlag() == 9){
+                                iterator.remove();
                             }
                         }
                     }
@@ -306,10 +394,47 @@ public class TTrainingMatrixController extends BaseController {
     public AjaxResult batchAddCompany(@PathVariable Long[] ids) {
         for (int i = 0; i < ids.length; i++) {
             TTrainingMatrix tm = tTrainingMatrixService.selectTTrainingMatrixById(ids[i]);
+            if (tm.getTrainingLevel().equals("14")) {
+                continue;
+            }
             TTrainingCompanylevel tr = new TTrainingCompanylevel();
             tr.setDeptId(tm.getDeptId());
             tr.setCourseCode(tm.getCourseCode());
             tr.setItem(tm.getItem());
+            tr.setFrequency(tm.getFrequency());
+
+            // 根据岗位找出该装置的人员,设置到staffId字段
+            if (tm.getActualpostId() != null && !tm.getActualpostId().trim().isEmpty()) {
+                StringBuilder staffIds = new StringBuilder();
+                TStaffmgr staffmgr = new TStaffmgr();
+                staffmgr.setActualposts(tm.getActualpostId());
+                staffmgr.setDeptId(tm.getDeptId());
+                // 使用不带数据权限的查询方法,避免定时任务权限问题
+                List<TStaffmgr> staffmgrs = tStaffmgrService.selectAllTStaffmgrListWithoutScope(staffmgr);
+
+                // 过滤掉已离职的员工
+                Iterator<TStaffmgr> iterator = staffmgrs.iterator();
+                while (iterator.hasNext()) {
+                    TStaffmgr staff = iterator.next();
+                    if (staff.getDelFlag() == 9) { // 9表示已离职
+                        iterator.remove();
+                    }
+                }
+
+                // 收集员工编号
+                for (TStaffmgr staff : staffmgrs) {
+                    if (staff.getStaffid() != null && !staff.getStaffid().trim().isEmpty()) {
+                        staffIds.append(staff.getStaffid()).append(",");
+                    }
+                }
+
+                // 移除最后的逗号
+                if (staffIds.length() > 0) {
+                    staffIds.setLength(staffIds.length() - 1);
+                    tr.setStaffId(staffIds.toString());
+                }
+            }
+
             Calendar cal = Calendar.getInstance();
             int doInsert = tTrainingCompanylevelService.insertTTrainingCompanylevel(tr);
         }
@@ -388,220 +513,76 @@ public class TTrainingMatrixController extends BaseController {
                             }
                         }
                     } else if (j == 5) {
-                        for (SysDictData actualpost : actualposts) {
-                            if (actualpost.getDictLabel().equals(cellValue.trim())) {
-                                entity.setLecturer(actualpost.getDictValue());
+                        // 处理多选授课人,支持逗号分隔
+                        StringBuilder lecturerBuilder = new StringBuilder();
+                        String[] lecturerNames = cellValue.split(",");
+                        for (String lecturerName : lecturerNames) {
+                            lecturerName = lecturerName.trim();
+                            boolean found = false;
+                            for (SysDictData actualpost : actualposts) {
+                                if (actualpost.getDictLabel().equals(lecturerName)) {
+                                    lecturerBuilder.append(actualpost.getDictLabel()).append(",");
+                                    found = true;
+                                    break;
+                                }
                             }
+                            // 如果在字典中找不到,直接使用输入的名称
+                            if (!found && !lecturerName.isEmpty()) {
+                                lecturerBuilder.append(lecturerName).append(",");
+                            }
+                        }
+                        // 移除最后的逗号
+                        if (lecturerBuilder.length() > 0) {
+                            lecturerBuilder.setLength(lecturerBuilder.length() - 1);
+                            entity.setLecturer(lecturerBuilder.toString());
                         }
                     } else if (j == 6) {
                         entity.setHour(cellValue);
                     } else if (j == 7) {
-                        for (SysDictData actualpost : actualposts) {
-                            if (actualpost.getDictLabel().equals("首席经理")) {
-                                if ("M".equals(cellValue) || "X".equals(cellValue) || "m".equals(cellValue) || "x".equals(cellValue)) {
-                                    actualpostId.append(actualpost.getDictValue()).append(",");
-                                } else if ("(M)".equals(cellValue) || "(X)".equals(cellValue) || "(m)".equals(cellValue) || "(x)".equals(cellValue)||"(M)".equals(cellValue) || "(X)".equals(cellValue) || "(m)".equals(cellValue) || "(x)".equals(cellValue)) {
-                                    designatedOther.append(actualpost.getDictValue()).append(",");
-                                } else if ("I".equals(cellValue) || "i".equals(cellValue)) {
-                                    designatedPosition.append(actualpost.getDictValue()).append(",");
-                                }
-                            }
-                        }
+                        processPositionField("首席经理", cellValue, actualposts, actualpostId, designatedOther, designatedPosition);
                     } else if (j == 8) {
-                        for (SysDictData actualpost : actualposts) {
-                            if (actualpost.getDictLabel().equals("装置经理")) {
-                                if ("M".equals(cellValue) || "X".equals(cellValue) || "m".equals(cellValue) || "x".equals(cellValue)) {
-                                    actualpostId.append(actualpost.getDictValue()).append(",");
-                                } else if ("(M)".equals(cellValue) || "(X)".equals(cellValue) || "(m)".equals(cellValue) || "(x)".equals(cellValue)||"(M)".equals(cellValue) || "(X)".equals(cellValue) || "(m)".equals(cellValue) || "(x)".equals(cellValue)) {
-                                    designatedOther.append(actualpost.getDictValue()).append(",");
-                                } else if ("I".equals(cellValue) || "i".equals(cellValue)) {
-                                    designatedPosition.append(actualpost.getDictValue()).append(",");
-                                }
-                            }
-                        }
+                        processPositionField("首席专家", cellValue, actualposts, actualpostId, designatedOther, designatedPosition);
                     } else if (j == 9) {
-                        for (SysDictData actualpost : actualposts) {
-                            if (actualpost.getDictLabel().equals("资深工程师")) {
-                                if ("M".equals(cellValue) || "X".equals(cellValue) || "m".equals(cellValue) || "x".equals(cellValue)) {
-                                    actualpostId.append(actualpost.getDictValue()).append(",");
-                                } else if ("(M)".equals(cellValue) || "(X)".equals(cellValue) || "(m)".equals(cellValue) || "(x)".equals(cellValue)||"(M)".equals(cellValue) || "(X)".equals(cellValue) || "(m)".equals(cellValue) || "(x)".equals(cellValue)) {
-                                    designatedOther.append(actualpost.getDictValue()).append(",");
-                                } else if ("I".equals(cellValue) || "i".equals(cellValue)) {
-                                    designatedPosition.append(actualpost.getDictValue()).append(",");
-                                }
-                            }
-                        }
+                        processPositionField("装置经理", cellValue, actualposts, actualpostId, designatedOther, designatedPosition);
                     } else if (j == 10) {
-                        for (SysDictData actualpost : actualposts) {
-                            if (actualpost.getDictLabel().equals("生产主管")) {
-                                if ("M".equals(cellValue) || "X".equals(cellValue) || "m".equals(cellValue) || "x".equals(cellValue)) {
-                                    actualpostId.append(actualpost.getDictValue()).append(",");
-                                } else if ("(M)".equals(cellValue) || "(X)".equals(cellValue) || "(m)".equals(cellValue) || "(x)".equals(cellValue)||"(M)".equals(cellValue) || "(X)".equals(cellValue) || "(m)".equals(cellValue) || "(x)".equals(cellValue)) {
-                                    designatedOther.append(actualpost.getDictValue()).append(",");
-                                } else if ("I".equals(cellValue) || "i".equals(cellValue)) {
-                                    designatedPosition.append(actualpost.getDictValue()).append(",");
-                                }
-                            }
-                        }
+                        processPositionField("资深工程师", cellValue, actualposts, actualpostId, designatedOther, designatedPosition);
                     } else if (j == 11) {
-                        for (SysDictData actualpost : actualposts) {
-                            if (actualpost.getDictLabel().equals("片区工长")) {
-                                if ("M".equals(cellValue) || "X".equals(cellValue) || "m".equals(cellValue) || "x".equals(cellValue)) {
-                                    actualpostId.append(actualpost.getDictValue()).append(",");
-                                } else if ("(M)".equals(cellValue) || "(X)".equals(cellValue) || "(m)".equals(cellValue) || "(x)".equals(cellValue)||"(M)".equals(cellValue) || "(X)".equals(cellValue) || "(m)".equals(cellValue) || "(x)".equals(cellValue)) {
-                                    designatedOther.append(actualpost.getDictValue()).append(",");
-                                } else if ("I".equals(cellValue) || "i".equals(cellValue)) {
-                                    designatedPosition.append(actualpost.getDictValue()).append(",");
-                                }
-                            }
-                        }
+                        processPositionField("生产主管", cellValue, actualposts, actualpostId, designatedOther, designatedPosition);
                     } else if (j == 12) {
-                        for (SysDictData actualpost : actualposts) {
-                            if (actualpost.getDictLabel().equals("职员")) {
-                                if ("M".equals(cellValue) || "X".equals(cellValue) || "m".equals(cellValue) || "x".equals(cellValue)) {
-                                    actualpostId.append(actualpost.getDictValue()).append(",");
-                                } else if ("(M)".equals(cellValue) || "(X)".equals(cellValue) || "(m)".equals(cellValue) || "(x)".equals(cellValue)||"(M)".equals(cellValue) || "(X)".equals(cellValue) || "(m)".equals(cellValue) || "(x)".equals(cellValue)) {
-                                    designatedOther.append(actualpost.getDictValue()).append(",");
-                                } else if ("I".equals(cellValue) || "i".equals(cellValue)) {
-                                    designatedPosition.append(actualpost.getDictValue()).append(",");
-                                }
-                            }
-                        }
+                        processPositionField("片区工长", cellValue, actualposts, actualpostId, designatedOther, designatedPosition);
                     } else if (j == 13) {
-                        for (SysDictData actualpost : actualposts) {
-                            if (actualpost.getDictLabel().equals("EHS督导")) {
-                                if ("M".equals(cellValue) || "X".equals(cellValue) || "m".equals(cellValue) || "x".equals(cellValue)) {
-                                    actualpostId.append(actualpost.getDictValue()).append(",");
-                                } else if ("(M)".equals(cellValue) || "(X)".equals(cellValue) || "(m)".equals(cellValue) || "(x)".equals(cellValue)||"(M)".equals(cellValue) || "(X)".equals(cellValue) || "(m)".equals(cellValue) || "(x)".equals(cellValue)) {
-                                    designatedOther.append(actualpost.getDictValue()).append(",");
-                                } else if ("I".equals(cellValue) || "i".equals(cellValue)) {
-                                    designatedPosition.append(actualpost.getDictValue()).append(",");
-                                }
-                            }
-                        }
+                        processPositionField("职员", cellValue, actualposts, actualpostId, designatedOther, designatedPosition);
                     } else if (j == 14) {
-                        for (SysDictData actualpost : actualposts) {
-                            if (actualpost.getDictLabel().equals("倒班班长")) {
-                                if ("M".equals(cellValue) || "X".equals(cellValue) || "m".equals(cellValue) || "x".equals(cellValue)) {
-                                    actualpostId.append(actualpost.getDictValue()).append(",");
-                                } else if ("(M)".equals(cellValue) || "(X)".equals(cellValue) || "(m)".equals(cellValue) || "(x)".equals(cellValue)||"(M)".equals(cellValue) || "(X)".equals(cellValue) || "(m)".equals(cellValue) || "(x)".equals(cellValue)) {
-                                    designatedOther.append(actualpost.getDictValue()).append(",");
-                                } else if ("I".equals(cellValue) || "i".equals(cellValue)) {
-                                    designatedPosition.append(actualpost.getDictValue()).append(",");
-                                }
-                            }
-                        }
+                        processPositionField("安全专员", cellValue, actualposts, actualpostId, designatedOther, designatedPosition);
                     } else if (j == 15) {
-                        for (SysDictData actualpost : actualposts) {
-                            if (actualpost.getDictLabel().equals("倒班副班长")) {
-                                if ("M".equals(cellValue) || "X".equals(cellValue) || "m".equals(cellValue) || "x".equals(cellValue)) {
-                                    actualpostId.append(actualpost.getDictValue()).append(",");
-                                } else if ("(M)".equals(cellValue) || "(X)".equals(cellValue) || "(m)".equals(cellValue) || "(x)".equals(cellValue)||"(M)".equals(cellValue) || "(X)".equals(cellValue) || "(m)".equals(cellValue) || "(x)".equals(cellValue)) {
-                                    designatedOther.append(actualpost.getDictValue()).append(",");
-                                } else if ("I".equals(cellValue) || "i".equals(cellValue)) {
-                                    designatedPosition.append(actualpost.getDictValue()).append(",");
-                                }
-                            }
-                        }
+                        processPositionField("OTS培训专员", cellValue, actualposts, actualpostId, designatedOther, designatedPosition);
                     } else if (j == 16) {
-                        for (SysDictData actualpost : actualposts) {
-                            if (actualpost.getDictLabel().equals("主操")) {
-                                if ("M".equals(cellValue) || "X".equals(cellValue) || "m".equals(cellValue) || "x".equals(cellValue)) {
-                                    actualpostId.append(actualpost.getDictValue()).append(",");
-                                } else if ("(M)".equals(cellValue) || "(X)".equals(cellValue) || "(m)".equals(cellValue) || "(x)".equals(cellValue)||"(M)".equals(cellValue) || "(X)".equals(cellValue) || "(m)".equals(cellValue) || "(x)".equals(cellValue)) {
-                                    designatedOther.append(actualpost.getDictValue()).append(",");
-                                } else if ("I".equals(cellValue) || "i".equals(cellValue)) {
-                                    designatedPosition.append(actualpost.getDictValue()).append(",");
-                                }
-                            }
-                        }
+                        processPositionField("倒班班长", cellValue, actualposts, actualpostId, designatedOther, designatedPosition);
                     } else if (j == 17) {
-                        for (SysDictData actualpost : actualposts) {
-                            if (actualpost.getDictLabel().equals("副操")) {
-                                if ("M".equals(cellValue) || "X".equals(cellValue) || "m".equals(cellValue) || "x".equals(cellValue)) {
-                                    actualpostId.append(actualpost.getDictValue()).append(",");
-                                } else if ("(M)".equals(cellValue) || "(X)".equals(cellValue) || "(m)".equals(cellValue) || "(x)".equals(cellValue)||"(M)".equals(cellValue) || "(X)".equals(cellValue) || "(m)".equals(cellValue) || "(x)".equals(cellValue)) {
-                                    designatedOther.append(actualpost.getDictValue()).append(",");
-                                } else if ("I".equals(cellValue) || "i".equals(cellValue)) {
-                                    designatedPosition.append(actualpost.getDictValue()).append(",");
-                                }
-                            }
-                        }
+                        processPositionField("倒班副班长", cellValue, actualposts, actualpostId, designatedOther, designatedPosition);
                     } else if (j == 18) {
-                        for (SysDictData actualpost : actualposts) {
-                            if (actualpost.getDictLabel().equals("主操(白班)")) {
-                                if ("M".equals(cellValue) || "X".equals(cellValue) || "m".equals(cellValue) || "x".equals(cellValue)) {
-                                    actualpostId.append(actualpost.getDictValue()).append(",");
-                                } else if ("(M)".equals(cellValue) || "(X)".equals(cellValue) || "(m)".equals(cellValue) || "(x)".equals(cellValue)||"(M)".equals(cellValue) || "(X)".equals(cellValue) || "(m)".equals(cellValue) || "(x)".equals(cellValue)) {
-                                    designatedOther.append(actualpost.getDictValue()).append(",");
-                                } else if ("I".equals(cellValue) || "i".equals(cellValue)) {
-                                    designatedPosition.append(actualpost.getDictValue()).append(",");
-                                }
-                            }
-                        }
+                        processPositionField("主操", cellValue, actualposts, actualpostId, designatedOther, designatedPosition);
                     } else if (j == 19) {
-                        for (SysDictData actualpost : actualposts) {
-                            if (actualpost.getDictLabel().equals("机械维修人员")) {
-                                if ("M".equals(cellValue) || "X".equals(cellValue) || "m".equals(cellValue) || "x".equals(cellValue)) {
-                                    actualpostId.append(actualpost.getDictValue()).append(",");
-                                } else if ("(M)".equals(cellValue) || "(X)".equals(cellValue) || "(m)".equals(cellValue) || "(x)".equals(cellValue)||"(M)".equals(cellValue) || "(X)".equals(cellValue) || "(m)".equals(cellValue) || "(x)".equals(cellValue)) {
-                                    designatedOther.append(actualpost.getDictValue()).append(",");
-                                } else if ("I".equals(cellValue) || "i".equals(cellValue)) {
-                                    designatedPosition.append(actualpost.getDictValue()).append(",");
-                                }
-                            }
-                        }
+                        processPositionField("副操", cellValue, actualposts, actualpostId, designatedOther, designatedPosition);
                     } else if (j == 20) {
-                        for (SysDictData actualpost : actualposts) {
-                            if (actualpost.getDictLabel().equals("电仪维修人员")) {
-                                if ("M".equals(cellValue) || "X".equals(cellValue) || "m".equals(cellValue) || "x".equals(cellValue)) {
-                                    actualpostId.append(actualpost.getDictValue()).append(",");
-                                } else if ("(M)".equals(cellValue) || "(X)".equals(cellValue) || "(m)".equals(cellValue) || "(x)".equals(cellValue)||"(M)".equals(cellValue) || "(X)".equals(cellValue) || "(m)".equals(cellValue) || "(x)".equals(cellValue)) {
-                                    designatedOther.append(actualpost.getDictValue()).append(",");
-                                } else if ("I".equals(cellValue) || "i".equals(cellValue)) {
-                                    designatedPosition.append(actualpost.getDictValue()).append(",");
-                                }
-                            }
-                        }
+                        processPositionField("主操(白班)", cellValue, actualposts, actualpostId, designatedOther, designatedPosition);
                     } else if (j == 21) {
-                        for (SysDictData actualpost : actualposts) {
-                            if (actualpost.getDictLabel().equals("实验室人员")) {
-                                if ("M".equals(cellValue) || "X".equals(cellValue) || "m".equals(cellValue) || "x".equals(cellValue)) {
-                                    actualpostId.append(actualpost.getDictValue()).append(",");
-                                } else if ("(M)".equals(cellValue) || "(X)".equals(cellValue) || "(m)".equals(cellValue) || "(x)".equals(cellValue)||"(M)".equals(cellValue) || "(X)".equals(cellValue) || "(m)".equals(cellValue) || "(x)".equals(cellValue)) {
-                                    designatedOther.append(actualpost.getDictValue()).append(",");
-                                } else if ("I".equals(cellValue) || "i".equals(cellValue)) {
-                                    designatedPosition.append(actualpost.getDictValue()).append(",");
-                                }
-                            }
-                        }
+                        processPositionField("机械维修经理", cellValue, actualposts, actualpostId, designatedOther, designatedPosition);
                     } else if (j == 22) {
-                        for (SysDictData actualpost : actualposts) {
-                            if (actualpost.getDictLabel().equals("见习生")) {
-                                if ("M".equals(cellValue) || "X".equals(cellValue) || "m".equals(cellValue) || "x".equals(cellValue)) {
-                                    actualpostId.append(actualpost.getDictValue()).append(",");
-                                } else if ("(M)".equals(cellValue) || "(X)".equals(cellValue) || "(m)".equals(cellValue) || "(x)".equals(cellValue)||"(M)".equals(cellValue) || "(X)".equals(cellValue) || "(m)".equals(cellValue) || "(x)".equals(cellValue)) {
-                                    designatedOther.append(actualpost.getDictValue()).append(",");
-                                } else if ("I".equals(cellValue) || "i".equals(cellValue)) {
-                                    designatedPosition.append(actualpost.getDictValue()).append(",");
-                                }
-                            }
-                        }
+                        processPositionField("机械维修人员", cellValue, actualposts, actualpostId, designatedOther, designatedPosition);
                     } else if (j == 23) {
-                        for (SysDictData actualpost : actualposts) {
-                            if (actualpost.getDictLabel().equals("工程师")) {
-                                if ("M".equals(cellValue) || "X".equals(cellValue) || "m".equals(cellValue) || "x".equals(cellValue)) {
-                                    actualpostId.append(actualpost.getDictValue()).append(",");
-                                } else if ("(M)".equals(cellValue) || "(X)".equals(cellValue) || "(m)".equals(cellValue) || "(x)".equals(cellValue)||"(M)".equals(cellValue) || "(X)".equals(cellValue) || "(m)".equals(cellValue) || "(x)".equals(cellValue)) {
-                                    designatedOther.append(actualpost.getDictValue()).append(",");
-                                } else if ("I".equals(cellValue) || "i".equals(cellValue)) {
-                                    designatedPosition.append(actualpost.getDictValue()).append(",");
-                                }
-                            }
-                        }
+                        processPositionField("电仪维修经理", cellValue, actualposts, actualpostId, designatedOther, designatedPosition);
                     } else if (j == 24) {
-                        entity.setRemarks(cellValue);
+                        processPositionField("电仪维修人员", cellValue, actualposts, actualpostId, designatedOther, designatedPosition);
                     } else if (j == 25) {
+                        processPositionField("工程师", cellValue, actualposts, actualpostId, designatedOther, designatedPosition);
+                    } else if (j == 26) {
+                        processPositionField("见习生", cellValue, actualposts, actualpostId, designatedOther, designatedPosition);
+                    } else if (j == 27) {
+                        processPositionField("实验室人员", cellValue, actualposts, actualpostId, designatedOther, designatedPosition);
+                    } else if (j == 28) {
+                        entity.setRemarks(cellValue);
+                    } else if (j == 29) {
                         for (SysDept d : dept) {
                             if (d.getDeptName().equals(cellValue.trim())) {
                                 entity.setDeptId(d.getDeptId());//部门编号
@@ -649,4 +630,33 @@ public class TTrainingMatrixController extends BaseController {
         logger.info("failRow:" + failRow);
         return AjaxResult.success(String.valueOf(successNumber), failRow);
     }
+
+    /**
+     * 处理岗位字段
+     */
+    private void processPositionField(String positionName, String cellValue, List<SysDictData> actualposts,
+                                    StringBuilder actualpostId, StringBuilder designatedOther, StringBuilder designatedPosition) {
+        boolean found = false;
+        for (SysDictData actualpost : actualposts) {
+            if (actualpost.getDictLabel().equals(positionName)) {
+                found = true;
+                logger.info("找到岗位: {} -> {}, 单元格值: {}", positionName, actualpost.getDictValue(), cellValue);
+                if ("M".equals(cellValue) || "X".equals(cellValue) || "m".equals(cellValue) || "x".equals(cellValue)) {
+                    actualpostId.append(actualpost.getDictValue()).append(",");
+                    logger.info("添加到actualpostId: {}", actualpost.getDictValue());
+                } else if ("(M)".equals(cellValue) || "(X)".equals(cellValue) || "(m)".equals(cellValue) || "(x)".equals(cellValue)||"(M)".equals(cellValue) || "(X)".equals(cellValue) || "(m)".equals(cellValue) || "(x)".equals(cellValue)) {
+                    designatedOther.append(actualpost.getDictValue()).append(",");
+                    logger.info("添加到designatedOther: {}", actualpost.getDictValue());
+                } else if ("I".equals(cellValue) || "i".equals(cellValue)) {
+                    designatedPosition.append(actualpost.getDictValue()).append(",");
+                    logger.info("添加到designatedPosition: {}", actualpost.getDictValue());
+                }
+                break;
+            }
+        }
+        if (!found) {
+            logger.warn("未找到岗位: {}, 可用岗位列表: {}", positionName,
+                actualposts.stream().map(SysDictData::getDictLabel).collect(java.util.stream.Collectors.toList()));
+        }
+    }
 }

+ 2 - 8
master/src/main/java/com/ruoyi/project/training/controller/TTrainingParticipantsController.java

@@ -79,14 +79,8 @@ public class TTrainingParticipantsController extends BaseController
                 Iterator<TStaffmgr> iterator = staffmgrs.iterator();
                 while (iterator.hasNext()) {
                     TStaffmgr t = iterator.next();
-                    if (t.getLeftDate() != null && t.getDelFlag() == 9){
-                        Calendar cal = Calendar.getInstance();
-                        cal.setTime(t.getLeftDate());
-                        Integer year = cal.get(Calendar.YEAR);//获取年
-                        if (year < Integer.parseInt(staffmgr.getLeftYear())) {
-                            logger.debug(t.getName() + "离职年份小于数据");
-                            iterator.remove();
-                        }
+                    if (t.getDelFlag() == 9){
+                        iterator.remove();
                     }
                 }
             }

+ 59 - 1
master/src/main/java/com/ruoyi/project/training/controller/TTrainingbccController.java

@@ -19,6 +19,8 @@ import com.ruoyi.project.plant.domain.TStaffmgr;
 import com.ruoyi.project.plant.service.ITStaffmgrService;
 import com.ruoyi.project.system.domain.SysUser;
 import com.ruoyi.project.system.mapper.SysUserMapper;
+import com.ruoyi.project.document.domain.TPlantproglist;
+import com.ruoyi.project.document.service.ITPlantproglistService;
 import com.ruoyi.project.training.domain.TTrainingbcc;
 import com.ruoyi.project.training.domain.TTrainingbccDevice;
 import com.ruoyi.project.training.mapper.TTrainingbccDeviceMapper;
@@ -61,6 +63,8 @@ public class TTrainingbccController extends BaseController {
     private ITStaffmgrService tStaffmgrService;
     @Autowired
     private SysUserMapper sysUserMapper;
+    @Autowired
+    private ITPlantproglistService tPlantproglistService;
     @Resource
     private OfficeConvertController officeConvertController;
 
@@ -321,7 +325,61 @@ public class TTrainingbccController extends BaseController {
         }
 
         // 准备表格数据和其他参数
-        params.put("course", trainingbcc.getCourse());
+        params.put("course", trainingbcc.getCourse() != null ? trainingbcc.getCourse() : "NA");                    // 培训课程名称
+        params.put("courseid", trainingbcc.getCourseid() != null ? trainingbcc.getCourseid() : "NA");                // 培训材料编号
+        // 处理培训材料版本:通过courseid查询TPlantproglist获取版本号
+        String revision = "NA";
+        if (trainingbcc.getCourseid() != null && !trainingbcc.getCourseid().trim().isEmpty()) {
+            TPlantproglist plantproglist = new TPlantproglist();
+            plantproglist.setFileno(trainingbcc.getCourseid().trim());
+            List<TPlantproglist> plantproglistList = tPlantproglistService.selectTPlantproglistList(plantproglist);
+            if (plantproglistList != null && !plantproglistList.isEmpty()) {
+                TPlantproglist matchedPlantproglist = plantproglistList.get(0);
+                if (matchedPlantproglist.getRevision() != null && !matchedPlantproglist.getRevision().trim().isEmpty()) {
+                    revision = matchedPlantproglist.getRevision();
+                }
+            }
+        }
+        params.put("revision", revision);                                   // 培训材料版本
+        params.put("duration", trainingbcc.getDuration() != null ? trainingbcc.getDuration() : "NA");                // 培训时长
+        params.put("content", trainingbcc.getContent() != null ? trainingbcc.getContent() : "NA");                  // 培训内容
+        
+        // 处理讲师信息:通过员工号查询讲师姓名
+        String trainerNames = "NA";
+        if (trainingbcc.getTrainer() != null && !trainingbcc.getTrainer().trim().isEmpty()) {
+            String[] staffIds = trainingbcc.getTrainer().split(",");
+            StringBuilder trainerNameList = new StringBuilder();
+            for (String staffId : staffIds) {
+                if (staffId.trim().isEmpty()) continue;
+                TStaffmgr staffmgr = tStaffmgrService.selectTStaffmgrByStaffId(staffId.trim());
+                if (staffmgr != null && staffmgr.getName() != null) {
+                    if (trainerNameList.length() > 0) {
+                        trainerNameList.append("、");
+                    }
+                    trainerNameList.append(staffmgr.getName());
+                }
+            }
+            trainerNames = trainerNameList.length() > 0 ? trainerNameList.toString() : "NA";
+        }
+        params.put("trainer", trainerNames);                             // 培训讲师姓名
+        
+        // 处理培训日期:使用斜杠格式 yyyy/MM/dd
+        String courseStartdateStr = "";
+        if (trainingbcc.getCourseStartdate() != null) {
+            String startDate = DateUtils.parseDateToStr("yyyy/MM/dd", trainingbcc.getCourseStartdate());
+            if (trainingbcc.getCourseEnddate() != null) {
+                String endDate = DateUtils.parseDateToStr("yyyy/MM/dd", trainingbcc.getCourseEnddate());
+                // 如果开始和结束日期不同,显示日期范围
+                if (!startDate.equals(endDate)) {
+                    courseStartdateStr = startDate + "-" + endDate;
+                } else {
+                    courseStartdateStr = startDate;
+                }
+            } else {
+                courseStartdateStr = startDate;
+            }
+        }
+        params.put("courseStartdate", courseStartdateStr); // 培训日期
         params.put("table1", tableRenderData);
 
         return params;

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

@@ -153,9 +153,9 @@ public class TElPaperServiceImpl implements ITElPaperService {
     public TElPaper createPaper(TElPaper tElPaper, Long userId) {
         // 查找考试
         TElExam exam = tElExamMapper.selectTElExamById(tElPaper.getExamId());
-//        if (exam.getExamType() == 2 && tElPaper.getDeviceId()==null) { //装置培训
-//            throw new IndexOutOfBoundsException("无法匹配装置培训");
-//        }
+        if (exam.getExamType() == 2 && tElPaper.getDeviceId()==null) { //装置培训
+            throw new IndexOutOfBoundsException("无法匹配装置培训");
+        }
 
         // 考试题目列表
         List<TElPaperQu> paperQuList = new ArrayList<>();
@@ -378,45 +378,98 @@ public class TElPaperServiceImpl implements ITElPaperService {
 
 
         if (exam.getExamType() == 2) { //装置培训考试
+            logger.info("开始处理装置培训考试 - 考试ID: {}, 试卷ID: {}", exam.getExamId(), paper.getExamId());
             new Thread(() -> {
-                TTrainingbcc param = new TTrainingbcc();
-                logger.info("===================" + paper.getExamId());
-                logger.info("++++++++++++++++++++++" + exam.getExamId());
-                param.setExamId(paper.getExamId());
-                List<TTrainingbcc> tTrainingbccList = tTrainingbccMapper.selectTTrainingbccList(param);
-                if (!CollectionUtils.isEmpty(tTrainingbccList)) {
-                    for (TTrainingbcc t : tTrainingbccList
-                    ) {
-                        TTrainingbccDevice device = new TTrainingbccDevice();
-                        device.setRegularId(t.getId());
-                        device.setStaffId(user.getStaffId());
-                        List<TTrainingbccDevice> deviceList = tTrainingbccDeviceMapper.selectTTrainingbccDeviceList(device);
-                        if (!CollectionUtils.isEmpty(deviceList)) {
-                            for (TTrainingbccDevice d : deviceList
-                            ) {
-
-                                long pass;
-                                if (objScore >= paper.getTotalScore()) {
-                                    pass = 1; // 满分情况
-                                    d.setFinishDate(new Date());
-                                } else if (objScore >= paper.getQualifyScore()) {
-                                    pass = 3; // 及格但未满分
-                                    d.setFinishDate(new Date());
-                                } else {
-                                    pass = 0; // 不及格
-                                }
-                                paper.getTotalScore();
-                                d.setExamState(pass);
-                                d.setExamNum(d.getExamNum() + 1);
-                                if (d.getExamNum() >= 5) {
-                                    d.setExamState(-1l);
-                                }
-                                d.setExamDate(new Date());
-                                tTrainingbccDeviceMapper.updateTTrainingbccDevice(d);
-                            }
+                try {
+                    TTrainingbcc param = new TTrainingbcc();
+                    logger.info("创建装置培训查询参数 - 考试ID: {}", paper.getExamId());
+                    param.setExamId(paper.getExamId());
+                    
+                    if (paper.getDeviceId() != null) {
+                        logger.info("开始处理装置培训设备记录 - 设备ID: {}", paper.getDeviceId());
+                        TTrainingbccDevice tTrainingbccDevice = tTrainingbccDeviceMapper.selectTTrainingbccDeviceById(paper.getDeviceId());
+                        
+                        if (tTrainingbccDevice == null) {
+                            logger.warn("未找到装置培训设备记录 - 设备ID: {}", paper.getDeviceId());
+                            return;
+                        }
+                        
+                        logger.info("找到装置培训设备记录 - 设备ID: {}, 当前考试状态: {}, 考试次数: {}", 
+                                   paper.getDeviceId(), tTrainingbccDevice.getExamState(), tTrainingbccDevice.getExamNum());
+                        
+                        long pass;
+                        logger.info("开始判断考试结果 - 实际得分: {}, 总分: {}, 及格分: {}", 
+                                   objScore, paper.getTotalScore(), paper.getQualifyScore());
+                        
+                        if (objScore >= paper.getTotalScore()) {
+                            pass = 1; // 满分情况
+                            logger.info("考试结果: 满分通过 - 得分: {}/{}", objScore, paper.getTotalScore());
+                            tTrainingbccDevice.setFinishDate(new Date());
+                        } else if (objScore >= paper.getQualifyScore()) {
+                            pass = 3; // 及格但未满分
+                            logger.info("考试结果: 及格通过 - 得分: {}/{}", objScore, paper.getTotalScore());
+                            tTrainingbccDevice.setFinishDate(new Date());
+                        } else {
+                            pass = 0; // 不及格
+                            logger.info("考试结果: 不及格 - 得分: {}/{}", objScore, paper.getTotalScore());
                         }
+                        
+                        tTrainingbccDevice.setExamState(pass);
+                        int newExamNum = tTrainingbccDevice.getExamNum() + 1;
+                        tTrainingbccDevice.setExamNum(newExamNum);
+                        
+                        logger.info("更新考试状态和次数 - 新状态: {}, 新次数: {}", pass, newExamNum);
+                        
+                        if (newExamNum >= 5) {
+                            logger.warn("考试次数已达上限(5次),设置状态为-1 - 设备ID: {}", paper.getDeviceId());
+                            tTrainingbccDevice.setExamState(-1l);
+                        }
+                        
+                        tTrainingbccDevice.setExamDate(new Date());
+                        int updateResult = tTrainingbccDeviceMapper.updateTTrainingbccDevice(tTrainingbccDevice);
+                        logger.info("更新装置培训设备记录完成 - 设备ID: {}, 更新结果: {}", paper.getDeviceId(), updateResult);
+                    } else {
+                        logger.warn("装置培训考试缺少设备ID - 考试ID: {}, 试卷ID: {}", exam.getExamId(), paper.getExamId());
                     }
+                } catch (Exception e) {
+                    logger.error("处理装置培训考试时发生异常 - 考试ID: {}, 试卷ID: {}, 错误: {}", 
+                               exam.getExamId(), paper.getExamId(), e.getMessage(), e);
                 }
+                logger.info("装置培训考试处理完成 - 考试ID: {}, 试卷ID: {}", exam.getExamId(), paper.getExamId());
+
+//                List<TTrainingbcc> tTrainingbccList = tTrainingbccMapper.selectTTrainingbccList(param);
+//                if (!CollectionUtils.isEmpty(tTrainingbccList)) {
+//                    for (TTrainingbcc t : tTrainingbccList
+//                    ) {
+//                        TTrainingbccDevice device = new TTrainingbccDevice();
+//                        device.setRegularId(t.getId());
+//                        device.setStaffId(user.getStaffId());
+//                        List<TTrainingbccDevice> deviceList = tTrainingbccDeviceMapper.selectTTrainingbccDeviceList(device);
+//                        if (!CollectionUtils.isEmpty(deviceList)) {
+//                            for (TTrainingbccDevice d : deviceList
+//                            ) {
+//                                long pass;
+//                                if (objScore >= paper.getTotalScore()) {
+//                                    pass = 1; // 满分情况
+//                                    d.setFinishDate(new Date());
+//                                } else if (objScore >= paper.getQualifyScore()) {
+//                                    pass = 3; // 及格但未满分
+//                                    d.setFinishDate(new Date());
+//                                } else {
+//                                    pass = 0; // 不及格
+//                                }
+//                                paper.getTotalScore();
+//                                d.setExamState(pass);
+//                                d.setExamNum(d.getExamNum() + 1);
+//                                if (d.getExamNum() >= 5) {
+//                                    d.setExamState(-1l);
+//                                }
+//                                d.setExamDate(new Date());
+//                                tTrainingbccDeviceMapper.updateTTrainingbccDevice(d);
+//                            }
+//                        }
+//                    }
+//                }
 
             }, "装置培训考试成绩").start();
         } else if (exam.getExamType() == 3) {

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

@@ -81,7 +81,7 @@ spring:
   devtools:
     restart:
       # 热部署开关
-      enabled: true
+      enabled: false
   # redis 配置
   redis:
     # 地址

+ 1 - 1
master/src/main/resources/mybatis/system/SysUserMapper.xml

@@ -294,7 +294,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 
 	<select id="selectUserByStaffId" parameterType="String" resultMap="SysUserResult">
 		<include refid="selectUserVo"/>
-		where u.staffid = #{staffid}
+		where 2 > ROWNUM and u.staffid = #{staffid} and u.del_flag = 0
 	</select>
 
 	<select id="checkUserNameUnique" parameterType="String" resultType="int">

+ 8 - 8
master/src/main/resources/mybatis/training/TTrainingNonMapper.xml

@@ -3,7 +3,7 @@
 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.ruoyi.project.training.mapper.TTrainingNonMapper">
-    
+
     <resultMap type="TTrainingNon" id="TTrainingNonResult">
         <result property="id"    column="id"    />
         <result property="delFlag"    column="del_flag"    />
@@ -30,18 +30,18 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     <select id="selectTTrainingNonList" parameterType="TTrainingNon" resultMap="TTrainingNonResult">
         <include refid="selectTTrainingNonVo"/>
         <where>
-            <if test="staffId != null  and staffId != ''"> and staff_id = #{staffId}</if>
-            <if test="trainingId != null "> and training_id = #{trainingId}</if>
-            <if test="isNew != null  and isNew != ''"> and is_new = #{isNew}</if>
+            <if test="staffId != null  and staffId != ''"> and d.staff_id = #{staffId}</if>
+            <if test="trainingId != null "> and d.training_id = #{trainingId}</if>
+            <if test="isNew != null  and isNew != ''"> and d.is_new = #{isNew}</if>
             and d.del_flag = 0
         </where>
     </select>
-    
+
     <select id="selectTTrainingNonById" parameterType="Long" resultMap="TTrainingNonResult">
         select *  from t_training_non
         where id = #{id}
     </select>
-        
+
     <insert id="insertTTrainingNon" parameterType="TTrainingNon">
         <selectKey keyProperty="id" resultType="long" order="BEFORE">
             SELECT seq_t_training_non.NEXTVAL as id FROM DUAL
@@ -107,5 +107,5 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             #{id}
         </foreach>
     </update>
-    
-</mapper>
+
+</mapper>

BIN
master/src/main/resources/static/template/training/trainingMatrix.xlsx


BIN
master/src/main/resources/static/word/training/signMOC.docx


BIN
master/src/main/resources/static/word/training/signMOCbcc.docx


BIN
master/src/main/resources/static/word/training/signbcc.docx


+ 11 - 2
ui/src/views/training/bccregular/regular.vue

@@ -450,8 +450,17 @@ export default {
     },
     // 判断是否需要隐藏列
     shouldHideColumn(columnLabel) {
-      const hideColumns = ['工程师', '见习生', '机械维修经理', '电仪维修经理'];
-      return hideColumns.some(hideLabel => columnLabel.includes(hideLabel));
+      // 基础隐藏的列
+      const baseHideColumns = ['工程师', '见习生', '机械维修经理', '电仪维修经理'];
+
+      // 如果用户homeType为6,额外隐藏更多列
+      if (this.$store.state.user.homeType == 6) {
+        const additionalHideColumns = ['首席专家', '片区工长', 'OTS培训专员'];
+        const allHideColumns = [...baseHideColumns, ...additionalHideColumns];
+        return allHideColumns.some(hideLabel => columnLabel.includes(hideLabel));
+      }
+
+      return baseHideColumns.some(hideLabel => columnLabel.includes(hideLabel));
     },
     // 获取岗位在原始数组中的索引
     getOriginalIndex(item) {

+ 13 - 0
ui/src/views/training/companylevel/index.vue

@@ -105,6 +105,15 @@
           size="mini"
           @click="handleScore"
         >{{ $t('更新培训成绩') }}</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          icon="el-icon-tickets"
+          size="mini"
+          @click="handleCompany"
+        >{{ $t('公司级培训记录') }}
+        </el-button>
       </el-col>
 	  <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
@@ -421,6 +430,10 @@ export default {
         this.total = response.total;
         this.loading = false;
       });
+    },
+    /** 公司级培训矩阵按钮操作 */
+    handleCompany() {
+      this.$router.push({ path: '/trainingrecords/companyRecords'});
     },
      /** 查询部门下拉树结构 */
      getTreeselect() {

+ 46 - 7
ui/src/views/training/matrix/index.vue

@@ -136,7 +136,7 @@
       </el-table-column>      <el-table-column :label="$t('责任部门')" align="center" prop="responsDept" width="120" min-width="120" :formatter="responsDeptFormat" />
       <el-table-column :label="$t('授课人')" align="center" prop="lecturer" width="100" min-width="100" :formatter="lecturerFormat"/>
       <el-table-column :label="$t('课时')" align="center" prop="hour" width="70" min-width="70"  :show-overflow-tooltip="true"/>
-      <el-table-column v-for="(item, index) in actualpostIdOptions"
+      <el-table-column  v-for="(item, index) in actualpostIdOptions"
                        v-if="!shouldHideColumn(item.dictLabel)"
                        width="150" min-width="150"
                        :label="item.dictLabel"
@@ -146,6 +146,7 @@
           {{scope.row.actualpost[getOriginalIndex(item)]}}
         </template>
       </el-table-column>
+
       <el-table-column :label="$t('备注')" align="center" prop="remarks" width="300" min-width="300" :show-overflow-tooltip="true"/>
       <el-table-column :label="$t('操作')" align="center" fixed="right" width="120" min-width="120" class-name="small-padding fixed-width">
         <template slot-scope="scope">
@@ -223,12 +224,18 @@
           </el-select>
         </el-form-item>
         <el-form-item :label="$t('授课人')" prop="lecturer">
-          <el-select v-model="form.lecturer" :placeholder="$t('请选择') + $t('授课人')">
+          <el-select
+            v-model="lecturerList"
+            multiple
+            filterable
+            allow-create
+            :placeholder="$t('请选择或输入') + $t('授课人')"
+            @change="handleLecturerChange">
             <el-option
               v-for="dict in lecturerOptions"
               :key="dict.dictValue"
               :label="dict.dictLabel"
-              :value="dict.dictValue"
+              :value="dict.dictLabel"
             ></el-option>
           </el-select>
         </el-form-item>
@@ -357,6 +364,8 @@ export default {
       actualpostIdOptions: [],
       // 授课人字典
       lecturerOptions: [],
+      // 授课人多选列表
+      lecturerList: [],
       // 指定岗位字典
       designatedPositionOptions: [],
       // 指定部门字典
@@ -468,7 +477,19 @@ export default {
     },
     // 授课人字典翻译
     lecturerFormat(row, column) {
-      return this.selectDictLabel(this.lecturerOptions, row.lecturer);
+      // 处理多选授课人的显示
+      if (row.lecturer && row.lecturer.includes(',')) {
+        const lecturerNames = row.lecturer.split(',').map(name => name.trim());
+        return lecturerNames.join('、');
+      }
+      // 单个授课人直接显示
+      return row.lecturer || '';
+    },
+    // 处理授课人变化
+    handleLecturerChange(value) {
+      // 过滤空值并去除前后空格
+      const filteredValue = value.filter(item => item && item.trim() !== '').map(item => item.trim());
+      this.form.lecturer = filteredValue.length > 0 ? filteredValue.join(',') : '';
     },
     // 责任部门字典翻译
     responsDeptFormat(row, column) {
@@ -486,8 +507,17 @@ export default {
      },
     // 判断是否需要隐藏列
     shouldHideColumn(columnLabel) {
-      const hideColumns = ['工程师', '见习生', '机械维修经理', '电仪维修经理'];
-      return hideColumns.some(hideLabel => columnLabel.includes(hideLabel));
+      // 基础隐藏的列
+      const baseHideColumns = ['工程师', '见习生', '机械维修经理', '电仪维修经理'];
+
+      // 如果用户homeType为6,额外隐藏更多列
+      if (this.$store.state.user.homeType == 6) {
+        const additionalHideColumns = ['首席专家', '片区工长', 'OTS培训专员'];
+        const allHideColumns = [...baseHideColumns, ...additionalHideColumns];
+        return allHideColumns.some(hideLabel => columnLabel.includes(hideLabel));
+      }
+
+      return baseHideColumns.some(hideLabel => columnLabel.includes(hideLabel));
     },
     // 获取岗位在原始数组中的索引
     getOriginalIndex(item) {
@@ -536,7 +566,7 @@ export default {
     //是否涉及其他部门变动
     changeInvolved() {
        if (this.form.involvedMoc === true) {
-         this.otherPositions = ['28','30','32']
+         this.otherPositions = ['28','30','32','40','42']
        }else {
          this.otherPositions = []
        }
@@ -571,6 +601,8 @@ export default {
         isNewstaff: 0,
         fqYear: 0,
       };
+      // 重置授课人多选列表
+      this.lecturerList = [];
       this.resetForm("form");
     },
     /** 搜索按钮操作 */
@@ -593,6 +625,7 @@ export default {
     handleAdd() {
       this.reset();
       this.actualpostIds = [];
+      this.lecturerList = [];
       this.haveDesignated = false;
       this.designatedPositions = [];
       this.otherPositions = [];
@@ -616,6 +649,12 @@ export default {
         }else {
           this.actualpostIds = [];
         }
+        //授课人显示下拉框内容
+        if (this.form.lecturer != null && this.form.lecturer.trim() !== '') {
+          this.lecturerList = this.form.lecturer.split(',').map(name => name.trim()).filter(name => name !== '');
+        }else {
+          this.lecturerList = [];
+        }
         //指定人员下拉数据
         this.getDicts("ACTUALPOST").then(response => {
           this.designatedPositionOptions = response.data;

+ 11 - 2
ui/src/views/training/regular/index.vue

@@ -473,8 +473,17 @@
       },
       // 判断是否需要隐藏列
       shouldHideColumn(columnLabel) {
-        const hideColumns = ['工程师', '见习生', '机械维修经理', '电仪维修经理'];
-        return hideColumns.some(hideLabel => columnLabel.includes(hideLabel));
+        // 基础隐藏的列
+        const baseHideColumns = ['工程师', '见习生', '机械维修经理', '电仪维修经理'];
+
+        // 如果用户homeType为6,额外隐藏更多列
+        if (this.$store.state.user.homeType == 6) {
+          const additionalHideColumns = ['首席专家', '片区工长', 'OTS培训专员'];
+          const allHideColumns = [...baseHideColumns, ...additionalHideColumns];
+          return allHideColumns.some(hideLabel => columnLabel.includes(hideLabel));
+        }
+
+        return baseHideColumns.some(hideLabel => columnLabel.includes(hideLabel));
       },
       // 获取岗位在原始数组中的索引
       getOriginalIndex(item) {

+ 6 - 1
ui/src/views/training/trainingbcc/index.vue

@@ -282,7 +282,12 @@
         <el-row>
           <el-col :span="12">
             <el-form-item :label="$t('培训内容')" prop="content">
-              <el-input v-model="form.content" :placeholder="$t('请输入') + $t('培训内容')" />
+              <el-input
+                v-model="form.content"
+                type="textarea"
+                :rows="3"
+                :placeholder="$t('请输入') + $t('培训内容')"
+              />
             </el-form-item>
           </el-col>
           <el-col :span="12">