Просмотр исходного кода

feat(hr): 添加高级人才聘任管理和员工评价积分功能

- 在FormConstant中新增序列、任职类型分类、工龄年限常量定义
- 新增ScoreItemLevelEnum、ScoreIteMrankEnum、ScoreItemSubEnum枚举类用于员工评价积分管理
- 修复DateUtil中beginOfYear和endOfYear方法的返回类型问题
- 在EmpPosOrgRelHelper中添加服务年限查询和全职任职经历查询功能
- 新增QFilterCommonHelper用于数据查询过滤器辅助功能
- 更新QFilterPersonHelper使用FormConstant常量进行字符串拼接
- 在ContributionConstant和PositionStructureConstant中添加相关常量定义
- 新增DismissAppointFormPlugin、KeyBeHavEvalListPlugin、NewSeniorAppointFormPlugin等表单插件
- 新增SeniorAppointListPlugin和SeniorAppointMgmtFormPlugin用于高级人才聘任管理
- 在PersonPosFileDeleteOpPlugin中添加聘任状态检查逻辑
- 新增DismissAppointOpPlugin和NewSeniorAppointOpPlugin操作插件实现解聘和聘任功能
wyc 2 недель назад
Родитель
Сommit
deac002696
20 измененных файлов с 1874 добавлено и 9 удалено
  1. 6 0
      code/base/nckd-jxccl-base-common/src/main/java/nckd/jxccl/base/common/constant/FormConstant.java
  2. 68 0
      code/base/nckd-jxccl-base-common/src/main/java/nckd/jxccl/base/common/enums/psms/ScoreIteMrankEnum.java
  3. 68 0
      code/base/nckd-jxccl-base-common/src/main/java/nckd/jxccl/base/common/enums/psms/ScoreItemLevelEnum.java
  4. 85 0
      code/base/nckd-jxccl-base-common/src/main/java/nckd/jxccl/base/common/enums/psms/ScoreItemSubEnum.java
  5. 4 4
      code/base/nckd-jxccl-base-common/src/main/java/nckd/jxccl/base/common/utils/DateUtil.java
  6. 44 0
      code/base/nckd-jxccl-base-helper/src/main/java/nckd/jxccl/base/hrpi/helper/EmpPosOrgRelHelper.java
  7. 21 0
      code/base/nckd-jxccl-base-helper/src/main/java/nckd/jxccl/base/orm/helper/QFilterCommonHelper.java
  8. 2 1
      code/base/nckd-jxccl-base-helper/src/main/java/nckd/jxccl/base/orm/helper/QFilterPersonHelper.java
  9. 2 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/common/ContributionConstant.java
  10. 22 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/common/PositionStructureConstant.java
  11. 44 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/form/other/DismissAppointFormPlugin.java
  12. 71 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/form/other/KeyBeHavEvalListPlugin.java
  13. 55 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/form/other/NewSeniorAppointFormPlugin.java
  14. 75 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/form/other/SeniorAppointListPlugin.java
  15. 82 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/form/other/SeniorAppointMgmtFormPlugin.java
  16. 6 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/operate/file/PersonPosFileDeleteOpPlugin.java
  17. 145 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/operate/other/DismissAppointOpPlugin.java
  18. 174 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/operate/other/NewSeniorAppointOpPlugin.java
  19. 896 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/task/KeyBeHavEvalTask.java
  20. 4 4
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/stm/plugin/form/unitst/UnitStBudgetApplyFormPlugin.java

+ 6 - 0
code/base/nckd-jxccl-base-common/src/main/java/nckd/jxccl/base/common/constant/FormConstant.java

@@ -277,6 +277,8 @@ public class FormConstant {
     public static final String COMPANY_KEY = "company";
     /** 岗位*/
     public static final String POSITION_KEY = "position";
+    /** 序列*/
+    public static final String JOBSEQ_KEY = "jobseq";
     /** 学历*/
     public static final String EDUCATION_KEY = "education";
     /** 职称*/
@@ -364,6 +366,8 @@ public class FormConstant {
     public static final String CHGACTION = "chgaction";
     /** 任职类型*/
     public static final String POSTYPE = "postype";
+    /** 任职类型分类*/
+    public static final String POSTCATEGORY = "postcategory";
     /** 任职状态分类*/
     public static final String POST_STATE_CLS = "poststatecls";
     /** 职位级别*/
@@ -460,5 +464,7 @@ public class FormConstant {
     public static final String NCKD_JOBTJOBTYPMAIN = "nckd_jobtjobtypmain";
     /** 工作性质大类离岗编码 */
     public static final String NCKD_JOBTJOBTYPMAIN_LEAVE_NUMBER = "05";
+    /**工龄年限*/
+    public static final String SOCIALWORKAGE = "socialworkage";
 
 }

+ 68 - 0
code/base/nckd-jxccl-base-common/src/main/java/nckd/jxccl/base/common/enums/psms/ScoreIteMrankEnum.java

@@ -0,0 +1,68 @@
+package nckd.jxccl.base.common.enums.psms;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 员工年度贡献综合评价积分-项目
+ * @author W.Y.C
+ * @date 2025/10/14 10:35
+ * @version 1.0
+ */
+public enum ScoreIteMrankEnum {
+    /**一等奖*/
+    FIRST_PRIZE("01-1", "一等奖"),
+    /**二等奖*/
+    SECOND_PRIZE("01-2", "二等奖"),
+    /**三等奖*/
+    THIRD_PRIZE("01-3", "三等奖"),
+    /**第一名*/
+    FIRST_PLACE("02-1", "第一名"),
+    /**第二名*/
+    SECOND_PLACE("02-2", "第二名"),
+    /**第三名*/
+    THIRD_PLACE("02-3", "第三名");
+
+
+
+    private static final Map<String, ScoreIteMrankEnum> CODE_MAP = new HashMap<>();
+
+    static {
+        for (ScoreIteMrankEnum value : ScoreIteMrankEnum.values()) {
+            CODE_MAP.put(value.code, value);
+        }
+    }
+
+    private final String code;
+    private final String name;
+
+    ScoreIteMrankEnum(String code, String name) {
+        this.code = code;
+        this.name = name;
+    }
+
+    /**
+     * 根据编码获取枚举
+     * @param code
+     * @return: AdjustTypeEnum
+     * @author W.Y.C
+     * @date: 2025/09/12 14:33
+     */
+    public static ScoreIteMrankEnum getByCode(String code) {
+        if (code == null) {
+            return null;
+        }
+        return CODE_MAP.get(code);
+    }
+
+
+
+    public String getCode() {
+        return code;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+}

+ 68 - 0
code/base/nckd-jxccl-base-common/src/main/java/nckd/jxccl/base/common/enums/psms/ScoreItemLevelEnum.java

@@ -0,0 +1,68 @@
+package nckd.jxccl.base.common.enums.psms;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 员工年度贡献综合评价积分-积分项目级别
+ * @author W.Y.C
+ * @date 2025/10/14 10:35
+ * @version 1.0
+ */
+public enum ScoreItemLevelEnum {
+
+    NATIONAL_LEVEL("01", "国家级"),
+    /**省部级*/
+    PROVINCIAL_LEVEL("02", "省部级"),
+    /**公司级*/
+    COMPANY_LEVEL("03", "公司级"),
+    /**厂矿级*/
+    FACTORY_LEVEL("04", "厂矿级"),
+    /**公司青工*/
+    COMPANY_JUNIOR_LEVEL("05", "公司青工"),
+    /**车间级*/
+    WORKSHOP_LEVEL("06", "车间级");
+
+
+
+    private static final Map<String, ScoreItemLevelEnum> CODE_MAP = new HashMap<>();
+
+    static {
+        for (ScoreItemLevelEnum value : ScoreItemLevelEnum.values()) {
+            CODE_MAP.put(value.code, value);
+        }
+    }
+
+    private final String code;
+    private final String name;
+
+    ScoreItemLevelEnum(String code, String name) {
+        this.code = code;
+        this.name = name;
+    }
+
+    /**
+     * 根据编码获取枚举
+     * @param code
+     * @return: AdjustTypeEnum
+     * @author W.Y.C
+     * @date: 2025/09/12 14:33
+     */
+    public static ScoreItemLevelEnum getByCode(String code) {
+        if (code == null) {
+            return null;
+        }
+        return CODE_MAP.get(code);
+    }
+
+
+
+    public String getCode() {
+        return code;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+}

+ 85 - 0
code/base/nckd-jxccl-base-common/src/main/java/nckd/jxccl/base/common/enums/psms/ScoreItemSubEnum.java

@@ -0,0 +1,85 @@
+package nckd.jxccl.base.common.enums.psms;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 员工年度贡献综合评价积分-积分具体项目
+ * @author W.Y.C
+ * @date 2025/10/14 10:35
+ * @version 1.0
+ */
+public enum ScoreItemSubEnum {
+
+    /**技术奖*/
+    TECHNOLOGY_AWARD("01-1", "科技进步、科学技术奖"),
+    TECHNOLOGY_AWARD_2("01-2", "科技进步、科学技术奖"),
+    TECHNOLOGY_AWARD_3("01-3", "科技进步、科学技术奖"),
+    TECHNOLOGY_AWARD_4("01-4", "科技进步、科学技术奖"),
+    /**管理创新奖*/
+    MANAGEMENT_INNOVATION_AWARD("03-1", "管理创新奖"),
+    MANAGEMENT_INNOVATION_AWARD_2("03-2", "管理创新奖"),
+    /**全员创效奖*/
+    EMPLOYEES_CREATIVE_AWARD("04-1", "全员创效奖"),
+    EMPLOYEES_CREATIVE_AWARD_2("04-2", "全员创效奖"),
+    /**党建创新奖励*/
+    PARTY_INNOVATION_AWARD("06-1", "党建创新奖励"),
+    PARTY_INNOVATION_AWARD_2("06-2", "党建创新奖励"),
+    /**专利授权*/
+    PATENT_AUTHORIZATION("07-1", "专利授权"),
+    PATENT_AUTHORIZATION_2("07-2", "发明专利授权"),
+    /**期刊*/
+    JOURNAL("08-1", "国家级期刊"),
+    JOURNAL_2("08-2", "《铜业工程》"),
+    JOURNAL_3("08-3", "省部级期刊"),
+    /**技能竞赛奖*/
+    SKILL_COMPETITION_AWARD("09-1", "技能竞赛奖"),
+    SKILL_COMPETITION_AWARD_2("09-2", "技能竞赛奖"),
+    SKILL_COMPETITION_AWARD_3("09-3", "公司级青工技能竞赛奖"),
+    SKILL_COMPETITION_AWARD_4("09-4", "公司级青工技能竞赛奖"),
+    /**技能竞赛奖*/
+    SKILL_COMPETITION_AWARD_5("09-5", "厂矿级技能竞赛奖");
+
+
+
+    private static final Map<String, ScoreItemSubEnum> CODE_MAP = new HashMap<>();
+
+    static {
+        for (ScoreItemSubEnum value : ScoreItemSubEnum.values()) {
+            CODE_MAP.put(value.code, value);
+        }
+    }
+
+    private final String code;
+    private final String name;
+
+    ScoreItemSubEnum(String code, String name) {
+        this.code = code;
+        this.name = name;
+    }
+
+    /**
+     * 根据编码获取枚举
+     * @param code
+     * @return: AdjustTypeEnum
+     * @author W.Y.C
+     * @date: 2025/09/12 14:33
+     */
+    public static ScoreItemSubEnum getByCode(String code) {
+        if (code == null) {
+            return null;
+        }
+        return CODE_MAP.get(code);
+    }
+
+
+
+    public String getCode() {
+        return code;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+}

+ 4 - 4
code/base/nckd-jxccl-base-common/src/main/java/nckd/jxccl/base/common/utils/DateUtil.java

@@ -447,8 +447,8 @@ public class DateUtil {
      * @param date 日期时间
      * @return 当年第一天 00:00:00
      */
-    public static LocalDateTime beginOfYear(Date date) {
-        return beginOfYear(toLocalDateTime(date));
+    public static Date beginOfYear(Date date) {
+        return toDate(beginOfYear(toLocalDateTime(date)));
     }
     /**
      * 获取年份的开始时间
@@ -512,8 +512,8 @@ public class DateUtil {
      * @param date 日期时间
      * @return 当年最后一天 23:59:59.999999999
      */
-    public static LocalDateTime endOfYear(Date date) {
-        return endOfYear(toLocalDateTime(date));
+    public static Date endOfYear(Date date) {
+        return toDate(endOfYear(toLocalDateTime(date)));
     }
     /**
      * 获取年份结束时间

+ 44 - 0
code/base/nckd-jxccl-base-helper/src/main/java/nckd/jxccl/base/hrpi/helper/EmpPosOrgRelHelper.java

@@ -8,6 +8,7 @@ import kd.bos.orm.query.QFilter;
 import kd.bos.servicehelper.BusinessDataServiceHelper;
 import nckd.jxccl.base.common.constant.FormConstant;
 import nckd.jxccl.base.common.utils.QueryFieldBuilder;
+import nckd.jxccl.base.orm.helper.QFilterCommonHelper;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -26,6 +27,47 @@ import java.util.Map;
  */
 public class EmpPosOrgRelHelper {
 
+    /**
+     * 获取服务年限
+     * @param assignmentIds 组织分配ID
+     * @return: kd.bos.dataentity.entity.DynamicObject[]
+     * @author W.Y.C
+     * @date: 2025/12/25 09:57
+     */
+    public static DynamicObject[] getPerSerLen(Collection<Long> assignmentIds){
+        QFilter queryFilter = QFilterCommonHelper.getIsCurrentData()
+                .and(String.join(".",FormConstant.ASSIGNMENT,FormConstant.ID_KEY),QCP.in,assignmentIds);
+        QueryFieldBuilder queryField = QueryFieldBuilder.create()
+                .addIdNumberName(FormConstant.EMPLOYEE_KEY)
+                .add(FormConstant.FIRSTJOINCOMDATE_KEY)
+                .add(FormConstant.JOINCOMDATE_KEY)
+                .add(FormConstant.STARTDATE)
+                .add(FormConstant.ENDDATE)
+                .add(FormConstant.SOCIALWORKAGE)
+                .orderDesc(FormConstant.CREATE_TIME_KEY,FormConstant.MODIFY_TIME_KEY);
+        return BusinessDataServiceHelper.load(FormConstant.HRPI_PERSERLEN, queryField.buildSelect(),new QFilter[]{queryFilter});
+    }
+    /**
+     * 查询所有“全职任职”和“在岗”的任职经历
+     * @return: kd.bos.dataentity.entity.DynamicObject[]
+     * @author W.Y.C
+     * @date: 2025/12/25 09:47
+     */
+    public static DynamicObject[] allEmpPosOrgRel() {
+        //查询在职人员任职经历
+        QFilter queryFilter = new QFilter(FormConstant.IS_SEQLATESTRECORD, QCP.equals, EnableEnum.YES.getCode())
+                .and(FormConstant.IS_DELETED, QCP.equals, EnableEnum.NO.getCode())
+                .and(FormConstant.IS_PRIMARY, QCP.equals, EnableEnum.YES.getCode())
+                .and(String.join( ".", FormConstant.POSITION_KEY, FormConstant.NCKD_JOBSEQ),QCP.is_notnull,null)
+                //全职任职
+                .and(String.join(".", FormConstant.POSTYPE,FormConstant.POSTCATEGORY,FormConstant.NUMBER_KEY),QCP.equals,"1010_S")
+                //在岗
+                .and(String.join( ".", FormConstant.POS_STATUS, FormConstant.POST_STATE_CLS, FormConstant.NUMBER_KEY),QCP.equals,"1010_S");
+        String selectProperties = selectProperties().buildSelect();
+        String order = selectProperties().buildOrder();
+        return BusinessDataServiceHelper.load(FormConstant.HRPI_EMPPOSORGREL, selectProperties, new QFilter[]{queryFilter}, order);
+    }
+
     //根据id查询任职经历
     public static DynamicObject[] queryEmpPosOrgRelById(Collection<Long> ids) {
         // 构建基础查询条件
@@ -167,6 +209,8 @@ public class EmpPosOrgRelHelper {
                 .addIdNumberName(FormConstant.ADMINORG)
                 // 岗位
                 .addIdNumberName(FormConstant.POSITION_KEY)
+                .addIdNumberName(FormConstant.POSITION_KEY,FormConstant.NCKD_JOBSEQ)
+                .addIdNumberName(FormConstant.ASSIGNMENT)
                 .orderDesc(FormConstant.STARTDATE)
                 .orderDesc(FormConstant.ENDDATE);
     }

+ 21 - 0
code/base/nckd-jxccl-base-helper/src/main/java/nckd/jxccl/base/orm/helper/QFilterCommonHelper.java

@@ -26,6 +26,27 @@ public final class QFilterCommonHelper {
 
     private QFilterCommonHelper() {
     }
+
+    /**
+     * 当前数据QFilter实例
+     * @return: kd.bos.orm.query.QFilter
+     * @author W.Y.C
+     * @date: 2025/07/07 09:20
+     */
+    public static QFilter getIsCurrentData() {
+        return new QFilter(FormConstant.ISCURRENTDATA, QCP.equals, EnableEnum.YES.getCode());
+    }
+
+    /**
+     * 是否删除QFilter实例
+     * @return: kd.bos.orm.query.QFilter
+     * @author W.Y.C
+     * @date: 2025/07/07 09:20
+     */
+    public static QFilter getIsDeleted() {
+        return new QFilter(FormConstant.IS_DELETED, QCP.equals, EnableEnum.NO.getCode());
+    }
+
     /**
      * 获取使用状态为可用的QFilter实例
      * @param

+ 2 - 1
code/base/nckd-jxccl-base-helper/src/main/java/nckd/jxccl/base/orm/helper/QFilterPersonHelper.java

@@ -2,6 +2,7 @@ package nckd.jxccl.base.orm.helper;
 
 import kd.bos.orm.query.QCP;
 import kd.bos.orm.query.QFilter;
+import nckd.jxccl.base.common.constant.FormConstant;
 
 /**
  * QFilter 人员查询辅助类
@@ -12,7 +13,7 @@ import kd.bos.orm.query.QFilter;
 public class QFilterPersonHelper {
 
     /** 组织人关联的任职类型编码(任职类型.任职类型分类.编码)*/
-    private static final String POS_TYPE_POST_CATEGORY_KEY = "postype.postcategory.number";
+    private static final String POS_TYPE_POST_CATEGORY_KEY = String.join(".", FormConstant.POSTYPE,FormConstant.POSTCATEGORY,FormConstant.NUMBER_KEY);
     /**任职类型全职编码*/
     private static final String POST_CATEGORY_OF_STAFF_NUMBER = "1010_S";
 

+ 2 - 0
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/common/ContributionConstant.java

@@ -41,6 +41,8 @@ public class ContributionConstant extends FormConstant {
     public static final String NCKD_SCOREITEMRANK = "nckd_scoreitemrank";
     /** 分录-积分项目名次 */
     public static final String NCKD_SCOREITEMRANKEN = "nckd_scoreitemranken";
+    /** 分录-积分项目级别 */
+    public static final String NCKD_SCOREITEMLEVEL = "nckd_scoreitemlevel";
 
 
 

+ 22 - 0
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/common/PositionStructureConstant.java

@@ -301,4 +301,26 @@ public class PositionStructureConstant extends FormConstant {
     /** 最小职级 */
     public static final String NCKD_MINJOBLEVEL = "nckd_minjoblevel";
     /*-------------------------------------- 职位津贴配置 end --------------------------------------*/
+
+    /** 周期开始年份 */
+    public static final String NCKD_BEGINYEAR = "nckd_beginyear";
+    /** 周期结束年份 */
+    public static final String NCKD_ENDYEAR = "nckd_endyear";
+    /** 人员考评管理分录实体名称 */
+    public static final String NCKD_PERFMANAGERENTRY = "nckd_perfmanagerentry";
+    /** 分录-考核年份 */
+    public static final String NCKD_APPRAISALYEAR = "nckd_appraisalyear";
+
+
+
+    /** 关键行为评价表-实体标识 */
+    public static final String KEYBEHAVEVAL_ENTITYID = "nckd_keybehaveval";
+    /** HR员工 */
+    public static final String NCKD_PERSON = "nckd_person";
+    /** 科研、创新、创效成果 */
+    public static final String NCKD_INNOVATE = "nckd_innovate";
+    /** 工作年限 */
+    public static final String NCKD_WORKYEAR = "nckd_workyear";
+    /** 匹配情况说明 */
+    public static final String NCKD_MATCHCONDDESC = "nckd_matchconddesc";
 }

+ 44 - 0
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/form/other/DismissAppointFormPlugin.java

@@ -0,0 +1,44 @@
+package nckd.jxccl.hr.psms.plugin.form.other;
+
+import kd.bos.form.FormShowParameter;
+import kd.bos.form.events.AfterDoOperationEventArgs;
+import kd.bos.form.plugin.AbstractFormPlugin;
+import kd.sdk.plugin.Plugin;
+import nckd.jxccl.base.common.utils.ConvertUtil;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.EventObject;
+import java.util.List;
+
+/**
+* 高级人才-解聘
+* 实体标识:nckd_dismissappoint
+* @author W.Y.C
+* @date 2025/12/25 20:54
+* @version 1.0
+*/
+public class DismissAppointFormPlugin extends AbstractFormPlugin implements Plugin {
+
+    @Override
+    public void afterBindData(EventObject e) {
+        // 获取当前页面的FormShowParameter对象
+        FormShowParameter showParameter = this.getView().getFormShowParameter();
+        //获取列表选择的数据
+        List<Long> selectRowId = ConvertUtil.toList(showParameter.getCustomParam("ids"));
+        String idsStr = StringUtils.join(selectRowId, ",");
+        this.getModel().setValue("nckd_ids", idsStr);
+        this.getView().updateView("nckd_ids");
+    }
+
+
+    @Override
+    public void afterDoOperation(AfterDoOperationEventArgs e) {
+        if(e.getOperationResult() != null && e.getOperationResult().isSuccess()){
+            String operateKey = e.getOperateKey();
+            if("dismissappointaffirm".equalsIgnoreCase(operateKey)){
+                this.getView().returnDataToParent(Boolean.TRUE);
+                this.getView().close();
+            }
+        }
+    }
+}

+ 71 - 0
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/form/other/KeyBeHavEvalListPlugin.java

@@ -0,0 +1,71 @@
+package nckd.jxccl.hr.psms.plugin.form.other;
+
+import kd.bos.entity.datamodel.ListSelectedRow;
+import kd.bos.entity.datamodel.ListSelectedRowCollection;
+import kd.bos.form.CloseCallBack;
+import kd.bos.form.FormShowParameter;
+import kd.bos.form.ShowType;
+import kd.bos.form.events.AfterDoOperationEventArgs;
+import kd.bos.form.events.ClosedCallBackEvent;
+import kd.bos.list.ListShowParameter;
+import kd.bos.list.events.ListRowClickEvent;
+import kd.bos.list.plugin.AbstractListPlugin;
+import kd.sdk.plugin.Plugin;
+import nckd.jxccl.base.common.constant.FormConstant;
+import nckd.jxccl.hr.psms.common.PositionStructureConstant;
+
+import java.util.EventObject;
+
+/**
+* 关键行为评价表
+* 实体标识:nckd_keybehaveval
+* @author W.Y.C
+* @date 2025/12/25 18:59
+* @version 1.0
+*/
+public class KeyBeHavEvalListPlugin extends AbstractListPlugin implements Plugin {
+
+    @Override
+    public void listRowClick(ListRowClickEvent evt) {
+        // 获取当前点击的行
+        ListSelectedRow currentRow = evt.getCurrentListSelectedRow();
+        // 获取所有选中的行(在已勾选多行的情况下)
+        ListSelectedRowCollection selectedRows = evt.getListSelectedRowCollection();
+        // 后续处理...
+    }
+
+    @Override
+    public void afterCreateNewData(EventObject e) {
+        ListShowParameter listShowParameter = (ListShowParameter)this.getView().getFormShowParameter();
+        listShowParameter.setMultiSelect(false);
+    }
+
+    @Override
+    public void afterDoOperation(AfterDoOperationEventArgs e) {
+        String operateKey = e.getOperateKey();
+        if(e.getOperationResult() != null && e.getOperationResult().isSuccess()){
+            if("newappointment".equalsIgnoreCase(operateKey)) {
+                ListSelectedRowCollection selectedRows = this.getSelectedRows();
+                FormShowParameter showParameter = new FormShowParameter();
+                showParameter.setFormId("nckd_newseniorappoint");
+                showParameter.getOpenStyle().setShowType(ShowType.Modal);
+                showParameter.setCaption("新建聘任");
+                showParameter.setCustomParam("selectRow", selectedRows.get(0).getPrimaryKeyValue());
+                showParameter.setCloseCallBack(new CloseCallBack(this, "nckd_newseniorappoint"));
+                this.getView().showForm(showParameter);
+            }
+            this.getView().invokeOperation(FormConstant.REFRESH_OP);
+        }
+    }
+
+    @Override
+    public void closedCallBack(ClosedCallBackEvent closedCallBackEvent) {
+        String actionId = closedCallBackEvent.getActionId();
+        if("nckd_newseniorappoint".equalsIgnoreCase(actionId)){
+            Object returnData = closedCallBackEvent.getReturnData();
+            if(returnData != null) {
+                this.getView().showSuccessNotification("聘任成功!");
+            }
+        }
+    }
+}

+ 55 - 0
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/form/other/NewSeniorAppointFormPlugin.java

@@ -0,0 +1,55 @@
+package nckd.jxccl.hr.psms.plugin.form.other;
+
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.entity.EntityMetadataCache;
+import kd.bos.entity.MainEntityType;
+import kd.bos.form.FormShowParameter;
+import kd.bos.form.events.AfterDoOperationEventArgs;
+import kd.bos.form.plugin.AbstractFormPlugin;
+import kd.bos.servicehelper.BusinessDataServiceHelper;
+import kd.sdk.plugin.Plugin;
+import nckd.jxccl.base.common.constant.FormConstant;
+import nckd.jxccl.base.common.utils.ConvertUtil;
+import nckd.jxccl.hr.psms.common.PerfRankMgmtConstant;
+import nckd.jxccl.hr.psms.common.PositionStructureConstant;
+
+import java.util.EventObject;
+
+/**
+* 高级人才新建聘任
+* 实体标识:nckd_newseniorappoint
+* @author W.Y.C
+* @date 2025/12/25 19:17
+* @version 1.0
+*/
+public class NewSeniorAppointFormPlugin extends AbstractFormPlugin implements Plugin {
+
+    @Override
+    public void afterBindData(EventObject e) {
+        // 获取当前页面的FormShowParameter对象
+        FormShowParameter showParameter = this.getView().getFormShowParameter();
+        //获取列表选择的人员
+        Long selectRowId = ConvertUtil.toLong(showParameter.getCustomParam("selectRow"));
+        if(selectRowId != null && selectRowId > 0){
+            MainEntityType keyBeHavEvalEntityType = EntityMetadataCache.getDataEntityType(PositionStructureConstant.KEYBEHAVEVAL_ENTITYID);
+            DynamicObject[] load = BusinessDataServiceHelper.load(new Long[]{selectRowId}, keyBeHavEvalEntityType);
+            if(load != null && load.length > 0){
+                DynamicObject dynamicObject = load[0].getDynamicObject(PositionStructureConstant.NCKD_PERSON);
+                this.getModel().setValue(PositionStructureConstant.NCKD_PERSON, dynamicObject);
+                this.getView().updateView(PositionStructureConstant.NCKD_PERSON);
+                this.getView().updateView("nckd_querypropfield");
+            }
+        }
+    }
+
+    @Override
+    public void afterDoOperation(AfterDoOperationEventArgs e) {
+        if(e.getOperationResult() != null && e.getOperationResult().isSuccess()){
+            String operateKey = e.getOperateKey();
+            if("newseniorappoint".equalsIgnoreCase(operateKey)){
+                this.getView().returnDataToParent(Boolean.TRUE);
+                this.getView().close();
+            }
+        }
+    }
+}

+ 75 - 0
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/form/other/SeniorAppointListPlugin.java

@@ -0,0 +1,75 @@
+package nckd.jxccl.hr.psms.plugin.form.other;
+
+import kd.bos.entity.datamodel.ListSelectedRow;
+import kd.bos.entity.datamodel.ListSelectedRowCollection;
+import kd.bos.form.CloseCallBack;
+import kd.bos.form.FormShowParameter;
+import kd.bos.form.ShowType;
+import kd.bos.form.events.AfterDoOperationEventArgs;
+import kd.bos.form.events.ClosedCallBackEvent;
+import kd.bos.form.events.SetFilterEvent;
+import kd.bos.list.plugin.AbstractListPlugin;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
+import kd.sdk.plugin.Plugin;
+import nckd.jxccl.base.common.constant.FormConstant;
+import nckd.jxccl.base.common.enums.psms.TypeStateEnum;
+import nckd.jxccl.base.common.utils.ConvertUtil;
+import nckd.jxccl.hr.psms.common.PositionStructureConstant;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+* 高级人才聘任
+* 实体标识:nckd_mgrappointmgmt
+* @author W.Y.C
+* @date 2025/12/4 18:23
+* @version 1.0
+*/
+public class SeniorAppointListPlugin extends AbstractListPlugin implements Plugin {
+
+    @Override
+    public void setFilter(SetFilterEvent e) {
+        //只查询类型状态
+        QFilter filter = new QFilter(PositionStructureConstant.NCKD_TYPESTATE, QCP.equals, TypeStateEnum.HIGH_PROFESSIONAL_EMPLOYMENT.getCode());
+        e.addCustomQFilter(filter);
+    }
+
+    @Override
+    public void afterDoOperation(AfterDoOperationEventArgs e) {
+        String operateKey = e.getOperateKey();
+        if(e.getOperationResult() != null && e.getOperationResult().isSuccess()){
+            ListSelectedRowCollection selectedRows = this.getSelectedRows();
+            if(selectedRows.isEmpty()){
+                this.getView().showMessage("请选择要解聘的人员");
+                return;
+            }
+            List<Long> ids = new ArrayList<>();
+            for (ListSelectedRow selectedRow : selectedRows) {
+                ids.add(ConvertUtil.toLong(selectedRow.getPrimaryKeyValue()));
+            }
+            if("dismissappoint".equalsIgnoreCase(operateKey)) {
+                FormShowParameter showParameter = new FormShowParameter();
+                showParameter.setFormId("nckd_dismissappoint");
+                showParameter.getOpenStyle().setShowType(ShowType.Modal);
+                showParameter.setCaption("解聘");
+                showParameter.setCustomParam("ids", ids);
+                showParameter.setCloseCallBack(new CloseCallBack(this, "nckd_dismissappoint"));
+                this.getView().showForm(showParameter);
+            }
+        }
+    }
+
+    @Override
+    public void closedCallBack(ClosedCallBackEvent closedCallBackEvent) {
+        String actionId = closedCallBackEvent.getActionId();
+        if("nckd_dismissappoint".equalsIgnoreCase(actionId)){
+            Object returnData = closedCallBackEvent.getReturnData();
+            if(returnData != null) {
+                this.getView().invokeOperation(FormConstant.REFRESH_OP);
+                this.getView().showSuccessNotification("解聘成功!");
+            }
+        }
+    }
+}

+ 82 - 0
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/form/other/SeniorAppointMgmtFormPlugin.java

@@ -0,0 +1,82 @@
+package nckd.jxccl.hr.psms.plugin.form.other;
+
+import kd.bos.form.ShowType;
+import kd.bos.form.container.Tab;
+import kd.bos.form.control.events.TabSelectEvent;
+import kd.bos.form.control.events.TabSelectListener;
+import kd.bos.form.plugin.AbstractFormPlugin;
+import kd.bos.list.ListShowParameter;
+import kd.bos.logging.Log;
+import kd.bos.logging.LogFactory;
+import kd.bos.report.ReportShowParameter;
+import nckd.jxccl.hr.psms.common.PositionStructureConstant;
+
+import java.util.EventObject;
+
+/**
+* 职位体系-高级人才聘任
+* @author W.Y.C
+* @date 2025/10/11 18:28
+* @version 1.0
+*/
+public class SeniorAppointMgmtFormPlugin extends AbstractFormPlugin implements TabSelectListener {
+
+    private final static Log logger = LogFactory.getLog(SeniorAppointMgmtFormPlugin.class);
+
+    @Override
+    public void registerListener(EventObject e) {
+        super.registerListener(e);
+        // 获取页签控件并添加监听
+        Tab tab = (Tab)this.getControl(PositionStructureConstant.NCKD_TABAP);
+        tab.addTabSelectListener(this);
+    }
+
+    @Override
+    public void afterBindData(EventObject e) {
+        //页面加载完成默认打开已生成动态调整列表
+        switchTab();
+    }
+    @Override
+    public void tabSelected(TabSelectEvent tabSelectEvent) {
+        //切换tab页签
+        switchTab();
+
+    }
+
+    /**
+     * 切换页签(根据当前页签焦点加载对应页面)
+     * @param
+     * @return: void
+     * @author W.Y.C
+     * @date: 2025/09/10 17:16
+     */
+    private void switchTab() {
+        Tab tab = (Tab)this.getView().getControl(PositionStructureConstant.NCKD_TABAP);
+        String currentTab = tab.getCurrentTab();
+        if ("nckd_seniorappoint".equalsIgnoreCase(currentTab)) {
+            //打开“聘任人员”列表
+            openTargetPage("nckd_seniorappoint", "nckd_seniorappoint");
+        } else if ("nckd_keybehaveval".equalsIgnoreCase(currentTab)) {
+            //打开“关键行为人员”列表
+            openTargetPage("nckd_keybehaveval","nckd_keybehaveval");
+        }
+    }
+
+    /**
+     * 在页签中打开表单
+     * @param formId 需要打开的表单标识
+     * @param targetKey 目标容器标识
+     * @return: void
+     * @author W.Y.C
+     * @date: 2025/09/10 17:15
+     */
+    private void openTargetPage(String formId, String targetKey) {
+        ListShowParameter parameter = new ListShowParameter();
+        parameter.setBillFormId(formId);
+        // 在容器内打开
+        parameter.getOpenStyle().setShowType(ShowType.InContainer);
+        // 指定页签容器标识
+        parameter.getOpenStyle().setTargetKey(targetKey);
+        this.getView().showForm(parameter);
+    }
+}

+ 6 - 0
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/operate/file/PersonPosFileDeleteOpPlugin.java

@@ -48,6 +48,7 @@ public class PersonPosFileDeleteOpPlugin extends AbstractOperationServicePlugIn
         e.getFieldKeys().add(PositionStructureConstant.NCKD_JOBLEVELHR);
         e.getFieldKeys().add(PositionStructureConstant.NCKD_JOBSEQHR);
         e.getFieldKeys().add(PositionStructureConstant.NCKD_PROTITLELEVEL);
+        e.getFieldKeys().add(PositionStructureConstant.NCKD_EMPLOYMENTSTATUS);
     }
 
     @Override
@@ -75,6 +76,11 @@ public class PersonPosFileDeleteOpPlugin extends AbstractOperationServicePlugIn
                         idMaps.put(id,rowDataEntity.getDataEntityIndex());
                     }else if(typeStateEnum == TypeStateEnum.MANAGEMENT_SEQUENCE_EMPLOYMENT){
 
+                    }else if(typeStateEnum == TypeStateEnum.HIGH_PROFESSIONAL_EMPLOYMENT){
+                        String employmentStatus = data.getString(PositionStructureConstant.NCKD_EMPLOYMENTSTATUS);
+                        if(EnableEnum.YES.getCode().equalsIgnoreCase(employmentStatus)){
+                            this.addFatalErrorMessage(rowDataEntity, StrFormatter.format("【{}】已“聘任”,不能删除", person.getString("name")));
+                        }
                     }
                     else {
                         //其他类型不能置回未生效

+ 145 - 0
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/operate/other/DismissAppointOpPlugin.java

@@ -0,0 +1,145 @@
+package nckd.jxccl.hr.psms.plugin.operate.other;
+
+import com.grapecity.documents.excel.drawing.L;
+import kd.bos.common.enums.EnableEnum;
+import kd.bos.dataentity.OperateOption;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.utils.ObjectUtils;
+import kd.bos.entity.EntityMetadataCache;
+import kd.bos.entity.ExtendedDataEntity;
+import kd.bos.entity.MainEntityType;
+import kd.bos.entity.operate.result.IOperateInfo;
+import kd.bos.entity.operate.result.OperationResult;
+import kd.bos.entity.plugin.AbstractOperationServicePlugIn;
+import kd.bos.entity.plugin.AddValidatorsEventArgs;
+import kd.bos.entity.plugin.PreparePropertysEventArgs;
+import kd.bos.entity.plugin.args.BeginOperationTransactionArgs;
+import kd.bos.entity.validate.AbstractValidator;
+import kd.bos.servicehelper.BusinessDataServiceHelper;
+import kd.bos.servicehelper.operation.SaveServiceHelper;
+import kd.sdk.plugin.Plugin;
+import nckd.jxccl.base.common.constant.FormConstant;
+import nckd.jxccl.base.common.exception.ValidationException;
+import nckd.jxccl.hr.psms.common.PositionStructureConstant;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.StringJoiner;
+import java.util.stream.Collectors;
+
+/**
+* 高级人才聘任-解聘
+* 实体标识:nckd_dismissappoint
+* @author W.Y.C
+* @date 2025/12/25 20:40
+* @version 1.0
+*/
+public class DismissAppointOpPlugin extends AbstractOperationServicePlugIn implements Plugin {
+
+    @Override
+    public void onPreparePropertys(PreparePropertysEventArgs e) {
+        e.getFieldKeys().addAll(this.billEntityType.getAllFields().keySet());
+    }
+
+    @Override
+    public void onAddValidators(AddValidatorsEventArgs e) {
+        e.addValidator(new AbstractValidator() {
+
+            @Override
+            public void validate() {
+                List<Long> ids = new ArrayList<>();
+                for (ExtendedDataEntity dataEntity : getDataEntities()) {
+                    DynamicObject data = dataEntity.getDataEntity();
+                    String idStrs = data.getString("nckd_ids");
+                    List<Long> idList = Arrays.stream(idStrs.split(","))
+                            .filter(StringUtils::isNotBlank)
+                            .map(String::trim)
+                            .map(Long::valueOf)
+                            .collect(Collectors.toList());
+                    ids.addAll(idList);
+                    Date endDate = data.getDate(PositionStructureConstant.NCKD_ENDDATE);
+                    if(endDate == null){
+                        this.addFatalErrorMessage(dataEntity,"请选择解聘时间");
+                    }else{
+                        //聘任结束日期超出当前日期
+                        if(endDate.after(new Date())){
+                            this.addFatalErrorMessage(dataEntity,"解聘时间超出当前日期");
+                        }
+                    }
+                }
+                MainEntityType personPosFileEntityType = EntityMetadataCache.getDataEntityType(PositionStructureConstant.PERSONPOSFILE_ENTITYID);
+                DynamicObject[] personPosFileList = BusinessDataServiceHelper.load(ids.toArray(), personPosFileEntityType);
+                Map<Long, DynamicObject> personPosFileMap = Arrays.stream(personPosFileList)
+                        .collect(Collectors.toMap(
+                                obj -> obj.getLong(FormConstant.ID_KEY), // 以ID作为key
+                                obj -> obj, // 以DynamicObject本身作为value
+                                (existing, replacement) -> existing // 如果有重复key,保留现有的值
+                        ));
+                for (ExtendedDataEntity dataEntity : getDataEntities()) {
+                    DynamicObject data = dataEntity.getDataEntity();
+                    Date endDate = data.getDate(PositionStructureConstant.NCKD_ENDDATE);
+                    if(endDate != null) {
+                        String idStrs = data.getString("nckd_ids");
+                        List<Long> idList = Arrays.stream(idStrs.split(","))
+                                .filter(StringUtils::isNotBlank)
+                                .map(String::trim)
+                                .map(Long::valueOf)
+                                .collect(Collectors.toList());
+                        for (Long l : idList) {
+                            DynamicObject dynamicObject = personPosFileMap.get(l);
+                            Date date = dynamicObject.getDate(PositionStructureConstant.NCKD_BEGINDATE);
+                            //聘任结束日期在聘任开始日期之前
+                            if(endDate.before(date)){
+                                this.addFatalErrorMessage(dataEntity,"聘任结束日期在聘任开始日期之前");
+                            }
+                            String employMentStatus = dynamicObject.getString(PositionStructureConstant.NCKD_EMPLOYMENTSTATUS);
+                            if(!EnableEnum.YES.getCode().equalsIgnoreCase(employMentStatus)){
+                                this.addFatalErrorMessage(dataEntity,"只能对【已聘任】状态记录进行此操作");
+                            }
+                        }
+                    }
+                }
+            }
+        });
+    }
+
+    @Override
+    public void beginOperationTransaction(BeginOperationTransactionArgs e) {
+        Map<Long, Date> idMap = new HashMap<>();
+        for (DynamicObject dataEntity : e.getDataEntities()) {
+            Date endDate = dataEntity.getDate(PositionStructureConstant.NCKD_ENDDATE);
+            String idStrs = dataEntity.getString("nckd_ids");
+            List<Long> idList = Arrays.stream(idStrs.split(","))
+                    .filter(StringUtils::isNotBlank)
+                    .map(String::trim)
+                    .map(Long::valueOf)
+                    .collect(Collectors.toList());
+            for (Long id : idList) {
+                idMap.put(id, endDate);
+            }
+        }
+        MainEntityType personPosFileEntityType = EntityMetadataCache.getDataEntityType(PositionStructureConstant.PERSONPOSFILE_ENTITYID);
+        DynamicObject[] personPosFileList = BusinessDataServiceHelper.load(idMap.keySet().toArray(new Long[0]), personPosFileEntityType);
+        for (DynamicObject personPosFile : personPosFileList) {
+            long id = personPosFile.getLong(FormConstant.ID_KEY);
+            personPosFile.set(PositionStructureConstant.NCKD_EMPLOYMENTSTATUS,EnableEnum.NO.getCode());
+            personPosFile.set(PositionStructureConstant.NCKD_ENDDATE,idMap.get(id));
+        }
+        OperationResult operationResult = SaveServiceHelper.saveOperate(PositionStructureConstant.PERSONPOSFILE_ENTITYID, personPosFileList, OperateOption.create());
+        if (!operationResult.isSuccess()) {
+            StringJoiner errorMsg = new StringJoiner("\n");
+            for (IOperateInfo error : operationResult.getAllErrorOrValidateInfo()) {
+                errorMsg.add(error.getMessage());
+            }
+            if (!ObjectUtils.isEmpty(operationResult.getMessage())) {
+                errorMsg.add(operationResult.getMessage());
+            }
+            throw new ValidationException("解聘高级人才失败,原因:" + errorMsg.toString());
+        }
+    }
+}

+ 174 - 0
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/operate/other/NewSeniorAppointOpPlugin.java

@@ -0,0 +1,174 @@
+package nckd.jxccl.hr.psms.plugin.operate.other;
+
+import kd.bos.common.enums.EnableEnum;
+import kd.bos.context.RequestContext;
+import kd.bos.dataentity.OperateOption;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.dataentity.utils.ObjectUtils;
+import kd.bos.entity.ExtendedDataEntity;
+import kd.bos.entity.constant.StatusEnum;
+import kd.bos.entity.operate.result.IOperateInfo;
+import kd.bos.entity.operate.result.OperationResult;
+import kd.bos.entity.plugin.AbstractOperationServicePlugIn;
+import kd.bos.entity.plugin.AddValidatorsEventArgs;
+import kd.bos.entity.plugin.args.BeginOperationTransactionArgs;
+import kd.bos.entity.validate.AbstractValidator;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
+import kd.bos.servicehelper.QueryServiceHelper;
+import kd.bos.servicehelper.operation.SaveServiceHelper;
+import kd.sdk.plugin.Plugin;
+import nckd.jxccl.base.common.constant.FormConstant;
+import nckd.jxccl.base.common.enums.psms.TypeStateEnum;
+import nckd.jxccl.base.common.exception.ValidationException;
+import nckd.jxccl.base.common.utils.DateUtil;
+import nckd.jxccl.base.common.utils.QueryFieldBuilder;
+import nckd.jxccl.base.entity.helper.EntityHelper;
+import nckd.jxccl.base.hrpi.helper.EmpPosOrgRelHelper;
+import nckd.jxccl.hr.psms.common.PositionStructureConstant;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.StringJoiner;
+import java.util.stream.Collectors;
+
+/**
+* 高级人才新建聘任
+* 实体标识:nckd_newseniorappoint
+* @author W.Y.C
+* @date 2025/12/25 19:28
+* @version 1.0
+*/
+public class NewSeniorAppointOpPlugin extends AbstractOperationServicePlugIn implements Plugin {
+
+    @Override
+    public void onAddValidators(AddValidatorsEventArgs e) {
+        e.addValidator(new AbstractValidator() {
+
+            @Override
+            public void validate() {
+                //员工【吴洁】已存在高级人才聘任
+                //聘任开始日期超出当前日期!请重新操作!
+                List<Long> personIds = new ArrayList<>();
+                for (ExtendedDataEntity dataEntity : getDataEntities()) {
+                    DynamicObject data = dataEntity.getDataEntity();
+                    DynamicObject person = data.getDynamicObject(FormConstant.NCKD_PERSON);
+                    if (person == null) {
+                        this.addFatalErrorMessage(dataEntity,"请填写员工");
+                    }else{
+                        personIds.add(data.getLong(String.join(".", FormConstant.NCKD_PERSON, FormConstant.ID_KEY)));
+                    }
+                    Date beginDate = data.getDate(PositionStructureConstant.NCKD_BEGINDATE);
+                    if(beginDate == null){
+                        this.addFatalErrorMessage(dataEntity,"请填写聘任开始日期");
+                    }
+                    //判断开始日期是否超出当前日期
+                    if (beginDate != null && beginDate.after(new Date())) {
+                        this.addFatalErrorMessage(dataEntity,"聘任开始日期超出当前日期");
+                    }
+
+                }
+
+                QFilter keyFilter = new QFilter(PositionStructureConstant.NCKD_DISABLE, QCP.equals, EnableEnum.NO.getCode())
+                        .and(PositionStructureConstant.NCKD_TYPESTATE,QCP.equals, TypeStateEnum.HIGH_PROFESSIONAL_EMPLOYMENT.getCode())
+                        .and(PositionStructureConstant.NCKD_EMPLOYMENTSTATUS,QCP.equals, EnableEnum.YES.getCode());
+                QueryFieldBuilder keyFieldBuilder = QueryFieldBuilder.create()
+                        .addIdNumberName(PositionStructureConstant.NCKD_PERSON)
+                        .addIdNumberName(PositionStructureConstant.NCKD_JOBSEQHR)
+                        .addIdNumberNameWithExtras(new String[]{PositionStructureConstant.NCKD_JOBLEVELHR},FormConstant.JOBLEVELSEQ)
+                        .add(PositionStructureConstant.NCKD_BEGINDATE)
+                        .orderDesc(PositionStructureConstant.NCKD_BEGINDATE);
+                DynamicObjectCollection keyList = QueryServiceHelper.query(PositionStructureConstant.PERSONPOSFILE_ENTITYID, keyFieldBuilder.buildSelect(), new QFilter[]{keyFilter}, keyFieldBuilder.buildOrder());
+                // 按人员分组,取最新一条记录
+                Map<Long, DynamicObject> keyListLatestMap = keyList.stream()
+                        .collect(Collectors.groupingBy(
+                                obj -> obj.getLong(String.join(".", FormConstant.NCKD_PERSON, FormConstant.ID_KEY)),
+                                Collectors.toList()
+                        ))
+                        .entrySet()
+                        .stream()
+                        .collect(Collectors.toMap(
+                                Map.Entry::getKey,
+                                entry -> entry.getValue().get(0) // 由于已按日期降序排列,取第一条即为最新
+                        ));
+
+                Map<Long, DynamicObject> empPosOrgRelByEmployeesMap = EmpPosOrgRelHelper.queryEmpPosOrgRelByEmployeesMap(personIds);
+                for (ExtendedDataEntity dataEntity : getDataEntities()) {
+                    DynamicObject data = dataEntity.getDataEntity();
+                    DynamicObject person = data.getDynamicObject(FormConstant.NCKD_PERSON);
+                    if (person != null)  {
+                        long personId = data.getLong(String.join(".", FormConstant.NCKD_PERSON, FormConstant.ID_KEY));
+                        DynamicObject latest = keyListLatestMap.get(personId);
+                        if (latest != null) {
+                            this.addFatalErrorMessage(dataEntity, "员工【" + data.getString(String.join(".", FormConstant.NCKD_PERSON, FormConstant.NAME_KEY)) + "】已存在高级人才聘任");
+                        }
+                        DynamicObject empPosOrgRel = empPosOrgRelByEmployeesMap.get(personId);
+                        if (empPosOrgRel == null) {
+                            this.addFatalErrorMessage(dataEntity, "员工【" + data.getString(String.join(".", FormConstant.NCKD_PERSON, FormConstant.NAME_KEY)) + "】不存在任职信息");
+                        } else {
+                            DynamicObject position = empPosOrgRel.getDynamicObject(FormConstant.POSITION_KEY);
+                            if (position == null) {
+                                this.addFatalErrorMessage(dataEntity, "员工【" + data.getString(String.join(".", FormConstant.NCKD_PERSON, FormConstant.NAME_KEY)) + "】不存在职位信息");
+                            } else {
+                                DynamicObject jobSeq = position.getDynamicObject(FormConstant.NCKD_JOBSEQ);
+                                if (jobSeq == null) {
+                                    this.addFatalErrorMessage(dataEntity, "员工【" + data.getString(String.join(".", FormConstant.NCKD_PERSON, FormConstant.NAME_KEY)) + "】不存在职位序列");
+                                }
+
+                            }
+                        }
+                    }
+                }
+            }
+        });
+    }
+
+    @Override
+    public void beginOperationTransaction(BeginOperationTransactionArgs e) {
+
+        List<Long> personIds = new ArrayList<>();
+        for (DynamicObject dataEntity : e.getDataEntities()) {
+            long personId = dataEntity.getLong(String.join(".", FormConstant.NCKD_PERSON, FormConstant.ID_KEY));
+            personIds.add(personId);
+        }
+        Map<Long, DynamicObject> empPosOrgRelByEmployeesMap = EmpPosOrgRelHelper.queryEmpPosOrgRelByEmployeesMap(personIds);
+        List<DynamicObject> saveDynamicObjectList = new ArrayList<>();
+        for (DynamicObject dataEntity : e.getDataEntities()) {
+            Date beginDate = dataEntity.getDate(PositionStructureConstant.NCKD_BEGINDATE);
+            long personId = dataEntity.getLong(String.join(".", FormConstant.NCKD_PERSON, FormConstant.ID_KEY));
+            DynamicObject empPosOrgRel = empPosOrgRelByEmployeesMap.get(personId);
+            DynamicObject newPersonPosFile = EntityHelper.newEntity(PositionStructureConstant.PERSONPOSFILE_ENTITYID);
+            newPersonPosFile.set(PositionStructureConstant.NCKD_PERSON, dataEntity.getDynamicObject(FormConstant.NCKD_PERSON));
+            newPersonPosFile.set(PositionStructureConstant.NCKD_FIRSTRANK, EnableEnum.YES.getCode());
+            newPersonPosFile.set(PositionStructureConstant.NCKD_BEGINDATE, beginDate);
+            DynamicObject position = empPosOrgRel.getDynamicObject(FormConstant.POSITION_KEY);
+            DynamicObject jobSeq = position.getDynamicObject(FormConstant.NCKD_JOBSEQ);
+            newPersonPosFile.set(PositionStructureConstant.NCKD_JOBSEQHR, jobSeq);
+            newPersonPosFile.set(PositionStructureConstant.NCKD_POSITIONHR, position);
+            newPersonPosFile.set(PositionStructureConstant.NCKD_DEP, empPosOrgRel.getDynamicObject(FormConstant.ADMINORG));
+            newPersonPosFile.set(PositionStructureConstant.NCKD_JOBLEVELHR, dataEntity.getDynamicObject(PositionStructureConstant.NCKD_JOBLEVELHR));
+            newPersonPosFile.set(PositionStructureConstant.NCKD_TYPESTATE, TypeStateEnum.HIGH_PROFESSIONAL_EMPLOYMENT.getCode());
+            newPersonPosFile.set(PositionStructureConstant.NCKD_EXECUTEYEAR, DateUtil.getYear(beginDate));
+            newPersonPosFile.set(PositionStructureConstant.NCKD_EMPLOYMENTSTATUS, EnableEnum.YES.getCode());
+            newPersonPosFile.set(PositionStructureConstant.NCKD_DISABLE, EnableEnum.NO.getCode());
+            newPersonPosFile.set(PositionStructureConstant.STATUS, StatusEnum.C.toString());
+            newPersonPosFile.set(PositionStructureConstant.ENABLE, EnableEnum.YES.getCode());
+            newPersonPosFile.set(PositionStructureConstant.CREATOR_KEY, RequestContext.get().getCurrUserId());
+            saveDynamicObjectList.add(newPersonPosFile);
+        }
+        OperationResult operationResult = SaveServiceHelper.saveOperate(PositionStructureConstant.PERSONPOSFILE_ENTITYID, saveDynamicObjectList.toArray(new DynamicObject[0]), OperateOption.create());
+        if (!operationResult.isSuccess()) {
+            StringJoiner errorMsg = new StringJoiner("\n");
+            for (IOperateInfo error : operationResult.getAllErrorOrValidateInfo()) {
+                errorMsg.add(error.getMessage());
+            }
+            if (!ObjectUtils.isEmpty(operationResult.getMessage())) {
+                errorMsg.add(operationResult.getMessage());
+            }
+            throw new ValidationException("聘任高级人才失败,原因:" + errorMsg.toString());
+        }
+    }
+}

+ 896 - 0
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/task/KeyBeHavEvalTask.java

@@ -0,0 +1,896 @@
+package nckd.jxccl.hr.psms.task;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+import kd.bos.common.enums.EnableEnum;
+import kd.bos.context.RequestContext;
+import kd.bos.dataentity.OperateOption;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.dataentity.utils.ObjectUtils;
+import kd.bos.db.tx.TX;
+import kd.bos.db.tx.TXHandle;
+import kd.bos.entity.EntityMetadataCache;
+import kd.bos.entity.MainEntityType;
+import kd.bos.entity.QueryEntityType;
+import kd.bos.entity.constant.StatusEnum;
+import kd.bos.entity.operate.result.IOperateInfo;
+import kd.bos.entity.operate.result.OperationResult;
+import kd.bos.exception.KDException;
+import kd.bos.logging.Log;
+import kd.bos.logging.LogFactory;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
+import kd.bos.schedule.executor.AbstractTask;
+import kd.bos.servicehelper.BusinessDataServiceHelper;
+import kd.bos.servicehelper.QueryServiceHelper;
+import kd.bos.servicehelper.operation.DeleteServiceHelper;
+import kd.bos.servicehelper.operation.SaveServiceHelper;
+import kd.hr.hbp.business.servicehelper.HRQueryEntityHelper;
+import kd.sdk.plugin.Plugin;
+import nckd.jxccl.base.common.constant.FormConstant;
+import nckd.jxccl.base.common.enums.AppraisalResultEnum;
+import nckd.jxccl.base.common.enums.psms.JobSeqEnum;
+import nckd.jxccl.base.common.enums.psms.ScoreIteMrankEnum;
+import nckd.jxccl.base.common.enums.psms.ScoreItemEnum;
+import nckd.jxccl.base.common.enums.psms.ScoreItemLevelEnum;
+import nckd.jxccl.base.common.enums.psms.ScoreItemSubEnum;
+import nckd.jxccl.base.common.enums.psms.TypeStateEnum;
+import nckd.jxccl.base.common.exception.ValidationException;
+import nckd.jxccl.base.common.utils.DateUtil;
+import nckd.jxccl.base.common.utils.QueryFieldBuilder;
+import nckd.jxccl.base.common.utils.StrFormatter;
+import nckd.jxccl.base.entity.helper.EntityHelper;
+import nckd.jxccl.base.hrpi.helper.EmpPosOrgRelHelper;
+import nckd.jxccl.base.orm.helper.QFilterCommonHelper;
+import nckd.jxccl.base.orm.helper.QFilterPersonHelper;
+import nckd.jxccl.hr.hstu.plugin.operate.EvalQuestGenerateQuestOperationPlugin;
+import nckd.jxccl.hr.psms.common.ContributionConstant;
+import nckd.jxccl.hr.psms.common.PositionStructureConstant;
+import org.apache.commons.lang3.StringUtils;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.time.LocalDate;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.StringJoiner;
+import java.util.stream.Collectors;
+
+/**
+* 关键行为评价定时任务
+* @author W.Y.C
+* @date 2025/12/24 17:28
+* @version 1.0
+*/
+public class KeyBeHavEvalTask extends AbstractTask implements Plugin {
+
+    private static final Log logger = LogFactory.getLog(KeyBeHavEvalTask.class);
+
+    public final static Map<String,List<Integer>> jobSeqJobLevelMap = ImmutableMap.<String, List<Integer>>builder()
+            .put(JobSeqEnum.TECHNICALS.getCode(), Lists.newArrayList(13,14,15))
+            .put(JobSeqEnum.FUNCTIONAL.getCode(), Lists.newArrayList(13,14,15))
+            .put(JobSeqEnum.SKILL.getCode(), Lists.newArrayList(12,13,14))
+            .build();
+
+    @Override
+    public void execute(RequestContext requestContext, Map<String, Object> map) throws KDException {
+        logger.info("开始执行关键行为评价定时任务");
+
+        //查询所有员工
+        logger.info("开始查询所有员工信息");
+        DynamicObject[] empPosOrgRelArray = EmpPosOrgRelHelper.allEmpPosOrgRel();
+        if(empPosOrgRelArray == null || empPosOrgRelArray.length == 0){
+            logger.warn("未查询到员工信息,任务结束");
+            return;
+        }
+        logger.info("查询到员工信息总数: {}", empPosOrgRelArray.length);
+        List<Long> personIds = Arrays.stream(empPosOrgRelArray).map(empPosOrgRel -> empPosOrgRel.getLong(String.join(".", FormConstant.EMPLOYEE_KEY, FormConstant.ID_KEY))).collect(Collectors.toList());
+        List<Long> assignmentIds = Arrays.stream(empPosOrgRelArray).map(empPosOrgRel -> empPosOrgRel.getLong(String.join(".", FormConstant.ASSIGNMENT, FormConstant.ID_KEY))).collect(Collectors.toList());
+        logger.info("员工ID数量: {}, 职务ID数量: {}", personIds.size(), assignmentIds.size());
+        Map<Long, DynamicObject> empPosOrgRelMap = Arrays.stream(empPosOrgRelArray)
+                .collect(Collectors.groupingBy(
+                        obj -> obj.getLong(String.join(".", FormConstant.EMPLOYEE_KEY, FormConstant.ID_KEY)),
+                        Collectors.collectingAndThen(
+                                Collectors.toList(),
+                                list -> list.isEmpty() ? null : list.get(0) // 取第一个,即最新记录
+                        )
+                ));
+        logger.info("员工信息分组完成,分组后Map大小: {}", empPosOrgRelMap.size());
+
+        //查询服务年限
+        logger.info("开始查询服务年限,查询职务数量: {}", assignmentIds.size());
+        DynamicObject[] perSerLenArray = EmpPosOrgRelHelper.getPerSerLen(assignmentIds);
+        logger.info("查询到服务年限数据数量: {}", perSerLenArray != null ? perSerLenArray.length : 0);
+        Map<Long, DynamicObject> perSerLenMap = Arrays.stream(perSerLenArray)
+                .collect(Collectors.groupingBy(
+                        obj -> obj.getLong(String.join(".", FormConstant.EMPLOYEE_KEY, FormConstant.ID_KEY)),
+                        Collectors.toList()
+                ))
+                .entrySet()
+                .stream()
+                .collect(Collectors.toMap(
+                        Map.Entry::getKey,
+                        entry -> entry.getValue().get(0) // 由于已按日期降序排列,取第一条即为
+                ));
+        logger.info("服务年限数据分组完成,分组后Map大小: {}", perSerLenMap.size());
+
+        //查询职位档案
+        logger.info("开始查询职位档案,员工数量: {}", personIds.size());
+        QFilter personPosFileFilter = new QFilter(PositionStructureConstant.NCKD_DISABLE, QCP.equals, EnableEnum.NO.getCode())
+                .and(PositionStructureConstant.NCKD_TYPESTATE, QCP.in, new String[]{TypeStateEnum.NEW_ENTRY.getCode(),TypeStateEnum.IN_SERVICE_LEVEL.getCode(),TypeStateEnum.ANNUAL_ADJUSTMENT.getCode(),TypeStateEnum.POSITION_TRANSFER.getCode()})
+                .and(String.join(".", FormConstant.NCKD_PERSON, FormConstant.ID_KEY),QCP.in,personIds);
+        QueryFieldBuilder personPosFileFieldBuilder = QueryFieldBuilder.create()
+                .addIdNumberName(PositionStructureConstant.NCKD_PERSON)
+                .addIdNumberName(PositionStructureConstant.NCKD_JOBSEQHR)
+                .addIdNumberNameWithExtras(new String[]{PositionStructureConstant.NCKD_JOBLEVELHR},FormConstant.JOBLEVELSEQ)
+                .add(PositionStructureConstant.NCKD_BEGINDATE)
+                .orderDesc(PositionStructureConstant.NCKD_BEGINDATE);
+        DynamicObjectCollection personPosFileList = QueryServiceHelper.query(PositionStructureConstant.PERSONPOSFILE_ENTITYID, personPosFileFieldBuilder.buildSelect(), new QFilter[]{personPosFileFilter}, personPosFileFieldBuilder.buildOrder());
+        logger.info("职位档案查询完成,查询结果数量: {}", personPosFileList.size());
+        // 按人员分组,取最新一条记录
+        Map<Long, DynamicObject> personPosLatestMap = personPosFileList.stream()
+                .collect(Collectors.groupingBy(
+                        obj -> obj.getLong(String.join(".", FormConstant.NCKD_PERSON, FormConstant.ID_KEY)),
+                        Collectors.toList()
+                ))
+                .entrySet()
+                .stream()
+                .collect(Collectors.toMap(
+                        Map.Entry::getKey,
+                        entry -> entry.getValue().get(0) // 由于已按日期降序排列,取第一条即为最新
+                ));
+        logger.info("职位档案分组完成,分组后Map大小: {}", personPosLatestMap.size());
+
+
+
+        //查询近3年考核结果
+        logger.info("开始查询近3年考核结果");
+        int threeYearsAgo = LocalDate.now().minusYears(2).getYear();
+        Date beginDate = DateUtil.toDate(LocalDate.of(threeYearsAgo, 1, 1));
+        int currentYear = LocalDate.now().getYear();
+        Date endDate = DateUtil.endOfYear(DateUtil.toDate(LocalDate.of(currentYear, 1, 1)));
+        logger.info("考核结果查询时间范围: {} 到 {}", DateUtil.getYear(beginDate), DateUtil.getYear(endDate));
+        //查询最近3年的数据
+        QFilter perfManagerFilter = new QFilter(PositionStructureConstant.NCKD_BEGINYEAR, QCP.less_equals, endDate)
+                .and(new QFilter(PositionStructureConstant.NCKD_ENDYEAR, QCP.large_equals, beginDate))
+                .and(String.join(".",FormConstant.NCKD_PERSON,FormConstant.ID_KEY), QCP.in, personIds);
+        QueryFieldBuilder perfManagerQueryField = QueryFieldBuilder.create()
+                .addIdNumberName(PositionStructureConstant.NCKD_PERSON)
+                .add(PositionStructureConstant.NCKD_PERFMANAGERENTRY,PositionStructureConstant.NCKD_APPRAISALYEAR)
+                .addIdNumberName(PositionStructureConstant.NCKD_PERFMANAGERENTRY,PositionStructureConstant.NCKD_APPRAISALRESULT);
+        DynamicObjectCollection perfManagerColl = QueryServiceHelper.query(PositionStructureConstant.PERFMANAGER_ENTITYID, perfManagerQueryField.buildSelect(), new QFilter[]{perfManagerFilter}, perfManagerQueryField.buildOrder());
+        logger.info("考核结果查询完成,查询结果数量: {}", perfManagerColl.size());
+        Map<Long, List<DynamicObject>> perfManagerResultMap = perfManagerColl.stream()
+                .collect(Collectors.groupingBy(obj ->
+                        obj.getLong(String.join(".", FormConstant.NCKD_PERSON, FormConstant.ID_KEY))
+                ));
+        logger.info("考核结果分组完成,分组后Map大小: {}", perfManagerResultMap.size());
+
+        //查询近3年科研创新积分
+        logger.info("开始查询近3年科研创新积分");
+        QFilter contribBillFilter = QFilterCommonHelper.getBillStatusFilter()
+                .and(ContributionConstant.NCKD_YEAR,QCP.large_equals,beginDate)
+                .and(ContributionConstant.NCKD_YEAR,QCP.less_equals, endDate)
+                .and(String.join( ".",FormConstant.NCKD_ENTRYENTITY, ContributionConstant.NCKD_PERSON),QCP.in,personIds)
+                .and(String.join( ".",ContributionConstant.NCKD_SCOREITEM, FormConstant.NUMBER_KEY),QCP.equals, ScoreItemEnum.RESEARCH_SCORE.getCode());
+        QueryFieldBuilder scoreItemConfFieldBuilder = QueryFieldBuilder.create()
+                .add(ContributionConstant.NCKD_YEAR)
+                .addIdNumberName(ContributionConstant.NCKD_SCOREITEM)
+                .addIdNumberName(ContributionConstant.NCKD_SCOREITEMSUB)
+                .addIdNumberName(ContributionConstant.NCKD_SCOREITEMSUB, ContributionConstant.NCKD_SCOREITEMLEVEL)
+                .addIdNumberName(ContributionConstant.NCKD_SCOREITEMRANK) // 添加积分项目名次字段
+                .addIdNumberName(FormConstant.NCKD_ENTRYENTITY, ContributionConstant.NCKD_PERSON);
+        DynamicObjectCollection contribBillList = QueryServiceHelper.query(ContributionConstant.CONTRIBBILL_ENTITYID, scoreItemConfFieldBuilder.buildSelect(), new QFilter[]{contribBillFilter}, scoreItemConfFieldBuilder.buildOrder());
+        logger.info("科研创新积分查询完成,查询结果数量: {}", contribBillList.size());
+        Map<Long, List<DynamicObject>> contribMap = contribBillList.stream()
+                .collect(Collectors.groupingBy(obj ->
+                        obj.getLong(String.join(".",FormConstant.NCKD_ENTRYENTITY, FormConstant.NCKD_PERSON, FormConstant.ID_KEY))
+                ));
+        logger.info("科研创新积分分组完成,分组后Map大小: {}", contribMap.size());
+
+        //查询当前已聘任的高级人才
+        logger.info("开始查询当前已聘任的高级人才");
+        QFilter keyFilter = new QFilter(PositionStructureConstant.NCKD_DISABLE, QCP.equals, EnableEnum.NO.getCode())
+                .and(PositionStructureConstant.NCKD_TYPESTATE,QCP.equals, TypeStateEnum.HIGH_PROFESSIONAL_EMPLOYMENT.getCode());
+        QueryFieldBuilder keyFieldBuilder = QueryFieldBuilder.create()
+                .addIdNumberName(PositionStructureConstant.NCKD_PERSON)
+                .addIdNumberName(PositionStructureConstant.NCKD_JOBSEQHR)
+                .addIdNumberNameWithExtras(new String[]{PositionStructureConstant.NCKD_JOBLEVELHR},FormConstant.JOBLEVELSEQ)
+                .add(PositionStructureConstant.NCKD_BEGINDATE)
+                .orderDesc(PositionStructureConstant.NCKD_BEGINDATE);
+        DynamicObjectCollection keyList = QueryServiceHelper.query(PositionStructureConstant.PERSONPOSFILE_ENTITYID, keyFieldBuilder.buildSelect(), new QFilter[]{keyFilter}, keyFieldBuilder.buildOrder());
+        logger.info("高级人才查询完成,查询结果数量: {}", keyList.size());
+        // 按人员分组,取最新一条记录
+        Map<Long, DynamicObject> keyListLatestMap = keyList.stream()
+                .collect(Collectors.groupingBy(
+                        obj -> obj.getLong(String.join(".", FormConstant.NCKD_PERSON, FormConstant.ID_KEY)),
+                        Collectors.toList()
+                ))
+                .entrySet()
+                .stream()
+                .collect(Collectors.toMap(
+                        Map.Entry::getKey,
+                        entry -> entry.getValue().get(0) // 由于已按日期降序排列,取第一条即为最新
+                ));
+        logger.info("高级人才分组完成,分组后Map大小: {}", keyListLatestMap.size());
+
+        //开始
+        logger.info("开始处理员工数据,总员工数: {}", empPosOrgRelMap.size());
+        List<DynamicObject> saveKeyBeHavEval = new ArrayList<>();
+        int processedCount = 0;
+        for (DynamicObject person : empPosOrgRelMap.values()) {
+            long personId = person.getLong(String.join(".", FormConstant.EMPLOYEE_KEY, FormConstant.ID_KEY));
+            logger.debug("处理员工ID: {}", personId);
+            DynamicObject personPosFile = personPosLatestMap.get(personId);
+            int jobLevelSeq = -2;
+            String jobSeqNumber = null;
+            DynamicObject jobSeqObj = null;
+            if(personPosFile == null){
+                continue;
+                /*DynamicObject position = person.getDynamicObject(FormConstant.POSITION_KEY);
+                if(position != null) {
+                    jobSeqObj = position.getDynamicObject(FormConstant.NCKD_JOBSEQ);
+                    if(jobSeqObj != null) {
+                        jobSeqNumber = jobSeqObj.getString(FormConstant.NUMBER_KEY);
+                    }
+                }*/
+            }else{
+                jobLevelSeq = personPosFile.getInt(String.join(".", PositionStructureConstant.NCKD_JOBLEVELHR, FormConstant.JOBLEVELSEQ));
+                jobSeqNumber = personPosFile.getString(String.join(".", PositionStructureConstant.NCKD_JOBSEQHR, FormConstant.NUMBER_KEY));
+                long jobSeqId = personPosFile.getLong(String.join(".", PositionStructureConstant.NCKD_JOBSEQHR, FormConstant.ID_KEY));
+                jobSeqObj = EntityHelper.newEntity(FormConstant.HBJM_JOBSEQHR,jobSeqId);
+            }
+            if(StringUtils.isBlank(jobSeqNumber)){
+                logger.debug("员工ID {} 的职位序列号为空,跳过处理", personId);
+                continue;
+            }
+            DynamicObject perSerLe = perSerLenMap.get(personId);
+            BigDecimal socialWorkAge = perSerLe != null ? perSerLe.getBigDecimal(FormConstant.SOCIALWORKAGE) : BigDecimal.ZERO;
+            DynamicObject keyDynObj = keyListLatestMap.get(personId);
+            //当前高级人才聘任的职级
+            int keyJobLevelSeq = 0;
+            if(keyDynObj != null){
+                keyJobLevelSeq = keyDynObj.getInt(String.join(".", PositionStructureConstant.NCKD_JOBLEVELHR, FormConstant.JOBLEVELSEQ));
+            }
+            logger.debug("员工ID: {}, 职位序列号: {}, 当前职级: {}, 工龄: {}, 高级人才职级: {}", 
+                personId, jobSeqNumber, jobLevelSeq, socialWorkAge, keyJobLevelSeq);
+            
+            List<DynamicObject> perfManagerResult = perfManagerResultMap.get(personId);
+            logger.debug("员工ID {} 查询到考核结果数量: {}", personId, perfManagerResult != null ? perfManagerResult.size() : 0);
+            String appraisalResultYear1 = null; // 最近一年的考核结果
+            String appraisalResultYearName1 = null; // 最近一年的考核结果
+            String appraisalResultYear2 = null; // 前一年的考核结果
+            String appraisalResultYearName2 = null; // 前一年的考核结果
+            String appraisalResultYear3 = null; // 再前一年的考核结果
+            String appraisalResultYearName3 = null; // 再前一年的考核结果
+
+            if (perfManagerResult != null && !perfManagerResult.isEmpty()) {
+                // 分配最近3年的考核结果
+                for (int i = 0; i < perfManagerResult.size(); i++) {
+                    DynamicObject result = perfManagerResult.get(i);
+                    Date appraisalYear = result.getDate(String.join(".", PositionStructureConstant.NCKD_PERFMANAGERENTRY, PositionStructureConstant.NCKD_APPRAISALYEAR));
+                    String appraisalResult = result.getString(String.join(".", PositionStructureConstant.NCKD_PERFMANAGERENTRY, PositionStructureConstant.NCKD_APPRAISALRESULT, FormConstant.NUMBER_KEY));
+                    String appraisalResultName = result.getString(String.join(".", PositionStructureConstant.NCKD_PERFMANAGERENTRY, PositionStructureConstant.NCKD_APPRAISALRESULT, FormConstant.NAME_KEY));
+                    if(appraisalYear != null) {
+                        int year = DateUtil.toLocalDateTime(appraisalYear).getYear();
+                        if (year == currentYear - 1) {
+                            appraisalResultYear1 = appraisalResult;
+                            appraisalResultYearName1 = StringUtils.isBlank(appraisalResultName) ? "无" : appraisalResultName;
+                        } else if (year == currentYear - 2) {
+                            appraisalResultYear2 = appraisalResult;
+                            appraisalResultYearName2 = StringUtils.isBlank(appraisalResultName) ? "无" : appraisalResultName;
+                        } else if (year == currentYear - 3) {
+                            appraisalResultYear3 = appraisalResult;
+                            appraisalResultYearName3 = StringUtils.isBlank(appraisalResultName) ? "无" : appraisalResultName;
+                        }
+                    }
+                }
+                logger.debug("员工ID {} 考核结果: 第一年({})={}, 第二年({})={}, 第三年({})={}", 
+                    personId, currentYear - 1, appraisalResultYearName1, 
+                    currentYear - 2, appraisalResultYearName2, 
+                    currentYear - 3, appraisalResultYearName3);
+            }
+
+            //科研、创新、创效成果
+            List<DynamicObject> contribList = contribMap.get(personId);
+            logger.debug("员工ID {} 查询到科研创新成果数量: {}", personId, contribList != null ? contribList.size() : 0);
+
+            List<Integer> jobLevelList = jobSeqJobLevelMap.get(jobSeqNumber);
+            if(jobLevelList == null){
+                logger.debug("职位序列 {} 不在处理范围内,跳过", jobSeqNumber);
+                //是这3个序列得人才要处理
+                continue;
+            }
+            JobSeqEnum jobSeq = JobSeqEnum.getByCode(jobSeqNumber);
+            logger.debug("员工ID {} 职位序列: {}, 处理职级列表: {}", personId, jobSeq.getName(), jobLevelList);
+            for (Integer jobLevel : jobLevelList) {
+                logger.debug("处理员工ID {} 的职级: {}", personId, jobLevel);
+                boolean isInnovation = false;
+                boolean isAppraisalResult = false;
+                boolean isWorkYear= false;
+                if(jobSeq == JobSeqEnum.TECHNICALS){
+                    //技术
+                    if(jobLevel == 13){
+                        logger.debug("员工ID {} 技术序列13级条件判断", personId);
+                        isInnovation = hasFactoryTechInnovationThirdPrizeOrAbove(contribList);
+                        logger.debug("员工ID {} 技术序列13级创新条件判断结果: {}", personId, isInnovation);
+                        // 判断近3年绩效定格均在合格及以上
+                        isAppraisalResult = isAllAppraisalQualifyOrAbove(appraisalResultYear1, appraisalResultYear2, appraisalResultYear3);
+                        logger.debug("员工ID {} 技术序列13级绩效条件判断结果: {}", personId, isAppraisalResult);
+
+                        //工作年限≥10 年,任前职级7至12级
+                        isWorkYear = socialWorkAge.compareTo(new BigDecimal(10)) >= 0 && jobLevelSeq > 7;
+                        logger.debug("员工ID {} 技术序列13级工作年限条件判断结果: {}, 工龄: {}, 当前职级: {}", personId, isWorkYear, socialWorkAge, jobLevelSeq);
+
+                    }else if(jobLevel == 14){
+                        logger.debug("员工ID {} 技术序列14级条件判断", personId);
+                        isInnovation = hasFactoryTechSecondAndCompanyTechThird(contribList);
+                        logger.debug("员工ID {} 技术序列14级创新条件判断结果: {}", personId, isInnovation);
+
+                        // 判断近3年绩效定格均在合格及以上,且至少有一次优秀
+                        isAppraisalResult = isAllAppraisalQualifyOrAboveWithExcellent(appraisalResultYear1, appraisalResultYear2, appraisalResultYear3);
+                        logger.debug("员工ID {} 技术序列14级绩效条件判断结果: {}", personId, isAppraisalResult);
+                        //在13职级工作不少于一个聘期
+                        isWorkYear = keyJobLevelSeq >= 13;
+                        logger.debug("员工ID {} 技术序列14级工作年限条件判断结果: {}, 高级人才职级: {}", personId, isWorkYear, keyJobLevelSeq);
+                    }else if(jobLevel == 15){
+                        logger.debug("员工ID {} 技术序列15级条件判断", personId);
+                        isInnovation = hasCompanyTechSecondAndProvinceTechThird(contribList);
+                        logger.debug("员工ID {} 技术序列15级创新条件判断结果: {}", personId, isInnovation);
+                        // 判断近3年绩效定格均在合格及以上,且至少有一次优秀
+                        isAppraisalResult = isAllAppraisalQualifyOrAboveWithExcellent(appraisalResultYear1, appraisalResultYear2, appraisalResultYear3);
+                        logger.debug("员工ID {} 技术序列15级绩效条件判断结果: {}", personId, isAppraisalResult);
+                        //工作年限≥15年,在14职级工作不少于一个聘期
+                        isWorkYear = socialWorkAge.compareTo(new BigDecimal(15)) >= 0 && keyJobLevelSeq >= 14;
+                        logger.debug("员工ID {} 技术序列15级工作年限条件判断结果: {}, 工龄: {}, 高级人才职级: {}", personId, isWorkYear, socialWorkAge, keyJobLevelSeq);
+                    }
+                }else if(jobSeq == JobSeqEnum.FUNCTIONAL){
+                    //职能序列
+                    if(jobLevel == 13){
+                        logger.debug("员工ID {} 职能序列13级条件判断", personId);
+                        isInnovation = hasCompanyManagementInnovationThird(contribList);
+                        logger.debug("员工ID {} 职能序列13级创新条件判断结果: {}", personId, isInnovation);
+                        // 判断近3年绩效定格均在合格及以上
+                        isAppraisalResult = isAllAppraisalQualifyOrAbove(appraisalResultYear1, appraisalResultYear2, appraisalResultYear3);
+                        logger.debug("员工ID {} 职能序列13级绩效条件判断结果: {}", personId, isAppraisalResult);
+                        //工作年限≥10 年,任前职级7至12级
+                        isWorkYear = socialWorkAge.compareTo(new BigDecimal(10)) >= 0 && jobLevelSeq > 7;
+                        logger.debug("员工ID {} 职能序列13级工作年限条件判断结果: {}, 工龄: {}, 当前职级: {}", personId, isWorkYear, socialWorkAge, jobLevelSeq);
+                    }else if(jobLevel == 14){
+                        logger.debug("员工ID {} 职能序列14级条件判断", personId);
+                        isInnovation = hasCompanyManagementInnovationSecond(contribList);
+                        logger.debug("员工ID {} 职能序列14级创新条件判断结果: {}", personId, isInnovation);
+                        // 判断近3年绩效定格均在合格及以上,且至少有一次优秀
+                        isAppraisalResult = isAllAppraisalQualifyOrAboveWithExcellent(appraisalResultYear1, appraisalResultYear2, appraisalResultYear3);
+                        logger.debug("员工ID {} 职能序列14级绩效条件判断结果: {}", personId, isAppraisalResult);
+                        //在13职级工作不少于一个聘期
+                        isWorkYear = keyJobLevelSeq >= 13;
+                        logger.debug("员工ID {} 职能序列14级工作年限条件判断结果: {}, 高级人才职级: {}", personId, isWorkYear, keyJobLevelSeq);
+                    }else if(jobLevel == 15){
+                        logger.debug("员工ID {} 职能序列15级条件判断", personId);
+                        isInnovation = hasCompanyManagementInnovationFirst(contribList);
+                        logger.debug("员工ID {} 职能序列15级创新条件判断结果: {}", personId, isInnovation);
+                        // 判断近3年绩效定格均在合格及以上,且至少有一次优秀
+                        isAppraisalResult = isAllAppraisalQualifyOrAboveWithExcellent(appraisalResultYear1, appraisalResultYear2, appraisalResultYear3);
+                        logger.debug("员工ID {} 职能序列15级绩效条件判断结果: {}", personId, isAppraisalResult);
+                        //工作年限≥15年,在14职级工作不少于一个聘期
+                        isWorkYear = socialWorkAge.compareTo(new BigDecimal(15)) >= 0 && keyJobLevelSeq >= 14;
+                        logger.debug("员工ID {} 职能序列15级工作年限条件判断结果: {}, 工龄: {}, 高级人才职级: {}", personId, isWorkYear, socialWorkAge, keyJobLevelSeq);
+                    }
+                }else if(jobSeq == JobSeqEnum.SKILL){
+                    //技能序列
+                    if(jobLevel == 12){
+                        logger.debug("员工ID {} 技能序列12级条件判断", personId);
+                        isInnovation = hasFactoryInnovationThird(contribList);
+                        logger.debug("员工ID {} 技能序列12级创新条件判断结果: {}", personId, isInnovation);
+                        // 判断近3年绩效定格均在合格及以上
+                        isAppraisalResult = isAllAppraisalQualifyOrAbove(appraisalResultYear1, appraisalResultYear2, appraisalResultYear3);
+                        logger.debug("员工ID {} 技能序列12级绩效条件判断结果: {}", personId, isAppraisalResult);
+                        //工作年限≥10 年,任前职级7至11级
+                        isWorkYear = socialWorkAge.compareTo(new BigDecimal(10)) >= 0 && jobLevelSeq > 7;
+                        logger.debug("员工ID {} 技能序列12级工作年限条件判断结果: {}, 工龄: {}, 当前职级: {}", personId, isWorkYear, socialWorkAge, jobLevelSeq);
+                    }else if(jobLevel == 13){
+                        logger.debug("员工ID {} 技能序列13级条件判断", personId);
+                        isInnovation = hasFactoryInnovationSecondAndCompanyTechThird(contribList);
+                        logger.debug("员工ID {} 技能序列13级创新条件判断结果: {}", personId, isInnovation);
+                        // 判断近3年绩效定格均在合格及以上,且至少有一次优秀
+                        isAppraisalResult = isAllAppraisalQualifyOrAboveWithExcellent(appraisalResultYear1, appraisalResultYear2, appraisalResultYear3);
+                        logger.debug("员工ID {} 技能序列13级绩效条件判断结果: {}", personId, isAppraisalResult);
+                        //在12职级工作不少于一个聘期
+                        isWorkYear = keyJobLevelSeq >= 12;
+                        logger.debug("员工ID {} 技能序列13级工作年限条件判断结果: {}, 高级人才职级: {}", personId, isWorkYear, keyJobLevelSeq);
+                    }else if(jobLevel == 14){
+                        logger.debug("员工ID {} 技能序列14级条件判断", personId);
+                        isInnovation = hasCompanyInnovationSecondAndProvinceTechThird(contribList);
+                        logger.debug("员工ID {} 技能序列14级创新条件判断结果: {}", personId, isInnovation);
+                        // 判断近3年绩效定格均在合格及以上,且至少有一次优秀
+                        isAppraisalResult = isAllAppraisalQualifyOrAboveWithExcellent(appraisalResultYear1, appraisalResultYear2, appraisalResultYear3);
+                        logger.debug("员工ID {} 技能序列14级绩效条件判断结果: {}", personId, isAppraisalResult);
+                        //工作年限≥15年,在13职级工作不少于一个聘期
+                        isWorkYear = socialWorkAge.compareTo(new BigDecimal(15)) >= 0 && keyJobLevelSeq >= 13;
+                        logger.debug("员工ID {} 技能序列14级工作年限条件判断结果: {}, 工龄: {}, 高级人才职级: {}", personId, isWorkYear, socialWorkAge, keyJobLevelSeq);
+                    }
+                }
+                String appraisalResultsDisplay = String.join("、",
+                        appraisalResultYearName1 != null ? appraisalResultYearName1 : "无",
+                        appraisalResultYearName2 != null ? appraisalResultYearName2 : "无",
+                        appraisalResultYearName3 != null ? appraisalResultYearName3 : "无");
+                StringJoiner matchCondDescJoin = new StringJoiner(StrFormatter.LINE_SEPARATOR);
+                String contribString = getContribString(contribList);
+                matchCondDescJoin.add(StrFormatter.format("职位序列:{},匹配职级:{},员工职位档案最新职级:{}",jobSeq.getName(),jobLevel,jobLevelSeq == -2 ? "无" : jobLevelSeq));
+                matchCondDescJoin.add(StrFormatter.format("科研、创新、创效成果:【{}】,获奖情况:{}",(isInnovation ? "满足" : "不满足"),StringUtils.isBlank(contribString) ? "无" : contribString));
+                matchCondDescJoin.add(StrFormatter.format("绩效表现:【{}】,近三年考核结果:【{}】",(isAppraisalResult ? "满足" : "不满足"),appraisalResultsDisplay));
+                matchCondDescJoin.add(StrFormatter.format("工作年限:【{}】,工龄:【{}】,员工职位档案最新职级:【{}】,高级人才聘任职级:【{}】",
+                        (isWorkYear ? "满足" : "不满足"),
+                        socialWorkAge != null ? socialWorkAge.setScale(2, RoundingMode.HALF_UP) : BigDecimal.ZERO,
+                        jobLevelSeq == -2 ? "无" : jobLevelSeq,
+                        keyDynObj != null ? keyJobLevelSeq : "无"));
+                DynamicObject keyBeHavEval = EntityHelper.newEntity(PositionStructureConstant.KEYBEHAVEVAL_ENTITYID);
+                keyBeHavEval.set(FormConstant.NCKD_PERSON, person.getDynamicObject(FormConstant.EMPLOYEE_KEY));
+                keyBeHavEval.set(FormConstant.NCKD_DEP, person.getDynamicObject(FormConstant.ADMINORG));
+                keyBeHavEval.set(FormConstant.NCKD_POSITION_KEY, person.getDynamicObject(FormConstant.POSITION_KEY));
+                keyBeHavEval.set(FormConstant.NCKD_JOBSEQ, jobSeqObj);
+                keyBeHavEval.set(PositionStructureConstant.NCKD_JOBLEVEL, jobLevel);
+                keyBeHavEval.set(PositionStructureConstant.NCKD_INNOVATE, isInnovation ? EnableEnum.YES.getCode() : EnableEnum.NO.getCode());
+                keyBeHavEval.set(PositionStructureConstant.NCKD_WORKYEAR, isWorkYear ? EnableEnum.YES.getCode() : EnableEnum.NO.getCode());
+                keyBeHavEval.set(PositionStructureConstant.NCKD_APPRAISALRESULT, isAppraisalResult ? EnableEnum.YES.getCode() : EnableEnum.NO.getCode());
+                keyBeHavEval.set(PositionStructureConstant.NCKD_MATCHCONDDESC+"_tag", matchCondDescJoin.toString());
+                keyBeHavEval.set(PositionStructureConstant.STATUS,  StatusEnum.C.toString());
+                keyBeHavEval.set(PositionStructureConstant.ENABLE,  EnableEnum.YES.getCode());
+
+                logger.debug("员工ID {} 职级 {} 的评估结果: 创新条件={}, 绩效条件={}, 工作年限条件={}", 
+                    personId, jobLevel, isInnovation, isAppraisalResult, isWorkYear);
+                saveKeyBeHavEval.add(keyBeHavEval);
+                processedCount++;
+            }
+        }
+        
+        logger.info("关键行为评价定时任务处理完成,总共处理员工记录数: {}", processedCount);
+        logger.info("准备保存 {} 条关键行为评价记录", saveKeyBeHavEval.size());
+        TXHandle txHandle = TX.requiresNew();
+        try {
+            //删除原数据
+            logger.info("开始删除原数据");
+            DynamicObjectCollection query = QueryServiceHelper.query(PositionStructureConstant.KEYBEHAVEVAL_ENTITYID, FormConstant.ID_KEY, new QFilter[]{new QFilter(FormConstant.ID_KEY, QCP.is_notnull, null)});
+            List<Long> ids = query.stream().map(empPosOrgRel -> empPosOrgRel.getLong(FormConstant.ID_KEY)).collect(Collectors.toList());
+            logger.info("查询到需要删除的记录数量: {}", ids.size());
+            if (!ids.isEmpty()) {
+                MainEntityType keyBeHavEvalEntityType = EntityMetadataCache.getDataEntityType(PositionStructureConstant.KEYBEHAVEVAL_ENTITYID);
+                DeleteServiceHelper.delete(keyBeHavEvalEntityType, ids.toArray(new Long[0]));
+                logger.info("成功删除 {} 条原数据", ids.size());
+            } else {
+                logger.info("没有需要删除的原数据");
+            }
+
+            if (!saveKeyBeHavEval.isEmpty()) {
+                OperationResult operationResult = SaveServiceHelper.saveOperate(PositionStructureConstant.KEYBEHAVEVAL_ENTITYID, saveKeyBeHavEval.toArray(new DynamicObject[0]), OperateOption.create());
+                if (!operationResult.isSuccess()) {
+                    StringJoiner errorMsg = new StringJoiner("\n");
+                    for (IOperateInfo error : operationResult.getAllErrorOrValidateInfo()) {
+                        errorMsg.add(error.getMessage());
+                    }
+                    if (!ObjectUtils.isEmpty(operationResult.getMessage())) {
+                        errorMsg.add(operationResult.getMessage());
+                    }
+                    throw new ValidationException("保存关键行为评价结果失败,原因:" + errorMsg.toString());
+                }
+            }
+        } catch (Exception e) {
+            txHandle.markRollback();
+            throw new RuntimeException(e);
+        }finally {
+            txHandle.close();
+        }
+
+
+    }
+
+    private String getContribString(List<DynamicObject> contribList){
+        logger.debug("开始获取贡献字符串,贡献列表大小: {}", contribList != null ? contribList.size() : 0);
+        StringJoiner contribStringJoiner = new StringJoiner(";");
+        if(contribList != null) {
+            for (DynamicObject contrib : contribList) {
+                Date date = contrib.getDate(ContributionConstant.NCKD_YEAR);
+                String scoreItemNumber = contrib.getString(String.join(".", ContributionConstant.NCKD_SCOREITEM, FormConstant.NUMBER_KEY));
+                ScoreItemEnum scoreItem = ScoreItemEnum.getByCode(scoreItemNumber);
+                if (scoreItem != null) {
+                    String scoreItemSubNumber = contrib.getString(String.join(".", ContributionConstant.NCKD_SCOREITEMSUB, FormConstant.NUMBER_KEY));
+                    ScoreItemSubEnum scoreItemSub = ScoreItemSubEnum.getByCode(scoreItemSubNumber);
+
+                    String scoreItemLevelNumber = contrib.getString(String.join(".", ContributionConstant.NCKD_SCOREITEMSUB, ContributionConstant.NCKD_SCOREITEMLEVEL, FormConstant.NUMBER_KEY));
+                    ScoreItemLevelEnum scoreItemLevel = ScoreItemLevelEnum.getByCode(scoreItemLevelNumber);
+
+                    String scoreItemRankNumber = contrib.getString(String.join(".", ContributionConstant.NCKD_SCOREITEMRANK, FormConstant.NUMBER_KEY));
+                    ScoreIteMrankEnum scoreItemRank = ScoreIteMrankEnum.getByCode(scoreItemRankNumber);
+
+                    contribStringJoiner.add(StrFormatter.format("年度【{}】-项目【{}】-奖项级别【{}】-级别【{}】-获奖等级【{}】",
+                            DateUtil.getYear(date),
+                            scoreItem.getName(),
+                            scoreItemSub != null ? scoreItemSub.getName() : "",
+                            scoreItemLevel != null ? scoreItemLevel.getName() : "",
+                            scoreItemRank != null ? scoreItemRank.getName() : ""));
+                }
+            }
+        }
+        String result = contribStringJoiner.toString();
+        logger.debug("贡献字符串生成完成,内容: {}", result);
+        return result;
+    }
+
+    /**
+     * 判断近3年绩效定格是否均在合格及以上
+     * @param appraisalResultYear1 最近一年的考核结果
+     * @param appraisalResultYear2 前一年的考核结果
+     * @param appraisalResultYear3 再前一年的考核结果
+     * @return boolean
+     */
+    private boolean isAllAppraisalQualifyOrAbove(String appraisalResultYear1, String appraisalResultYear2, String appraisalResultYear3) {
+        logger.info("检查考核结果是否均在合格及以上: 第一年={}, 第二年={}, 第三年={}", appraisalResultYear1, appraisalResultYear2, appraisalResultYear3);
+        String[] appraisalResults = {appraisalResultYear1, appraisalResultYear2, appraisalResultYear3};
+
+        // 检查是否所有年份都有考核结果
+        for (String result : appraisalResults) {
+            if (result == null) {
+                logger.info("存在年份没有考核结果,不满足条件");
+                return false;
+            }
+        }
+
+        for (String result : appraisalResults) {
+            if (result != null) { // 检查所有考核结果
+                AppraisalResultEnum appraisalEnum = AppraisalResultEnum.getByCode(result);
+                if (appraisalEnum != null) {
+                    // 检查是否在合格及以上 (优秀、合格、基本合格、视同合格、良好、视同优秀)
+                    boolean isQualifyOrAbove = appraisalEnum == AppraisalResultEnum.EXCELLENT ||
+                            appraisalEnum == AppraisalResultEnum.QUALIFIED ||
+                            appraisalEnum == AppraisalResultEnum.BASICALLY_QUALIFIED ||
+                            appraisalEnum == AppraisalResultEnum.DEEMED_QUALIFIED ||
+                            appraisalEnum == AppraisalResultEnum.GOOD ||
+                            appraisalEnum == AppraisalResultEnum.DEEMED_EXCELLENT;
+
+                    logger.info("考核结果 {} 解析为: {},是否合格及以上: {}", result, appraisalEnum.getName(), isQualifyOrAbove);
+
+                    if (!isQualifyOrAbove) {
+                        logger.info("发现不合格考核结果: {}", result);
+                        return false;
+                    }
+                } else {
+                    logger.info("无法识别考核结果代码: {}", result);
+                    return false; // 如果无法识别考核结果,认为不符合条件
+                }
+            }
+        }
+        logger.info("所有考核结果均合格及以上");
+        return true;
+    }
+
+    /**
+     * 判断近3年绩效定格是否均在合格及以上,且至少有一次优秀
+     * @param appraisalResultYear1 最近一年的考核结果
+     * @param appraisalResultYear2 前一年的考核结果
+     * @param appraisalResultYear3 再前一年的考核结果
+     * @return boolean
+     */
+    private boolean isAllAppraisalQualifyOrAboveWithExcellent(String appraisalResultYear1, String appraisalResultYear2, String appraisalResultYear3) {
+        logger.info("检查考核结果是否均在合格及以上且至少有一次优秀: 第一年={}, 第二年={}, 第三年={}", appraisalResultYear1, appraisalResultYear2, appraisalResultYear3);
+        // 首先检查是否所有考核结果都在合格及以上
+        if (!isAllAppraisalQualifyOrAbove(appraisalResultYear1, appraisalResultYear2, appraisalResultYear3)) {
+            logger.info("并非所有考核结果都在合格及以上或没有考核结果");
+            return false;
+        }
+
+        // 然后检查是否至少有一次优秀(包括优秀、视同优秀、良好)
+        String[] appraisalResults = {appraisalResultYear1, appraisalResultYear2, appraisalResultYear3};
+        int excellentCount = 0;
+
+        for (String result : appraisalResults) {
+            if (result != null) { // 只检查非空的考核结果
+                AppraisalResultEnum appraisalEnum = AppraisalResultEnum.getByCode(result);
+                if (appraisalEnum != null) {
+                    // 检查是否为优秀等级
+                    boolean isExcellent = appraisalEnum == AppraisalResultEnum.EXCELLENT ||
+                            appraisalEnum == AppraisalResultEnum.DEEMED_EXCELLENT ||
+                            appraisalEnum == AppraisalResultEnum.GOOD;
+                    
+                    if (isExcellent) {
+                        excellentCount++;
+                        logger.info("发现优秀考核结果: {} ({})", result, appraisalEnum.getName());
+                    }
+                }
+            }
+        }
+        
+        boolean hasExcellent = excellentCount > 0;
+        logger.info("至少有一次优秀的考核结果: {}, 优秀次数: {}", hasExcellent, excellentCount);
+        return hasExcellent;
+    }
+
+
+
+    /**
+     * 判断近3年是否获得厂矿科技进步、科学技术奖三等奖及以上
+     * @param contribList 贡献列表
+     * @return boolean
+     */
+    private boolean hasFactoryTechInnovationThirdPrizeOrAbove(List<DynamicObject> contribList) {
+        logger.debug("检查厂矿科技进步、科学技术奖三等奖及以上,贡献列表大小: {}", contribList != null ? contribList.size() : 0);
+        boolean result = hasRequiredAwards(contribList,
+                AwardCondition.thirdPrizeOrAbove(
+                        new ScoreItemSubEnum[]{ScoreItemSubEnum.TECHNOLOGY_AWARD},
+                        new ScoreItemLevelEnum[]{ScoreItemLevelEnum.FACTORY_LEVEL}
+                )
+        );
+        logger.debug("厂矿科技进步、科学技术奖三等奖及以上检查结果: {}", result);
+        return result;
+    }
+
+    /**
+     * 判断近3年是否获得厂矿科技进步、科学技术奖二等奖及以上,公司科技进步、科学技术奖三等奖及以上
+     * @param contribList 贡献列表
+     * @return boolean
+     */
+    private boolean hasFactoryTechSecondAndCompanyTechThird(List<DynamicObject> contribList) {
+        logger.debug("检查厂矿科技进步、科学技术奖二等奖及以上,公司科技进步、科学技术奖三等奖及以上,贡献列表大小: {}", contribList != null ? contribList.size() : 0);
+        boolean result = hasRequiredAwards(contribList,
+                AwardCondition.secondPrizeOrAbove(
+                        new ScoreItemSubEnum[]{ScoreItemSubEnum.TECHNOLOGY_AWARD},
+                        new ScoreItemLevelEnum[]{ScoreItemLevelEnum.FACTORY_LEVEL}
+                ),
+                AwardCondition.thirdPrizeOrAbove(
+                        new ScoreItemSubEnum[]{ScoreItemSubEnum.TECHNOLOGY_AWARD},
+                        new ScoreItemLevelEnum[]{ScoreItemLevelEnum.COMPANY_LEVEL}
+                )
+        );
+        logger.debug("厂矿科技进步、科学技术奖二等奖及以上,公司科技进步、科学技术奖三等奖及以上检查结果: {}", result);
+        return result;
+    }
+
+    /**
+     * 判断近3年是否获得公司科技进步、科学技术奖二等奖及以上,省科技进步、科学技术奖三等奖及以上
+     * @param contribList 贡献列表
+     * @return boolean
+     */
+    private boolean hasCompanyTechSecondAndProvinceTechThird(List<DynamicObject> contribList) {
+        logger.debug("检查公司科技进步、科学技术奖二等奖及以上,省科技进步、科学技术奖三等奖及以上,贡献列表大小: {}", contribList != null ? contribList.size() : 0);
+        boolean result = hasRequiredAwards(contribList,
+                AwardCondition.secondPrizeOrAbove(
+                        new ScoreItemSubEnum[]{ScoreItemSubEnum.TECHNOLOGY_AWARD},
+                        new ScoreItemLevelEnum[]{ScoreItemLevelEnum.COMPANY_LEVEL}
+                ),
+                AwardCondition.thirdPrizeOrAbove(
+                        new ScoreItemSubEnum[]{ScoreItemSubEnum.TECHNOLOGY_AWARD},
+                        new ScoreItemLevelEnum[]{ScoreItemLevelEnum.PROVINCIAL_LEVEL}
+                )
+        );
+        logger.debug("公司科技进步、科学技术奖二等奖及以上,省科技进步、科学技术奖三等奖及以上检查结果: {}", result);
+        return result;
+    }
+
+    /**
+     * 判断近3年是否获得公司管理创新奖、全员创效奖三等奖及以上
+     * @param contribList 贡献列表
+     * @return boolean
+     */
+    private boolean hasCompanyManagementInnovationThird(List<DynamicObject> contribList) {
+        logger.debug("检查公司管理创新奖、全员创效奖三等奖及以上,贡献列表大小: {}", contribList != null ? contribList.size() : 0);
+        boolean result = hasRequiredAwards(contribList,
+                AwardCondition.thirdPrizeOrAbove(
+                        new ScoreItemSubEnum[]{ScoreItemSubEnum.MANAGEMENT_INNOVATION_AWARD, ScoreItemSubEnum.EMPLOYEES_CREATIVE_AWARD},
+                        new ScoreItemLevelEnum[]{ScoreItemLevelEnum.COMPANY_LEVEL}
+                )
+        );
+        logger.debug("公司管理创新奖、全员创效奖三等奖及以上检查结果: {}", result);
+        return result;
+    }
+
+    /**
+     * 判断近3年是否获得公司管理创新奖、全员创效奖二等奖及以上
+     * @param contribList 贡献列表
+     * @return boolean
+     */
+    private boolean hasCompanyManagementInnovationSecond(List<DynamicObject> contribList) {
+        logger.debug("检查公司管理创新奖、全员创效奖二等奖及以上,贡献列表大小: {}", contribList != null ? contribList.size() : 0);
+        boolean result = hasRequiredAwards(contribList,
+                AwardCondition.secondPrizeOrAbove(
+                        new ScoreItemSubEnum[]{ScoreItemSubEnum.MANAGEMENT_INNOVATION_AWARD, ScoreItemSubEnum.EMPLOYEES_CREATIVE_AWARD},
+                        new ScoreItemLevelEnum[]{ScoreItemLevelEnum.COMPANY_LEVEL}
+                )
+        );
+        logger.debug("公司管理创新奖、全员创效奖二等奖及以上检查结果: {}", result);
+        return result;
+    }
+
+    /**
+     * 判断近3年是否获得公司管理创新奖、全员创效奖一等奖及以上
+     * @param contribList 贡献列表
+     * @return boolean
+     */
+    private boolean hasCompanyManagementInnovationFirst(List<DynamicObject> contribList) {
+        return hasRequiredAwards(contribList,
+                AwardCondition.firstPrizeOrAbove(
+                        new ScoreItemSubEnum[]{ScoreItemSubEnum.MANAGEMENT_INNOVATION_AWARD, ScoreItemSubEnum.EMPLOYEES_CREATIVE_AWARD},
+                        new ScoreItemLevelEnum[]{ScoreItemLevelEnum.COMPANY_LEVEL}
+                )
+        );
+    }
+
+    /**
+     * 判断近3年是否获得厂矿创新奖、全员创效奖三等奖及以上
+     * @param contribList 贡献列表
+     * @return boolean
+     */
+    private boolean hasFactoryInnovationThird(List<DynamicObject> contribList) {
+        return hasRequiredAwards(contribList,
+                AwardCondition.thirdPrizeOrAbove(
+                        new ScoreItemSubEnum[]{ScoreItemSubEnum.MANAGEMENT_INNOVATION_AWARD, ScoreItemSubEnum.EMPLOYEES_CREATIVE_AWARD},
+                        new ScoreItemLevelEnum[]{ScoreItemLevelEnum.FACTORY_LEVEL}
+                )
+        );
+    }
+
+    /**
+     * 判断近3年是否获得厂矿创新奖、全员创效奖二等奖及以上,公司科技进步三等奖及以上
+     * @param contribList 贡献列表
+     * @return boolean
+     */
+    private boolean hasFactoryInnovationSecondAndCompanyTechThird(List<DynamicObject> contribList) {
+        return hasRequiredAwards(contribList,
+                AwardCondition.secondPrizeOrAbove(
+                        new ScoreItemSubEnum[]{ScoreItemSubEnum.MANAGEMENT_INNOVATION_AWARD, ScoreItemSubEnum.EMPLOYEES_CREATIVE_AWARD},
+                        new ScoreItemLevelEnum[]{ScoreItemLevelEnum.FACTORY_LEVEL}
+                ),
+                AwardCondition.thirdPrizeOrAbove(
+                        new ScoreItemSubEnum[]{ScoreItemSubEnum.TECHNOLOGY_AWARD},
+                        new ScoreItemLevelEnum[]{ScoreItemLevelEnum.COMPANY_LEVEL}
+                )
+        );
+    }
+
+    /**
+     * 判断近3年是否获得公司创新奖、全员创效奖二等奖及以上,省科技进步三等奖及以上
+     * @param contribList 贡献列表
+     * @return boolean
+     */
+    private boolean hasCompanyInnovationSecondAndProvinceTechThird(List<DynamicObject> contribList) {
+        return hasRequiredAwards(contribList,
+                AwardCondition.secondPrizeOrAbove(
+                        new ScoreItemSubEnum[]{ScoreItemSubEnum.MANAGEMENT_INNOVATION_AWARD, ScoreItemSubEnum.EMPLOYEES_CREATIVE_AWARD},
+                        new ScoreItemLevelEnum[]{ScoreItemLevelEnum.COMPANY_LEVEL}
+                ),
+                AwardCondition.thirdPrizeOrAbove(
+                        new ScoreItemSubEnum[]{ScoreItemSubEnum.TECHNOLOGY_AWARD},
+                        new ScoreItemLevelEnum[]{ScoreItemLevelEnum.PROVINCIAL_LEVEL}
+                )
+        );
+    }
+
+    /**
+     * 通用的奖励判断方法
+     * @param contribList 贡献列表
+     * @param requiredAwards 需要满足的奖项条件数组
+     * @return boolean
+     */
+    private boolean hasRequiredAwards(List<DynamicObject> contribList, AwardCondition... requiredAwards) {
+        if (contribList == null || contribList.isEmpty() || requiredAwards == null || requiredAwards.length == 0) {
+            return false;
+        }
+
+        // 为每个奖项条件创建一个标记,表示是否已满足
+        boolean[] satisfied = new boolean[requiredAwards.length];
+
+        for (DynamicObject contrib : contribList) {
+            String scoreItemNumber = contrib.getString(String.join(".", ContributionConstant.NCKD_SCOREITEM, FormConstant.NUMBER_KEY));
+            ScoreItemEnum scoreItem = ScoreItemEnum.getByCode(scoreItemNumber);
+
+            if (scoreItem != null && scoreItem == ScoreItemEnum.RESEARCH_SCORE) {
+                String scoreItemSubNumber = contrib.getString(String.join(".", ContributionConstant.NCKD_SCOREITEMSUB, FormConstant.NUMBER_KEY));
+                ScoreItemSubEnum scoreItemSub = ScoreItemSubEnum.getByCode(scoreItemSubNumber);
+
+                String scoreItemLevelNumber = contrib.getString(String.join(".", ContributionConstant.NCKD_SCOREITEMSUB, ContributionConstant.NCKD_SCOREITEMLEVEL, FormConstant.NUMBER_KEY));
+                ScoreItemLevelEnum scoreItemLevel = ScoreItemLevelEnum.getByCode(scoreItemLevelNumber);
+
+                String scoreItemRankNumber = contrib.getString(String.join(".", ContributionConstant.NCKD_SCOREITEMRANK, FormConstant.NUMBER_KEY));
+                ScoreIteMrankEnum scoreItemRank = ScoreIteMrankEnum.getByCode(scoreItemRankNumber);
+
+                // 检查当前奖项是否满足任一条件
+                for (int i = 0; i < requiredAwards.length; i++) {
+                    AwardCondition condition = requiredAwards[i];
+
+                    if (condition.isMatch(scoreItemRank, scoreItemLevel, scoreItemSub)) {
+                        satisfied[i] = true;
+                    }
+                }
+            }
+        }
+
+        // 检查所有条件是否都已满足
+        for (boolean isSatisfied : satisfied) {
+            if (!isSatisfied) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    /**
+     * 奖项条件类
+     */
+    private static class AwardCondition {
+        private final ScoreIteMrankEnum[] rankEnums;
+        private final ScoreItemLevelEnum[] levelEnums;
+        private final ScoreItemSubEnum[] subEnums;
+
+        public AwardCondition(ScoreIteMrankEnum[] rankEnums, ScoreItemLevelEnum[] levelEnums, ScoreItemSubEnum[] subEnums) {
+            this.rankEnums = rankEnums;
+            this.levelEnums = levelEnums;
+            this.subEnums = subEnums;
+        }
+
+        /**
+         * 检查当前奖项是否匹配条件
+         */
+        public boolean isMatch(ScoreIteMrankEnum rank, ScoreItemLevelEnum level, ScoreItemSubEnum sub) {
+            if (rank == null || level == null || sub == null) {
+                return false;
+            }
+
+            // 检查奖项类型是否匹配
+            boolean rankMatch = false;
+            for (ScoreIteMrankEnum requiredRank : rankEnums) {
+                if (rank == requiredRank) {
+                    rankMatch = true;
+                    break;
+                }
+            }
+
+            // 检查级别是否匹配
+            boolean levelMatch = false;
+            for (ScoreItemLevelEnum requiredLevel : levelEnums) {
+                if (level == requiredLevel) {
+                    levelMatch = true;
+                    break;
+                }
+            }
+
+            // 检查等级是否匹配
+            boolean subMatch = false;
+            for (ScoreItemSubEnum requiredSub : subEnums) {
+                if (sub == requiredSub) {
+                    subMatch = true;
+                    break;
+                }
+            }
+
+            return rankMatch && levelMatch && subMatch;
+        }
+
+        /**
+         * 创建三等奖及以上的条件
+         */
+        public static AwardCondition thirdPrizeOrAbove(ScoreItemSubEnum[] subEnums, ScoreItemLevelEnum[] levelEnums) {
+            ScoreIteMrankEnum[] rankEnums = {ScoreIteMrankEnum.THIRD_PRIZE, ScoreIteMrankEnum.SECOND_PRIZE, ScoreIteMrankEnum.FIRST_PRIZE};
+            return new AwardCondition(rankEnums, levelEnums, subEnums);
+        }
+
+        /**
+         * 创建二等奖及以上的条件
+         */
+        public static AwardCondition secondPrizeOrAbove(ScoreItemSubEnum[] subEnums, ScoreItemLevelEnum[] levelEnums) {
+            ScoreIteMrankEnum[] rankEnums = {ScoreIteMrankEnum.SECOND_PRIZE, ScoreIteMrankEnum.FIRST_PRIZE};
+            return new AwardCondition(rankEnums, levelEnums, subEnums);
+        }
+
+        /**
+         * 创建一等奖及以上的条件
+         */
+        public static AwardCondition firstPrizeOrAbove(ScoreItemSubEnum[] subEnums, ScoreItemLevelEnum[] levelEnums) {
+            ScoreIteMrankEnum[] rankEnums = {ScoreIteMrankEnum.FIRST_PRIZE};
+            return new AwardCondition(rankEnums, levelEnums, subEnums);
+        }
+    }
+}

+ 4 - 4
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/stm/plugin/form/unitst/UnitStBudgetApplyFormPlugin.java

@@ -146,11 +146,11 @@ public class UnitStBudgetApplyFormPlugin extends AbstractFormPlugin implements P
                     }
                 }
                 queryFieldBuilder.add(String.join( ".", StmConstant.NCKD_PAYUNIT, FormConstant.NAME_KEY));
-                LocalDateTime beginOfYear = DateUtil.beginOfYear(year);
-                LocalDateTime endOfYear = DateUtil.endOfYear(year);
+                Date beginOfYear = DateUtil.beginOfYear(year);
+                Date endOfYear = DateUtil.endOfYear(year);
                 QFilter qFilter = new QFilter(String.join(".",StmConstant.NCKD_PAYUNIT, FormConstant.PARENTORG_KEY, FormConstant.ID_KEY), QCP.equals, payUnit.getLong(FormConstant.ID_KEY))
-                        .and(StmConstant.NCKD_YEAR,QCP.large_equals, DateUtil.toDate(beginOfYear))
-                        .and(StmConstant.NCKD_YEAR,QCP.less_equals,  DateUtil.toDate(endOfYear))
+                        .and(StmConstant.NCKD_YEAR,QCP.large_equals, beginOfYear)
+                        .and(StmConstant.NCKD_YEAR,QCP.less_equals,  endOfYear)
                         .and(QFilterCommonHelper.getBillStatusFilter());
                 DynamicObjectCollection query = QueryServiceHelper.query(StmConstant.UNITSTBUDGETAPPLY_ENTITYID, queryFieldBuilder.buildSelect(), new QFilter[]{qFilter});
                 // 对查询结果按照buildSelectArray()中的字段进行汇总