Преглед на файлове

Merge remote-tracking branch 'origin/master'

turborao преди 1 седмица
родител
ревизия
bcb73466fa
променени са 100 файла, в които са добавени 6464 реда и са изтрити 1182 реда
  1. 42 0
      code/base/nckd-jxccl-base-common/src/main/java/nckd/jxccl/base/common/algo/DistinctConcatFunction.java
  2. 47 0
      code/base/nckd-jxccl-base-common/src/main/java/nckd/jxccl/base/common/algo/GroupMaxStrFunction.java
  3. 32 2
      code/base/nckd-jxccl-base-common/src/main/java/nckd/jxccl/base/common/constant/FormConstant.java
  4. 43 0
      code/base/nckd-jxccl-base-common/src/main/java/nckd/jxccl/base/common/utils/DateUtil.java
  5. 4 1
      code/base/nckd-jxccl-base-helper/src/main/java/nckd/jxccl/base/hrpi/helper/EmpPosOrgRelHelper.java
  6. 20 0
      code/base/nckd-jxccl-base-helper/src/main/java/nckd/jxccl/base/orm/helper/QFilterCommonHelper.java
  7. 39 0
      code/base/nckd-jxccl-base-helper/src/main/java/nckd/jxccl/base/swc/helper/SWCHelper.java
  8. 16 1
      code/base/nckd-jxccl-base-helper/src/main/java/nckd/jxccl/base/wtc/helper/WTCHelper.java
  9. 0 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/excells/business/.gitkeep
  10. 39 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/excells/common/ExcellsConstant.java
  11. 0 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/excells/mservice/.gitkeep
  12. 279 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/excells/plugin/form/ExcellentssAllowanceFormPlugin.java
  13. 237 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/excells/plugin/operate/PushAdjustOpPlugin.java
  14. 83 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/excells/plugin/operate/validate/ExcellentssAllowanceValiDate.java
  15. 0 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/excells/plugin/other/.gitkeep
  16. 0 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/excells/plugin/report/.gitkeep
  17. 0 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/excells/plugin/workflow/.gitkeep
  18. 0 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/excells/webapi/.gitkeep
  19. 1 1
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/homs/business/application/event/GenerateEmploymentContractEventServicePlugin.java
  20. 1 4
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/htm/plugin/form/quitapply/QuitApplyFormPlugin.java
  21. 156 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/common/HasPosAllowDataService.java
  22. 11 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/common/PositionStructureConstant.java
  23. 1 1
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/form/adjust/report/UnAdjustedReportFormPlugin.java
  24. 13 2
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/form/adjust/report/UnAdjustedReportReportListDataPlugin.java
  25. 8 1
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/form/annualadjust/AnnualAdjustmentFormPlugin.java
  26. 22 3
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/form/annualadjust/UnAnnualAdjustListPlugin.java
  27. 78 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/form/annualadjust/report/UnAnnualAdjustReportFormPlugin.java
  28. 302 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/form/annualadjust/report/UnAnnualAdjustReportListDataPlugin.java
  29. 72 1
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/form/contribution/ContribBillFormPlugin.java
  30. 44 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/form/other/KeyBeHavEvalListPlugin.java
  31. 48 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/form/other/KeyBeHavEvalReptFormPlugin.java
  32. 7 1
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/form/other/SeniorAppointMgmtFormPlugin.java
  33. 38 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/form/other/impt/KeyBeHavEvalProjRsltImportPlugin.java
  34. 124 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/form/other/report/KeyBeHavEvalReptQueryFromPlugin.java
  35. 449 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/form/other/report/KeyBeHavEvalReptQueryPlugin.java
  36. 1 1
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/operate/annualadjust/AnnualAdjustmentOperationPlugin.java
  37. 19 1
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/operate/other/MgrAppointMgmtTransferAfterEffectOp.java
  38. 21 197
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/task/KeyBeHavEvalTask.java
  39. 70 33
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/sdm/plugin/operate/SendTaskOpPlugin.java
  40. 4 4
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/haos/plugin/operate/adminorg/AdminOrgDetailConfirmChangeOpPlugin.java
  41. 0 119
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/business/hr/PositionBillClosedCallBackService.java
  42. 0 347
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/business/hr/PositionBillServiceHelper.java
  43. 135 0
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/business/hr/service/impl/PosBillEntryFastChgHelper.java
  44. 196 0
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/business/hr/service/impl/PositionBillAfterBindDataService.java
  45. 2 1
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/business/hr/service/impl/PositionBillBaseService.java
  46. 101 0
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/business/hr/service/impl/PositionBillBeforeBindDataService.java
  47. 195 0
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/business/hr/service/impl/PositionBillClosedCallBackService.java
  48. 70 39
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/business/hr/service/impl/PositionBillConfirmCallBackService.java
  49. 44 24
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/business/hr/service/impl/PositionBillPropertyChangedService.java
  50. 211 0
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/business/hr/service/impl/PositionBillSaveHelper.java
  51. 581 0
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/business/hr/service/impl/PositionBillServiceHelper.java
  52. 29 0
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/business/hr/utils/PositionBillUtil.java
  53. 1 1
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/common/hr/PatternUtil.java
  54. 124 8
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/common/hr/PositionBillConstant.java
  55. 42 10
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/common/hr/PositionChangeTypeEnum.java
  56. 0 38
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/form/hr/ParentPositionListPlugin.java
  57. 153 76
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/form/hr/PosBillEntryAddFormPlugin.java
  58. 38 0
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/form/hr/PosBillEntryChangeFormPlugin.java
  59. 425 0
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/form/hr/PosBillEntryUpdatePlugin.java
  60. 96 52
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/form/hr/PositionBillEntryFormPlugin.java
  61. 338 94
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/form/hr/PositionBillFormPlugin.java
  62. 70 0
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/form/hr/PositionBillListPlugin.java
  63. 2 1
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/operate/hr/PosBillEntryAddSaveOpPlugin.java
  64. 26 0
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/operate/hr/PosBillEntryChangeSaveOpPlugin.java
  65. 6 5
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/operate/hr/PosBillEntryNewPositionTempSaveOpPlugin.java
  66. 55 0
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/operate/hr/PositionBillDeleteOpPlugin.java
  67. 1 0
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/operate/hr/PositionBillEntrySaveOpPlugin.java
  68. 53 0
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/operate/hr/PositionBillSaveOpPlugin.java
  69. 8 7
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/operate/hr/validator/AbsBillPositionSaveValidator.java
  70. 1 0
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/operate/hr/validator/PositionAddSaveValidator.java
  71. 46 0
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/operate/hr/validator/PositionBillDeleteStatusValidator.java
  72. 21 0
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/operate/hr/validator/PositionBillEntryImportValidator.java
  73. 5 4
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/operate/hr/validator/PositionBillEntryNameValidator.java
  74. 4 3
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/operate/hr/validator/PositionBillEntryNumberValidator.java
  75. 175 0
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/operate/hr/validator/PositionBillSaveAndSubmitValidator.java
  76. 200 0
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/operate/hr/validator/PositionBillSaveValidator.java
  77. 16 0
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/operate/hr/validator/PositionChangeSaveValidator.java
  78. 12 0
      code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/common/PerfManagerFormConstant.java
  79. 93 11
      code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/form/print/BatchModDocstampPopupFormPlugin.java
  80. 35 6
      code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/form/print/PerfBatchPrintListPlugin.java
  81. 191 14
      code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/form/print/PrintPerfDetailReportListDataPlugin.java
  82. 9 0
      code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/form/result/AnnualPerfDetailFormPlugin.java
  83. 45 10
      code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/form/result/AnnualPerfDetailReportListDataPlugin.java
  84. 20 16
      code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/operate/cycle/CycleGenerateOpPlugin.java
  85. 9 9
      code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/operate/salary/SalaryAdjOpPlugin.java
  86. 14 2
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/business/coordination/SinsurCoordSplitService.java
  87. 2 1
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/opplugin/web/coordination/SinsurEmpConfirmOpEx.java
  88. 25 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/utils/SITCoordinationUtils.java
  89. 54 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/validate/web/SinsurEmpCoordConfirmEffectValidator.java
  90. 9 1
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/constants/MasConstant.java
  91. 81 2
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/constants/StmConstant.java
  92. 1 1
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/mas/plugin/form/assessmentmgm/EntldrMgrPerfAssmtFormPlugin.java
  93. 1 1
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/mas/plugin/form/assessmentmgm/EntldrMgrTermAssmtFormPlugin.java
  94. 1 1
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/mas/plugin/form/empmgt/LoadPartyPostPopupFormPlugin.java
  95. 1 1
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/mas/plugin/form/empmgt/LoadppDatePopupFormPlugin.java
  96. 9 8
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/mas/plugin/form/empmgt/SubCoHeadServiceListPlugin.java
  97. 8 7
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/mas/plugin/form/empmgt/TenurePersonListListPlugin.java
  98. 1 2
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/mas/plugin/form/incentivemgmt/AbstractIncentiveApprFormPlugin.java
  99. 1 2
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/mas/plugin/form/incentivemgmt/EntldrTermBonusApprFormPlugin.java
  100. 1 4
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/mas/plugin/form/structappr/AbstractStructApprFormPlugin.java

+ 42 - 0
code/base/nckd-jxccl-base-common/src/main/java/nckd/jxccl/base/common/algo/DistinctConcatFunction.java

@@ -0,0 +1,42 @@
+package nckd.jxccl.base.common.algo;
+
+import kd.bos.algo.CustomAggFunction;
+import kd.bos.algo.DataType;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+* 去重并按逗号拼接
+* @author W.Y.C
+* @date 2025/12/30 12:41
+* @version 1.0
+*/
+public class DistinctConcatFunction extends CustomAggFunction<Set<String>> {
+    
+    public DistinctConcatFunction() {
+        // “distinct_concat”是函数名,DataType.StringType 指定返回类型为字符串
+        super("distinct_concat", DataType.StringType);
+    }
+
+    public Set<String> newAggValue() {
+        return new HashSet<>();
+    }
+
+    public Set<String> addValue(Set<String> aggValue, Object value) {
+
+        aggValue = aggValue == null ?  new HashSet<>() : aggValue;
+        aggValue.add(String.valueOf(value));
+        return aggValue;
+    }
+
+    public Set<String> combineAggValue(Set<String> aggValue, Set<String> aggValue2) {
+        aggValue.addAll(aggValue2);
+        return aggValue;
+    }
+
+    public Object getResult(Set<String> aggValue) {
+        return aggValue == null ? "" : String.join(",", aggValue);
+    }
+}

+ 47 - 0
code/base/nckd-jxccl-base-common/src/main/java/nckd/jxccl/base/common/algo/GroupMaxStrFunction.java

@@ -0,0 +1,47 @@
+package nckd.jxccl.base.common.algo;
+
+import kd.bos.algo.CustomAggFunction;
+import kd.bos.algo.DataType;
+
+/**
+* 自定义聚合函数类(假设按字典序求最大字符串)
+* @author W.Y.C
+* @date 2025/12/27 16:57
+* @version 1.0
+*/
+public class GroupMaxStrFunction extends CustomAggFunction<String> {
+    public GroupMaxStrFunction() {
+        super("group_maxstr", DataType.StringType); // 注册函数名和返回类型
+    }
+
+    @Override
+    public String newAggValue() {
+        return ""; // 初始化为空字符串
+    }
+
+    @Override
+    public String addValue(String oldValue, Object newValue) {
+        String curRowData = String.valueOf(newValue);
+        // 按字典序比较,取较大值(若需其他规则,可修改比较逻辑)
+        return oldValue.compareTo(curRowData) < 0 ? curRowData : oldValue;
+    }
+
+    @Override
+    public String combineAggValue(String paramT1, String paramT2) {
+        // 如果不需要分批处理,可直接返回 null
+        return null;
+    }
+
+    @Override
+    public Object getResult(String result) {
+        return result;
+    }
+}
+/*
+
+// 2. 在业务代码中使用
+GroupMaxStrFunction groupMaxStr = new GroupMaxStrFunction();
+DataSet resultDataSet = dataSet.groupBy("分组字段")
+        .agg(groupMaxStr, "p_1", "max_p1") // 对 p_1 字段应用自定义聚合,结果别名为 max_p1
+        .finish();
+*/

+ 32 - 2
code/base/nckd-jxccl-base-common/src/main/java/nckd/jxccl/base/common/constant/FormConstant.java

@@ -15,8 +15,10 @@ public class FormConstant {
     public static final String DATA_MIGRATION = "dataMigration";
 
     //====================================== 标品应用ID ======================================
-    /** 消息中心应用ID */
+    /** 消息中心 */
     public static final String WFTASK_APP = "wftask";
+    /** 组织管理 */
+    public static final String HOMS_APP = "homs";
 
     //====================================== 标品实体标识(需要小写) ======================================
     /**学历-实体标识*/
@@ -31,6 +33,8 @@ public class FormConstant {
     public static final String HBSS_OCPQUALLEVEL = "hbss_ocpquallevel";
     /**职称信息-实体标识*/
     public static final String HRPI_PERPROTITLE = "hrpi_perprotitle";
+    /**员工技能信息-实体标识*/
+    public static final String NCKD_HRPI_EMPSKILL = "nckd_hrpi_empskill";
     /**职业资格-实体标识*/
     public static final String HRPI_PEROCPQUAL = "hrpi_perocpqual";
     /**职位序列-实体标识*/
@@ -136,6 +140,10 @@ public class FormConstant {
     public static final String BOS_LIST_ENTITY = "bos_list";
     /** HR组织树实体标识 */
     public static final String HAOS_ADMINORGTREELISTF7_ENTITY = "haos_adminorgtreelistf7";
+    /** 批量单组织F7-树实体标识 */
+    public static final String HAOS_ORGBATCHTREELISTF7_ENTITY = "haos_orgbatchtreelistf7";
+    /** 组织快速维护实体标识 */
+    public static final String HAOS_ADMINORGDETAIL_ENTITY = "haos_adminorgdetail";
 
     //====================================== 标品op ======================================
     /** 确认框确认按钮 */
@@ -186,6 +194,10 @@ public class FormConstant {
     public static final String MODIFY_OP = "modify";
     /** 修改按钮标识 */
     public static final String BAR_MODIFY_KEY = "bar_modify";
+    /** 查看流程图操作标识 */
+    public static final String VIEWFLOWCHART_OP = "viewflowchart";
+    /** 查看流程图按钮标识 */
+    public static final String BAR_VIEWFLOWCHART_KEY = "bar_viewflowchart";
 
 
     //====================================== 标品页面控件 ======================================
@@ -199,6 +211,8 @@ public class FormConstant {
     public static final String REPORTLISTAP = "reportlistap";
     /** 多选基础资料*/
     public static final String BASEDATAID_KEY = "fbasedataid";
+    /** 多选基础资料*/
+    public static final String FBASEDATAID_KEY = "fbasedataid";
     /** 多选基础资料的ID*/
     public static final String FBASEDATAID_ID_KEY = "fbasedataid_id";
     /**工具栏*/
@@ -222,7 +236,7 @@ public class FormConstant {
     /** 编号标识 */
     public static final String NUMBER_KEY = "number";
     /** 单据编号*/
-    public static final String BILL_NO_KEY = "BILLNO";
+    public static final String BILL_NO_KEY = "billno";
     /** 单据状态 */
     public static final String BILL_STATUS_KEY = "billstatus";
     /** 单据状态 */
@@ -301,6 +315,8 @@ public class FormConstant {
     public static final String STARTDATE = "startdate";
     /** 结束时间 */
     public static final String ENDDATE = "enddate";
+    /** 用工关系类型 */
+    public static final String LABORRELTYPE = "laborreltype";
     /** 本次加入集团日期*/
     public static final String JOINCOMDATE_KEY = "joincomdate";
     /** 首次加入集团日期*/
@@ -333,6 +349,12 @@ public class FormConstant {
     public static final String INITDATASOURCE = "initdatasource";
     /** 是否标准岗位 */
     public static final String ISSTANDARDPOS_KEY = "isstandardpos";
+    /** 生效日期 */
+    public static final String BSED_KEY = "bsed";
+    /** 失效日期 */
+    public static final String BSLED_KEY = "bsled";
+    /** 是否存在工作流 */
+    public static final String ISEXISTSWORKFLOW_KEY = "isexistsworkflow";
 
     /** 工具栏标识(二开)*/
     public static final String NCKD_TOOLBARAP = "nckd_toolbarap";
@@ -411,6 +433,8 @@ public class FormConstant {
     public static final String NCKD_ORG = "nckd_org";
     /** 人员 */
     public static final String NCKD_EMPLOYEE = "nckd_employee";
+    /** 技能名称 */
+    public static final String NCKD_QUALINAME = "nckd_qualiname";
 
     /** 描述*/
     public static final String NCKD_DESCRIPTION = "nckd_description";
@@ -466,5 +490,11 @@ public class FormConstant {
     public static final String NCKD_JOBTJOBTYPMAIN_LEAVE_NUMBER = "05";
     /**工龄年限*/
     public static final String SOCIALWORKAGE = "socialworkage";
+    /**是否最高学历*/
+    public static final String NCKD_ISHIGHDEG = "nckd_ishighdeg";
+    /**全日制*/
+    public static final String ISFULLTIME = "isfulltime";
+    /**全日制*/
+    public static final String NCKD_MONEY = "nckd_money";
 
 }

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

@@ -147,6 +147,17 @@ public class DateUtil {
         return dateTime.plusYears(years);
     }
 
+    /**
+     * 减年
+     *
+     * @param date 原始日期时间
+     * @param years    要减的年数
+     * @return 计算后的日期时间
+     */
+    public static Date minusYears(Date date, int years) {
+        return toDate(minusYears(toLocalDateTime(date), years));
+    }
+
     /**
      * 减年
      *
@@ -169,6 +180,17 @@ public class DateUtil {
         return dateTime.plusMonths(months);
     }
 
+    /**
+     * 加月
+     *
+     * @param date 原始日期时间
+     * @param months   要加的月数(可为负数)
+     * @return 计算后的日期时间
+     */
+    public static Date addMonths(Date date, int months) {
+        return toDate(addMonths(toLocalDateTime(date), months));
+    }
+
     /**
      * 减月
      *
@@ -419,6 +441,16 @@ public class DateUtil {
         return dateTime.toLocalDate().atStartOfDay();
     }
 
+    /**
+     * 获取月份的开始时间
+     *
+     * @param date 日期时间
+     * @return 当月第一天 00:00:00
+     */
+    public static Date beginOfMonth(Date date) {
+        return toDate(beginOfMonth(toLocalDateTime(date)));
+    }
+
     /**
      * 获取月份的开始时间
      *
@@ -492,6 +524,17 @@ public class DateUtil {
         return dateTime.with(TemporalAdjusters.lastDayOfMonth()).toLocalDate().atTime(LocalTime.MAX);
     }
 
+
+    /**
+     * 获取月份结束时间
+     *
+     * @param date 日期时间
+     * @return 当月最后一天 23:59:59.999999999
+     */
+    public static Date endOfMonth(Date dateTime) {
+        return toDate(endOfMonth(toLocalDateTime(dateTime)));
+    }
+
     /**
      * 获取季度结束时间
      *

+ 4 - 1
code/base/nckd-jxccl-base-helper/src/main/java/nckd/jxccl/base/hrpi/helper/EmpPosOrgRelHelper.java

@@ -170,7 +170,10 @@ public class EmpPosOrgRelHelper {
                 .and(FormConstant.IS_DELETED, QCP.equals, EnableEnum.NO.getCode())
                 .and(FormConstant.IS_PRIMARY, QCP.equals, EnableEnum.YES.getCode())
                 .and(FormConstant.STARTDATE, QCP.less_equals, new Date())
-                .and(FormConstant.ENDDATE, QCP.large_equals, new Date());
+                .and(FormConstant.ENDDATE, QCP.large_equals, new Date())
+                .and(FormConstant.ISCURRENTDATA, QCP.equals, EnableEnum.YES.getCode())
+                //在岗
+                .and(String.join( ".", FormConstant.POS_STATUS, FormConstant.POST_STATE_CLS, FormConstant.NUMBER_KEY),QCP.equals,"1010_S");
 
         // 添加额外查询条件(如果有)
         if (otherFilter != null) {

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

@@ -185,4 +185,24 @@ public final class QFilterCommonHelper {
 
         return beginFilter.and(endFilter.or(nullEndFilter));
     }
+
+    /**
+     * 获取有效时间范围内的QFilter实例
+     * 如果结束时间为空,则表示持续有效
+     * @param beginDateProperty 开始时间字段名
+     * @param endDateProperty 结束时间字段名
+     * @param date 获取的日期
+     * @return: kd.bos.orm.query.QFilter
+     * @author W.Y.C
+     * @date: 2025/07/07
+     */
+    public static QFilter getValidDateFilter(String beginDateProperty, String endDateProperty,Date date) {
+        // 创建组合条件 (beginTime <= currentTime AND (endTime >= currentTime OR endTime IS NULL))
+        Date currentDate = new Date();
+        QFilter beginFilter = new QFilter(beginDateProperty, QCP.less_equals, date);
+        QFilter endFilter = new QFilter(endDateProperty, QCP.large_equals, date);
+        QFilter nullEndFilter = new QFilter(endDateProperty, QCP.is_null, null);
+
+        return beginFilter.and(endFilter.or(nullEndFilter));
+    }
 }

+ 39 - 0
code/base/nckd-jxccl-base-helper/src/main/java/nckd/jxccl/base/swc/helper/SWCHelper.java

@@ -142,6 +142,45 @@ public class SWCHelper {
         return calTableDyns;
     }
 
+    /**
+     * 按薪资业务单元 和 薪酬项目查询薪酬数据
+     * @param orgIds
+     * @param startdate
+     * @param enddate
+     * @return
+     */
+    public static DynamicObjectCollection querySalaryByOrgList(List<Long> orgIds,List<String> itemNumber, Date startdate, Date enddate, String type) {
+
+        // 获取核算列表信息
+        QFilter filter = new QFilter("org.id", QCP.in, orgIds);
+        if(type.equals("10")){
+            filter.and("caltask.paydate", QCP.large_equals, startdate);
+            filter.and("caltask.paydate", QCP.less_equals, enddate);
+        }else{
+            filter.and("caltask.payrolldate", QCP.large_equals, startdate);
+            filter.and("caltask.payrolldate", QCP.less_equals, enddate);
+        }
+        if(itemNumber != null && !itemNumber.isEmpty()){
+            filter.and("hsas_caltableentry.salaryitem.number", QCP.in, itemNumber);
+        }
+        //filter.and("caltask.taskstatuse", QCP.equals, "4");   ///任务状态  已审核 7  审批通过 4
+        filter.and("hsas_caltableentry.calamountvalue", QCP.large_than, 0);
+        String orderStr = "hsas_caltableentry.salaryitem.statisticstag.number";
+        String selectFields = "calpersonid,caltask.id,caltask.org.name,caltask.calrule.name,caltask.calcount,hsas_caltableentry.salaryitem.number,hsas_caltableentry.salaryitem.name,hsas_caltableentry.calamountvalue,hsas_caltableentry.salaryitem.statisticstag.number,org.id";
+        if(type.equals("10")){
+            selectFields = selectFields + ",caltask.paydate as bizdate";
+            //orderStr = "caltask.paydate";
+        }else{
+            selectFields = selectFields + ",caltask.payrolldate as bizdate";
+            //orderStr = "caltask.payrolldate";
+        }
+        selectFields = selectFields + ",caltask.paydate,caltask.payrolldate";
+
+        DynamicObjectCollection calTableDyns = QueryServiceHelper.query(FormConstant.HSAS_CALTABLE, selectFields, new QFilter[]{filter}, orderStr);
+
+        return calTableDyns;
+    }
+
     /**
      * 根据用户ID查询员工ID
      * @param userId

+ 16 - 1
code/base/nckd-jxccl-base-helper/src/main/java/nckd/jxccl/base/wtc/helper/WTCHelper.java

@@ -2,6 +2,7 @@ package nckd.jxccl.base.wtc.helper;
 
 import kd.bos.dataentity.entity.DynamicObject;
 import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.dataentity.utils.ObjectUtils;
 import kd.bos.logging.Log;
 import kd.bos.logging.LogFactory;
 import kd.bos.orm.query.QCP;
@@ -28,6 +29,7 @@ public class WTCHelper {
     /* 工作流角色 */
     public static final HRBaseServiceHelper WFROLE_HELPER = new HRBaseServiceHelper("wf_role");
     public static final HRBaseServiceHelper VAAPPLY_HELPER = new HRBaseServiceHelper("wtabm_vaapply");
+    public static final HRBaseServiceHelper PARTYPOSH_HELPER = new HRBaseServiceHelper("nckd_hrpi_partyposh");
 
     /**
      * 根据考勤档案ID获取二级单位编码
@@ -209,5 +211,18 @@ public class WTCHelper {
         return subPositionDyns.stream().map(dyn -> dyn.getLong("id")).collect(Collectors.toList());
     }
 
-
+    /**
+     * 根据员工ID获取职务层级
+     * 员工档案-党政职务变更履历-职务层级
+     * @param employeeId
+     * @return
+     */
+    public static String getZwcjByEmployeeId(Long employeeId) {
+        QFilter filter = new QFilter("employee.id", QCP.equals, employeeId);
+        filter.and("startdate", QCP.less_equals, new Date());
+        filter.and("enddate", QCP.large_equals, new Date());
+        String selectFields = "nckd_posgrade.name";
+        DynamicObject dyn = PARTYPOSH_HELPER.queryOriginalOne(selectFields, filter.toArray());
+        return ObjectUtils.isEmpty(dyn)? null : dyn.getString("nckd_posgrade.name");
+    }
 }

+ 0 - 0
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/excells/business/.gitkeep


+ 39 - 0
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/excells/common/ExcellsConstant.java

@@ -0,0 +1,39 @@
+package nckd.jxccl.hr.excells.common;
+
+import nckd.jxccl.base.common.constant.FormConstant;
+
+/**
+ * 优秀生津贴常量类
+ *
+ * @author W.Y.C
+ * @version 1.0
+ * @date 2026-01-02 20:48:06
+ */
+public class ExcellsConstant extends FormConstant {
+    /** 优秀生津贴-实体标识 */
+    public static final String EXCELLENTSSALLOWANCE_ENTITYID = "nckd_excellentssallowance";
+    /** 金额 */
+    public static final String NCKD_MONEY = "nckd_money";
+    /** 生效日期 */
+    public static final String NCKD_EFFDT = "nckd_effdt";
+    /** 失效日期 */
+    public static final String NCKD_LEFFDT = "nckd_leffdt";
+    /** 说明 */
+    public static final String NCKD_DESC = "nckd_desc";
+    /** 岗位 */
+    public static final String NCKD_POSITION = "nckd_position";
+    /** 全日制最高学历 */
+    public static final String NCKD_PEREDUEXP = "nckd_pereduexp";
+    /** 优秀生类型 */
+    public static final String NCKD_HONORTYPE = "nckd_honortype";
+    /** 本科专业 */
+    public static final String NCKD_UNDERGRADMAJOR = "nckd_undergradmajor";
+    /** 本科毕业学校 */
+    public static final String NCKD_UNIV = "nckd_univ";
+    /** 上年度绩效结果 */
+    public static final String NCKD_APPRAISALRESULT = "nckd_appraisalresult";
+    /** 上年度单元排名 */
+    public static final String NCKD_RANKANDTOTAL = "nckd_rankandtotal";
+    /** 全日制最高学历毕业时间(折算)*/
+    public static final String NCKD_FTTOPGRAD = "nckd_fttopgrad";
+}

+ 0 - 0
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/excells/mservice/.gitkeep


+ 279 - 0
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/excells/plugin/form/ExcellentssAllowanceFormPlugin.java

@@ -0,0 +1,279 @@
+package nckd.jxccl.hr.excells.plugin.form;
+
+import kd.bos.common.enums.EnableEnum;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.dataentity.entity.ILocaleString;
+import kd.bos.dataentity.metadata.IDataEntityProperty;
+import kd.bos.entity.BasedataEntityType;
+import kd.bos.entity.EntityMetadataCache;
+import kd.bos.entity.MainEntityType;
+import kd.bos.entity.datamodel.events.ChangeData;
+import kd.bos.entity.datamodel.events.IDataModelChangeListener;
+import kd.bos.entity.datamodel.events.PropertyChangedArgs;
+import kd.bos.entity.property.BasedataProp;
+import kd.bos.form.field.BasedataEdit;
+import kd.bos.form.field.events.AfterBindingDataEvent;
+import kd.bos.form.field.events.BasedataEditListener;
+import kd.bos.form.field.events.BeforeF7SelectEvent;
+import kd.bos.form.field.events.BeforeF7SelectListener;
+import kd.bos.form.plugin.AbstractFormPlugin;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
+import kd.bos.servicehelper.BusinessDataServiceHelper;
+import kd.bos.servicehelper.QueryServiceHelper;
+import kd.sdk.plugin.Plugin;
+import nckd.jxccl.base.common.constant.FormConstant;
+import nckd.jxccl.base.common.utils.ConvertUtil;
+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.excells.common.ExcellsConstant;
+
+import java.time.LocalDateTime;
+import java.util.Date;
+import java.util.EventObject;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+/**
+* 优秀生津贴
+* 实体标识:nckd_excellentssallowance
+* @author W.Y.C
+* @date 2026/1/2 20:49
+* @version 1.0
+*/
+public class ExcellentssAllowanceFormPlugin extends AbstractFormPlugin implements Plugin, BeforeF7SelectListener, BasedataEditListener, IDataModelChangeListener {
+
+    @Override
+    public void registerListener(EventObject e) {
+        // 1. 获取基础资料字段控件
+        BasedataEdit materialEdit = this.getView().getControl(FormConstant.NCKD_PERSON);
+        if(materialEdit != null) {
+            // 2. 注册 beforeF7Select 事件监听器
+            materialEdit.addBeforeF7SelectListener(this);
+        }
+
+        BasedataEdit mulEdit = this.getControl("nckd_pereduexp");
+        mulEdit.addBasedataEditListener(this);
+    }
+
+
+    @Override
+    public void beforeF7Select(BeforeF7SelectEvent event) {
+        String fieldName = event.getProperty().getName();
+        if (FormConstant.NCKD_PERSON.equals(fieldName)) {
+            //查询优秀生
+            QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create().addIdNumberName(FormConstant.EMPLOYEE_KEY).add("nckd_fttopgrad");
+            QFilter qFilter = new QFilter(ExcellsConstant.NCKD_HONORTYPE, QCP.is_notnull, null)
+                    .and(ExcellsConstant.NCKD_HONORTYPE, QCP.large_equals, 0);
+            DynamicObjectCollection query = QueryServiceHelper.query("nckd_hrpi_topstudent", queryFieldBuilder.buildSelect(), new QFilter[]{qFilter});
+            LocalDateTime tenYearsAgo = DateUtil.addYears(DateUtil.now(), 10);
+
+            Date date = DateUtil.toDate(tenYearsAgo);
+            List<Long> personId = query.stream()
+                    .filter(dynamicObject -> {
+                        Date nckdFttopgrad = dynamicObject.getDate("nckd_fttopgrad");
+                        if (nckdFttopgrad == null) {
+                            return false; // 排除空值
+                        }
+                        LocalDateTime nckdFttopgradLocalDateTime = DateUtil.toLocalDateTime(nckdFttopgrad);
+                        return nckdFttopgrad.compareTo(date) <= 0;
+                    })
+                    .map(dynamicObject -> dynamicObject.getLong(String.join(".", FormConstant.EMPLOYEE_KEY, FormConstant.ID_KEY)))
+                    .collect(Collectors.toList());
+            // 4. 创建过滤条件:物料编码 like 'Item%'
+            QFilter filter = new QFilter(FormConstant.ID_KEY, QCP.in, personId);
+            // 5. 将条件添加到事件中
+            event.getCustomQFilters().add(filter);
+        }
+    }
+
+    @Override
+    public void propertyChanged(PropertyChangedArgs e) {
+        String name = e.getProperty().getName();
+        ChangeData[] changeSet = e.getChangeSet();
+        Object newValue = changeSet[0].getNewValue();
+        Object oldValue = changeSet[0].getOldValue();
+        if(FormConstant.NCKD_PERSON.equalsIgnoreCase( name)){
+            int rowIndex = changeSet[0].getRowIndex();
+            if(newValue != null) {
+                if(!Objects.equals(newValue, oldValue)) {
+                    DynamicObject person = ConvertUtil.toDynamicObjectOrNull(newValue);
+                    if (person != null) {
+                        initValue(person.getLong(FormConstant.ID_KEY), rowIndex);
+
+                        Date effdt = ConvertUtil.toDate(this.getModel().getValue(ExcellsConstant.NCKD_EFFDT, rowIndex));
+                        if (effdt != null) {
+                            lastPerfRank(person.getLong(FormConstant.ID_KEY), effdt, rowIndex);
+                        }
+                    }
+                }
+
+            }else{
+                this.getModel().setValue(ExcellsConstant.NCKD_DEP,null,rowIndex);
+                this.getModel().setValue(ExcellsConstant.NCKD_FTTOPGRAD,null,rowIndex);
+                this.getModel().setValue(ExcellsConstant.NCKD_POSITION,null,rowIndex);
+                this.getModel().setValue(ExcellsConstant.NCKD_UNIV,null,rowIndex);
+                this.getModel().setValue(ExcellsConstant.NCKD_UNDERGRADMAJOR,null,rowIndex);
+                this.getModel().setValue(ExcellsConstant.NCKD_PEREDUEXP,null,rowIndex);
+                this.getModel().setValue(ExcellsConstant.NCKD_HONORTYPE,null,rowIndex);
+                this.getModel().setValue(ExcellsConstant.NCKD_RANKANDTOTAL,null, rowIndex);
+                this.getModel().setValue(ExcellsConstant.NCKD_APPRAISALRESULT, null,rowIndex);
+            }
+        }else if("nckd_effdt".equalsIgnoreCase( name)){
+            int rowIndex = changeSet[0].getRowIndex();
+            if(newValue != null) {
+                if(!Objects.equals(newValue, oldValue)) {
+                    Date date = ConvertUtil.toDate(this.getModel().getValue(ExcellsConstant.NCKD_EFFDT));
+
+                    Object value = this.getModel().getValue(FormConstant.NCKD_PERSON, rowIndex);
+                    if (date != null && value != null) {
+                        DynamicObject person = ConvertUtil.toDynamicObjectOrNull(value);
+                        if (person != null) {
+                            lastPerfRank(person.getLong(FormConstant.ID_KEY), date, rowIndex);
+                        }
+                    }
+                }
+            }else{
+                this.getModel().setValue(ExcellsConstant.NCKD_RANKANDTOTAL,null, rowIndex);
+                this.getModel().setValue(ExcellsConstant.NCKD_APPRAISALRESULT, null,rowIndex);
+            }
+
+
+
+        }
+    }
+
+    private void lastPerfRank(Long personId, Date date, int rowIndex) {
+        if(personId != null && personId > 0) {
+            Date lastDate = DateUtil.minusYears(date, 1);
+            //上年度绩效和排名
+            QueryFieldBuilder perfRankMgmtFieldBuilder = QueryFieldBuilder.create()
+                    .add("nckd_topranks")
+                    .addGroup(new String[]{"nckd_perfrankmgmtentry"}, "nckd_toprank")
+                    .addIdNumberName("nckd_perfrankmgmtentry", "nckd_appraisalresult");
+            QFilter qFilter1 = new QFilter(String.join(".", "nckd_perfrankmgmtentry", "nckd_person"), QCP.equals, personId)
+                    .and("nckd_theyear", QCP.less_equals, DateUtil.getYear(lastDate));
+            DynamicObjectCollection query = QueryServiceHelper.query("nckd_perfrankmgmt", perfRankMgmtFieldBuilder.buildSelect(), new QFilter[]{qFilter1});
+            if(!query.isEmpty()){
+                String topRanks = query.get(0).getString("nckd_topranks");
+                String topRank = query.get(0).getString(String.join(".", "nckd_perfrankmgmtentry", "nckd_toprank"));
+                this.getModel().setValue(ExcellsConstant.NCKD_RANKANDTOTAL,topRank+"/"+topRanks, rowIndex);
+                long appraisalResultId = query.get(0).getLong(String.join(".", "nckd_perfrankmgmtentry", "nckd_appraisalresult", FormConstant.ID_KEY));
+                if(appraisalResultId > 0) {
+                    DynamicObject dynamicObject = EntityHelper.newEntity("nckd_appraisalresult", appraisalResultId);
+                    String appraisalResultName = query.get(0).getString(String.join(".", "nckd_perfrankmgmtentry", "nckd_appraisalresult", FormConstant.NAME_KEY));
+                    dynamicObject.set(FormConstant.NAME_KEY, appraisalResultName);
+                    this.getModel().setValue(ExcellsConstant.NCKD_APPRAISALRESULT, dynamicObject,rowIndex);
+                }
+            }
+        }
+    }
+
+    private void initValue(Long personId,int rowIndex){
+        //任职经历
+        DynamicObject empPosOrgRel = EmpPosOrgRelHelper.queryEmpPosOrgRelByEmployees(personId);
+        if(empPosOrgRel != null) {
+            this.getModel().setValue(ExcellsConstant.NCKD_DEP,empPosOrgRel.getDynamicObject(FormConstant.ADMINORG),rowIndex);
+            this.getModel().setValue(ExcellsConstant.NCKD_POSITION,empPosOrgRel.getDynamicObject(FormConstant.POSITION_KEY),rowIndex);
+        }
+
+        //--------------------------- 最高学历 和 本科学历 begin --------------------------
+        QueryFieldBuilder perEduExpFieldBuilder = QueryFieldBuilder.create().add(FormConstant.ID_KEY);
+        QFilter highEducationFilter = new QFilter(ExcellsConstant.ISFULLTIME, QCP.equals, EnableEnum.YES.getCode());
+        //本科
+        QFilter undergradEducationFilter = new QFilter(String.join(".",ExcellsConstant.EDUCATION_KEY,FormConstant.NUMBER_KEY), QCP.equals, "1030_S");
+        QFilter educationFilter = highEducationFilter.or(undergradEducationFilter).and(FormConstant.EMPLOYEE_KEY, QCP.equals, personId);
+        DynamicObjectCollection perEduExp = QueryServiceHelper.query(FormConstant.HRPI_PEREDUEXP, perEduExpFieldBuilder.buildSelect(), new QFilter[]{educationFilter});
+        List<Long> eduExpIds = perEduExp.stream().map(dynamicObject -> dynamicObject.getLong(FormConstant.ID_KEY)).collect(Collectors.toList());
+        MainEntityType eduExpEntityType = EntityMetadataCache.getDataEntityType(FormConstant.HRPI_PEREDUEXP);
+        DynamicObject[] eduExpArray = BusinessDataServiceHelper.load(eduExpIds.toArray(new Long[0]), eduExpEntityType);
+        for (DynamicObject eduExp : eduExpArray) {
+            boolean isFulltime = eduExp.getBoolean(FormConstant.ISFULLTIME);
+            DynamicObject education = eduExp.getDynamicObject(ExcellsConstant.EDUCATION_KEY);
+            String educationNumber = education.getString(FormConstant.NUMBER_KEY);
+            if("1030_S".equalsIgnoreCase(educationNumber)){
+                this.getModel().setValue(ExcellsConstant.NCKD_UNIV,eduExp.getString("schoolrecord"),rowIndex);
+                this.getModel().setValue(ExcellsConstant.NCKD_UNDERGRADMAJOR,eduExp.getString("major"),rowIndex);
+            }
+            if(isFulltime){
+                this.getModel().setValue(ExcellsConstant.NCKD_PEREDUEXP,eduExp,rowIndex);
+            }
+        }
+        //--------------------------- 最高学历 和 本科学历 end --------------------------
+
+        //--------------------------- 优秀生类型 begin --------------------------
+        QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create().addIdNumberName(ExcellsConstant.NCKD_HONORTYPE).add(ExcellsConstant.NCKD_FTTOPGRAD);
+        QFilter qFilter = new QFilter(ExcellsConstant.NCKD_HONORTYPE, QCP.is_notnull, null)
+                .and(ExcellsConstant.NCKD_HONORTYPE, QCP.large_equals, 0)
+                .and(FormConstant.EMPLOYEE_KEY, QCP.equals, personId);
+        DynamicObjectCollection query = QueryServiceHelper.query("nckd_hrpi_topstudent", queryFieldBuilder.buildSelect(), new QFilter[]{qFilter});
+        if(!query.isEmpty()) {
+            List<Long> collect = query.stream().map(dynamicObject -> dynamicObject.getLong(String.join(".", ExcellsConstant.NCKD_HONORTYPE, FormConstant.ID_KEY))).collect(Collectors.toList());
+            MainEntityType honorTypeEntityType = EntityMetadataCache.getDataEntityType("nckd_hbss_honortype");
+            DynamicObject[] honorTypeArray = BusinessDataServiceHelper.load(collect.toArray(new Long[0]), honorTypeEntityType);
+            if (honorTypeArray != null && honorTypeArray.length > 0) {
+                this.getModel().setValue(ExcellsConstant.NCKD_HONORTYPE, honorTypeArray[0], rowIndex);
+                this.getModel().setValue(ExcellsConstant.NCKD_FTTOPGRAD, query.get(0).getDate(ExcellsConstant.NCKD_FTTOPGRAD), rowIndex);
+            }
+        }
+        //--------------------------- 优秀生类型 begin --------------------------
+    }
+
+
+    @Override
+    public void afterBindingData(AfterBindingDataEvent evt) {
+        BasedataEdit edit = (BasedataEdit) evt.getSource();
+        String fieldKey = edit.getFieldKey();
+        //修改“全日制最高学历”F7显示字段
+        if ("nckd_pereduexp".equalsIgnoreCase(fieldKey)) {
+            Object v = evt.getDataEntity();
+            Object editSearchProp = null;
+            Object displayProp = "";
+            if (v == null) {
+                return;
+            }
+
+            BasedataEntityType dt;
+            if (((DynamicObject) v).getDataEntityType() instanceof BasedataEntityType) {
+                dt = (BasedataEntityType) ((DynamicObject) v).getDataEntityType();
+            } else {
+                dt = (BasedataEntityType) ((BasedataProp) edit.getProperty()).getComplexType();
+            }
+
+            //获取数据包中的名称字段值
+            String nameKey = dt.getNameProperty();
+            IDataEntityProperty p2 = dt.findProperty(nameKey);
+            if (p2 != null) {
+                displayProp = p2.getValueFast(v);
+                if (displayProp instanceof ILocaleString) {
+                    displayProp = displayProp.toString();
+                }
+            }
+
+            //动态修改基础资料的显示属性为名称(部门)
+            if ("nckd_pereduexp".equals(edit.getKey())) {
+                nameKey = "education";
+            }
+            IDataEntityProperty p4 = dt.findProperty(nameKey);
+            if (p4 != null) {
+                Object valueFast = p4.getValueFast(v);
+                if (valueFast instanceof DynamicObject) {
+                    displayProp = ConvertUtil.toDynamicObjectOrNull(valueFast).getString(FormConstant.NAME_KEY);
+                    editSearchProp = ConvertUtil.toDynamicObjectOrNull(valueFast).getString(FormConstant.NUMBER_KEY);
+
+                }
+            }
+
+            //设置显示属性
+            evt.setDisplayProp(displayProp.toString());
+            //设置编辑显示属性
+            evt.setEditSearchProp(editSearchProp == null ? "" : editSearchProp.toString());
+
+        }
+    }
+
+}

+ 237 - 0
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/excells/plugin/operate/PushAdjustOpPlugin.java

@@ -0,0 +1,237 @@
+package nckd.jxccl.hr.excells.plugin.operate;
+
+import com.alibaba.fastjson.JSON;
+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.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.AfterOperationArgs;
+import kd.bos.entity.plugin.args.BeginOperationTransactionArgs;
+import kd.bos.entity.validate.BillStatus;
+import kd.bos.logging.Log;
+import kd.bos.logging.LogFactory;
+import kd.bos.servicehelper.BusinessDataServiceHelper;
+import kd.bos.servicehelper.DispatchServiceHelper;
+import kd.bos.servicehelper.operation.SaveServiceHelper;
+import kd.sdk.plugin.Plugin;
+import kd.sdk.swc.hcdm.business.helper.HCDMApplyBillServiceHelper;
+import nckd.jxccl.base.common.constant.FormConstant;
+import nckd.jxccl.base.common.exception.ValidationException;
+import nckd.jxccl.base.common.utils.ConvertUtil;
+import nckd.jxccl.base.common.utils.DateUtil;
+import nckd.jxccl.base.common.utils.StrFormatter;
+import nckd.jxccl.base.hrpi.helper.EmpPosOrgRelHelper;
+import nckd.jxccl.hr.excells.common.ExcellsConstant;
+import nckd.jxccl.hr.hstu.common.HonorStudentConstant;
+import nckd.jxccl.hr.psms.common.PositionStructureConstant;
+
+import java.util.ArrayList;
+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_excellentssallowance
+* @author W.Y.C
+* @date 2026/1/3 15:11
+* @version 1.0
+*/
+public class PushAdjustOpPlugin extends AbstractOperationServicePlugIn implements Plugin {
+
+    private static final Log logger = LogFactory.getLog(PushAdjustOpPlugin.class);
+
+    @Override
+    public void onAddValidators(AddValidatorsEventArgs e) {
+        super.onAddValidators(e);
+    }
+
+    @Override
+    public void onPreparePropertys(PreparePropertysEventArgs e) {
+        e.getFieldKeys().addAll(this.billEntityType.getAllFields().keySet());
+    }
+
+    @Override
+    public void beginOperationTransaction(BeginOperationTransactionArgs e) {
+
+        List<Long> ids = new ArrayList<>();
+        List<Long> personIds = new ArrayList<>();
+        for (DynamicObject data : e.getDataEntities()) {
+            DynamicObjectCollection entitys = data.getDynamicObjectCollection(FormConstant.NCKD_ENTRYENTITY);
+            for (DynamicObject entity : entitys) {
+                personIds.add(entity.getLong(String.join(".",FormConstant.NCKD_PERSON,FormConstant.ID_KEY)));
+            }
+            ids.add(data.getLong(FormConstant.ID_KEY));
+        }
+
+        //获取员工最新任职
+        Map<Long, DynamicObject> empPosOrgRelByEmployeesMap = EmpPosOrgRelHelper.queryEmpPosOrgRelByEmployeesMap(personIds);
+        List<Long> allEmpPosOrgRelIds = empPosOrgRelByEmployeesMap.values().stream()
+                .map(result -> result.getLong(FormConstant.ID_KEY))
+                .collect(Collectors.toList());
+
+        Map<String, Object> adjFileParams = new HashMap<>();
+        adjFileParams.put("employees", personIds);
+        List<String> status = new ArrayList<>();
+        status.add(BillStatus.C.toString());
+        adjFileParams.put("status", status);
+        //获取人员定薪档案
+        Map<String, Object> adjFileResult = DispatchServiceHelper.invokeBizService("swc", "hcdm", "IAdjFileInfoService", "queryAdjFileBoByEmp", adjFileParams);
+        Map<Long,Long> adjFileIdMap = new HashMap<>();
+        //key:定调薪档案ID,Value:发薪组织ID
+        Map<Long,Long> adjFileOrgIdMap = new HashMap<>();
+        if (ConvertUtil.toBoolean(adjFileResult.get("success"))) {
+            List<Map> list = ConvertUtil.toList(adjFileResult.get("data"), ArrayList::new);
+            for (Map map : list) {
+                Long id = ConvertUtil.toLong(map.get(FormConstant.ID_KEY));
+                //根据员工任职匹配
+                Long empPosOrgRelId = ConvertUtil.toLong(map.get("empposorgrel_id"));
+                if (allEmpPosOrgRelIds.contains(empPosOrgRelId)) {
+                    adjFileIdMap.put(ConvertUtil.toLong(map.get("employee_id")),id);
+                    adjFileOrgIdMap.put(id,ConvertUtil.toLong(map.get("org_id")));
+                }
+            }
+        }
+        //多人可能存在不同发薪组织,按单据和组织拆分定调薪单据。key:单据id-组织ID,value:申请单数据
+        Map<String,Map<String, Object>> applyBillMap = new HashMap<>();
+        for (DynamicObject data : e.getDataEntities()) {
+            boolean isSalAdjPush = data.getBoolean(PositionStructureConstant.NCKD_ISSALADJPUSH);
+            if(isSalAdjPush){
+                logger.warn("优秀生津贴单据号【{}】已推送过优秀生津贴申请单,忽略此次执行。",data.getString(FormConstant.BILL_NO_KEY));
+                continue;
+            }
+            long id = data.getLong(FormConstant.ID_KEY);
+            DynamicObject org = data.getDynamicObject(FormConstant.NCKD_ORG);
+            DynamicObject creator = data.getDynamicObject(FormConstant.CREATOR_KEY);
+
+            DynamicObjectCollection entitys = data.getDynamicObjectCollection(FormConstant.NCKD_ENTRYENTITY);
+            for (DynamicObject entity : entitys) {
+                DynamicObject person = entity.getDynamicObject(FormConstant.NCKD_PERSON);
+                Long employeeId = person.getLong(FormConstant.ID_KEY);
+                Long adjFileId = adjFileIdMap.get(employeeId);
+                Long orgId = adjFileOrgIdMap.get(adjFileId);
+                Map<String, Object> applyBill = applyBillMap.computeIfAbsent(id+"-"+orgId, k -> new HashMap<>());
+                applyBill.put("billname", StrFormatter.format("【{}】申请的优秀生津贴,申请单号:【{}】",creator.getString(FormConstant.NAME_KEY),data.getString(FormConstant.BILL_NO_KEY)));
+                applyBill.put("_uniquecode", data.getLong(FormConstant.ID_KEY));
+                applyBill.put("org", orgId);
+                //定调薪明细字段显示方案   调薪明细字段
+                applyBill.put("billtype", 2215975998602655744L);
+                //国家
+                applyBill.put("billcountry", 1000001L);
+                //定调薪类型(优秀生津贴)
+                applyBill.put("salaryadjrsn", 2352338051369287680L);
+                //默认币种
+                applyBill.put("billcurrency", 1L);
+                //定调薪方案
+                applyBill.put("salaryadjscm", 2322515162646457344L);
+                //汇率日期
+                applyBill.put("exchangeratedate", new Date());
+                //汇率表
+                applyBill.put("exctable", 2321965096026258432L);
+                //默认生效日期
+                applyBill.put("effectivedate", data.getDate(FormConstant.CREATE_TIME_KEY));
+                //草稿状态
+                applyBill.put("isdraft", "1");
+                //审核状态
+                applyBill.put("auditstatus", "A");
+                //申请单数据来源   //1:手工新增  2:接口写入
+                applyBill.put("datasource", "2");
+                applyBill.put("description",  StrFormatter.format("【{}】申请的优秀生津贴,申请单号:【{}】,申请日期:【{}】",creator.getString(FormConstant.NAME_KEY),data.getString(FormConstant.BILL_NO_KEY), DateUtil.format(data.getDate(FormConstant.CREATE_TIME_KEY),DateUtil.NORM_DATETIME_PATTERN)));
+                List<Map<String, Object>> applyBillEntryData = (List<Map<String, Object>>) applyBill.computeIfAbsent("applybillent", k -> new ArrayList<Map<String, Object>>());
+
+                DynamicObject position = entity.getDynamicObject(FormConstant.NCKD_POSITION_KEY);
+                Map<String, Object> applyBillEntry = new HashMap<>();
+                applyBillEntry.put("adjfile", adjFileId);
+                applyBillEntry.put("employee", employeeId);
+                applyBillEntry.put("standarditem", 2321901326927149056L);    //定调薪项目
+                applyBillEntry.put("frequency", 1095454108284088320L);       //频度  月
+                applyBillEntry.put("amount", entity.getBigDecimal(FormConstant.NCKD_MONEY));
+                applyBillEntry.put("position", position.getLong(FormConstant.ID_KEY));
+                applyBillEntry.put("reason", entity.getString(ExcellsConstant.NCKD_DESC));
+                applyBillEntry.put("startdate", entity.getDate(ExcellsConstant.NCKD_EFFDT));
+                applyBillEntry.put("enddate", entity.getDate(ExcellsConstant.NCKD_LEFFDT) == null ? DateUtil.getMaxDateAsDate() : entity.getDate(ExcellsConstant.NCKD_LEFFDT));
+                applyBillEntryData.add(applyBillEntry);
+                applyBill.put("applybillent", applyBillEntryData);
+                applyBillMap.put(id+"-"+orgId, applyBill);
+            }
+        }
+        if(!applyBillMap.isEmpty()) {
+
+
+            Map<String, Object> papams = new HashMap<>();
+            List<Map<String, Object>> applybillList = new ArrayList<>();
+            for (Map.Entry<String, Map<String, Object>> stringMapEntry : applyBillMap.entrySet()) {
+                applybillList.add(stringMapEntry.getValue());
+            }
+            papams.put("data", applybillList);
+            papams.put("isUseMatchAmount", Boolean.TRUE);
+            List<DynamicObject> saveDynamicObjects = new ArrayList<>();
+            TXHandle tx = TX.requiresNew();
+            try {
+                Map<String, Object> result = HCDMApplyBillServiceHelper.saveDraftApplyBill(papams);
+                logger.info("推送定调薪结果:{}", JSON.toJSONString(result));
+
+                if (!ConvertUtil.toBoolean(result.get("success")) || result.get("data") == null || ConvertUtil.toList(result.get("data")).isEmpty()) {
+                    logger.error("推送定调薪失败,原因:{}", JSON.toJSONString(result));
+                    throw new ValidationException("推送定调薪失败,原因:" + JSON.toJSONString(result));
+                } else {
+                    MainEntityType depEmpEntityType = EntityMetadataCache.getDataEntityType(ExcellsConstant.EXCELLENTSSALLOWANCE_ENTITYID);
+                    List<Map<String, Object>> list = ConvertUtil.toList(result.get("data"));
+                    for (DynamicObject dynamicObject : e.getDataEntities()) {
+                        long id = dynamicObject.getLong(FormConstant.ID_KEY);
+                        for (Map<String, Object> dataMap : list) {
+                            Long uniqueCode = ConvertUtil.toLong(dataMap.get("_uniquecode"));
+                            if (id == uniqueCode) {
+                                dynamicObject.set(PositionStructureConstant.NCKD_ISSALADJPUSH, Boolean.TRUE);
+                                dynamicObject.set(PositionStructureConstant.NCKD_SALADJPUSHTIME, new Date());
+//                                dynamicObject.set(PositionStructureConstant.NCKD_SALADJID, adjInfoId);
+
+                            }
+                            logger.info("成功推送的定调薪申请单,申请单ID: {}", uniqueCode);
+                            saveDynamicObjects.add(dynamicObject);
+                        }
+                    }
+                    tx.commit();
+                }
+            } catch (Exception ex) {
+                tx.markRollback();
+                throw ex;
+            }finally {
+                tx.close();
+            }
+
+            if (!saveDynamicObjects.isEmpty()) {
+                SaveServiceHelper.update(saveDynamicObjects.toArray(new DynamicObject[0]));
+                /*OperationResult operationResult = SaveServiceHelper.saveOperate(ExcellsConstant.EXCELLENTSSALLOWANCE_ENTITYID, saveDynamicObjects.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());
+                    }
+                    logger.error("保存职位津贴失败,原因:{}", errorMsg.toString());
+                    throw new ValidationException("保存职位津贴失败,原因:" + errorMsg.toString());
+                } else {
+                    logger.info("成功保存 {} 条职位津贴记录", saveDynamicObjects.size());
+                }*/
+            }
+        }
+    }
+
+
+
+}

+ 83 - 0
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/excells/plugin/operate/validate/ExcellentssAllowanceValiDate.java

@@ -0,0 +1,83 @@
+package nckd.jxccl.hr.excells.plugin.operate.validate;
+
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.entity.ExtendedDataEntity;
+import kd.bos.entity.validate.AbstractValidator;
+import kd.bos.entity.validate.BillStatus;
+import kd.bos.form.plugin.AbstractFormPlugin;
+import kd.bos.servicehelper.DispatchServiceHelper;
+import kd.sdk.plugin.Plugin;
+import nckd.jxccl.base.common.constant.FormConstant;
+import nckd.jxccl.base.common.utils.ConvertUtil;
+import nckd.jxccl.base.common.utils.StrFormatter;
+import nckd.jxccl.base.hrpi.helper.EmpPosOrgRelHelper;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+* 优秀生津贴验证
+* 实体标识:nckd_excellentssallowance
+* @author W.Y.C
+* @date 2026/1/3 16:34
+* @version 1.0
+*/
+public class ExcellentssAllowanceValiDate extends AbstractValidator {
+
+    @Override
+    public void validate() {
+        List<Long> personIds = new ArrayList<>();
+        for (ExtendedDataEntity dataEntity : this.getDataEntities()) {
+            DynamicObject data = dataEntity.getDataEntity();
+            DynamicObjectCollection entrys = data.getDynamicObjectCollection(FormConstant.NCKD_ENTRYENTITY);
+            for (DynamicObject entry : entrys) {
+                personIds.add(entry.getLong(String.join( ".", FormConstant.NCKD_PERSON, FormConstant.ID_KEY)));
+            }
+        }
+        if(!personIds.isEmpty()) {
+            //获取员工最新任职
+            Map<Long, DynamicObject> empPosOrgRelByEmployeesMap = EmpPosOrgRelHelper.queryEmpPosOrgRelByEmployeesMap(personIds);
+            List<Long> allEmpPosOrgRelIds = empPosOrgRelByEmployeesMap.values().stream()
+                    .map(result -> result.getLong(FormConstant.ID_KEY))
+                    .collect(Collectors.toList());
+
+            Map<String, Object> adjFileParams = new HashMap<>();
+            adjFileParams.put("employees", personIds);
+            List<String> status = new ArrayList<>();
+            status.add(BillStatus.C.toString());
+            adjFileParams.put("status", status);
+            //获取人员定薪档案
+            Map<String, Object> adjFileResult = DispatchServiceHelper.invokeBizService("swc", "hcdm", "IAdjFileInfoService", "queryAdjFileBoByEmp", adjFileParams);
+            Map<Long, Long> adjFileIdMap = new HashMap<>();
+            if (ConvertUtil.toBoolean(adjFileResult.get("success"))) {
+                List<Map> list = ConvertUtil.toList(adjFileResult.get("data"), ArrayList::new);
+                for (Map map : list) {
+                    Long id = ConvertUtil.toLong(map.get(FormConstant.ID_KEY));
+                    //根据员工任职匹配
+                    Long empPosOrgRelId = ConvertUtil.toLong(map.get("empposorgrel_id"));
+                    if (allEmpPosOrgRelIds.contains(empPosOrgRelId)) {
+                        adjFileIdMap.put(ConvertUtil.toLong(map.get("employee_id")), id);
+                    }
+                }
+            }
+            for (ExtendedDataEntity dataEntity : this.getDataEntities()) {
+                DynamicObject data = dataEntity.getDataEntity();
+                DynamicObjectCollection entrys = data.getDynamicObjectCollection(FormConstant.NCKD_ENTRYENTITY);
+                for (DynamicObject entry : entrys) {
+                    DynamicObject person = entry.getDynamicObject(FormConstant.NCKD_PERSON);
+                    if(person != null) {
+                        long personId = person.getLong(FormConstant.ID_KEY);
+                        String personName = person.getString(FormConstant.NAME_KEY);
+                        if (adjFileIdMap.get(personId) == null) {
+                            this.addFatalErrorMessage(dataEntity, StrFormatter.format("人员【{}】定薪档案不存在", personName));
+                        }
+                    }
+                }
+            }
+        }
+    }
+}

+ 0 - 0
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/excells/plugin/other/.gitkeep


+ 0 - 0
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/excells/plugin/report/.gitkeep


+ 0 - 0
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/excells/plugin/workflow/.gitkeep


+ 0 - 0
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/excells/webapi/.gitkeep


+ 1 - 1
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/homs/business/application/event/GenerateEmploymentContractEventServicePlugin.java

@@ -67,7 +67,7 @@ public class GenerateEmploymentContractEventServicePlugin implements IEventServi
         }
 
         public long getPkId() {
-            return this.pkId;// 37
+            return this.pkId;
         }
     }
 

+ 1 - 4
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/htm/plugin/form/quitapply/QuitApplyFormPlugin.java

@@ -1,10 +1,8 @@
 package nckd.jxccl.hr.htm.plugin.form.quitapply;
 
-import kd.bos.bill.BillShowParameter;
 import kd.bos.common.enums.EnableEnum;
 import kd.bos.dataentity.entity.DynamicObject;
 import kd.bos.entity.datamodel.events.PropertyChangedArgs;
-import kd.bos.form.events.PreOpenFormEventArgs;
 import kd.bos.form.plugin.AbstractFormPlugin;
 import kd.bos.orm.query.QCP;
 import kd.bos.orm.query.QFilter;
@@ -18,7 +16,6 @@ import java.time.ZoneId;
 import java.util.Collections;
 import java.util.Date;
 import java.util.List;
-import java.util.Map;
 
 /**
  * 离职申请单表单插件
@@ -81,7 +78,7 @@ public class QuitApplyFormPlugin extends AbstractFormPlugin {
         // 考勤档案
         quotaQueryParam.setAttFileBoId(attFile.getBoId());
         // 休假类型
-        quotaQueryParam.setQuotaTypeIdList(Collections.singletonList(1427605179489846272L));
+        quotaQueryParam.setQuotaTypeIdList(Collections.singletonList(1666695290893207552L));
         // 仅使用范围过滤
         quotaQueryParam.setRangQueryType(0);
         // 开始时间

+ 156 - 0
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/common/HasPosAllowDataService.java

@@ -0,0 +1,156 @@
+package nckd.jxccl.hr.psms.common;
+
+import kd.bos.common.enums.EnableEnum;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.entity.constant.StatusEnum;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
+import kd.bos.servicehelper.QueryServiceHelper;
+import kd.hr.hbp.business.servicehelper.HRBaseServiceHelper;
+import kd.sdk.swc.hscs.common.api.ICustomFetchDataService;
+import nckd.jxccl.base.common.constant.FormConstant;
+import nckd.jxccl.base.common.enums.psms.TypeStateEnum;
+import nckd.jxccl.base.common.utils.DateUtil;
+import nckd.jxccl.base.common.utils.QueryFieldBuilder;
+import nckd.jxccl.base.orm.helper.QFilterCommonHelper;
+
+import java.util.Arrays;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * 否有享受职位津贴薪酬函数
+ *
+ * @author W.Y.C
+ * @version 1.0
+ * @date 2026/1/3 20:53
+ */
+public class HasPosAllowDataService implements ICustomFetchDataService {
+
+    @Override
+    public Map<Long, Map<String, Object>> fetchDataCalPerson(List<Long> calPersonIdList, Map<Long, Map<String, Object>> paramsMap, Map<String, Object> extParamMap) {
+        Map<Long, Map<String, Object>> resultMap = new HashMap<Long, Map<String, Object>>();
+
+        QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create()
+                .add(FormConstant.ID_KEY)
+                .add(FormConstant.EMP_NUMBER_KEY)
+                .add(FormConstant.NAME_KEY)
+                .add(FormConstant.ORG_KEY)
+                .addGroup(new String[]{"caltask"}, "calcount", "payrolldate")
+                .addGroup(new String[]{"caltask", "calrule"}, FormConstant.ID_KEY)
+                .addGroup(new String[]{FormConstant.EMPLOYEE_KEY}, FormConstant.ID_KEY);
+        QFilter qFilter = new QFilter(FormConstant.ID_KEY, "in", calPersonIdList);
+        DynamicObject[] load = new HRBaseServiceHelper("hsas_calperson").load(queryFieldBuilder.buildSelect(), new QFilter[]{qFilter});
+        if(load != null && load.length > 0) {
+            Map<Long, Long> employeeToCalPersonMap = Arrays.stream(load)
+                    .collect(Collectors.toMap(
+                            obj -> obj.getLong(FormConstant.ID_KEY),
+                            obj -> obj.getLong(String.join(".", FormConstant.EMPLOYEE_KEY, FormConstant.ID_KEY))
+                            ));
+            long orgId = load[0].getLong(String.join(".", FormConstant.ORG_KEY, FormConstant.ID_KEY));
+            //核算任务
+            DynamicObject calTask = load[0].getDynamicObject("caltask");
+            //薪资所属年月
+            Date date = calTask.getDate("payrolldate");
+            int year = DateUtil.getYear(date);
+            int month = DateUtil.getMonthValue(date);
+            //核算规则
+            long calRuleId = calTask.getLong(String.join(".", "calrule", FormConstant.ID_KEY));
+            //核算次数
+            int calCount = calTask.getInt("calcount");
+
+            //查询非“高级人才”聘任类型的职位档案
+            QFilter personPosFileFilter = new QFilter(PositionStructureConstant.NCKD_DISABLE, QCP.equals, EnableEnum.NO.getCode())
+                    .and(PositionStructureConstant.NCKD_TYPESTATE, QCP.not_in, new String[]{TypeStateEnum.HIGH_PROFESSIONAL_EMPLOYMENT.getCode()})
+                    .and(QFilterCommonHelper.getValidDateFilter(PositionStructureConstant.NCKD_BEGINDATE, PositionStructureConstant.NCKD_ENDDATE,date))
+                    .and(new QFilter(PositionStructureConstant.NCKD_PERSON, QCP.in, employeeToCalPersonMap.values()));
+            QueryFieldBuilder personPosFileFieldBuilder = QueryFieldBuilder.create()
+                    .add(FormConstant.ID_KEY)
+                    .addIdNumberName(FormConstant.NCKD_PERSON)
+                    .add(PositionStructureConstant.NCKD_ISSALADJPUSH)
+                    .add(PositionStructureConstant.NCKD_BEGINDATE)
+                    .add(PositionStructureConstant.CREATE_TIME_KEY)
+                    .add(PositionStructureConstant.NCKD_TYPESTATE)
+                    .addIdNumberNameWithExtras(new String[]{PositionStructureConstant.NCKD_JOBLEVELHR},PositionStructureConstant.JOBLEVELSEQ,PositionStructureConstant.NCKD_COEFFICIENT)
+                    .orderDesc(PositionStructureConstant.NCKD_BEGINDATE);
+            DynamicObjectCollection personPosFileColl = QueryServiceHelper.query(PositionStructureConstant.PERSONPOSFILE_ENTITYID, personPosFileFieldBuilder.buildSelect(), new QFilter[]{personPosFileFilter});
+            //筛选出管理人员任命
+            List<DynamicObject> managementPostFile = personPosFileColl.stream().filter(obj -> TypeStateEnum.MANAGEMENT_SEQUENCE_EMPLOYMENT.getCode().equalsIgnoreCase(obj.getString(PositionStructureConstant.NCKD_TYPESTATE))).collect(Collectors.toList());
+            List<Long> managementPersonIds = managementPostFile.stream().map(obj -> obj.getLong(String.join(".", FormConstant.NCKD_PERSON, FormConstant.ID_KEY))).collect(Collectors.toList());
+
+            //如果是管理人员任命则必须“配置有职位津贴”才能享受职位津贴
+            //查询职位津贴
+            QFilter positionAllowanceFilter = new QFilter(PositionStructureConstant.NCKD_PERSON, QCP.in, managementPersonIds)
+                    .and(QFilterCommonHelper.getValidDateFilter(PositionStructureConstant.NCKD_STARTDATE, PositionStructureConstant.NCKD_ENDDATE,date))
+                    //已确认或已审批
+                    .and(new QFilter(PositionStructureConstant.STATUS, QCP.in, new String[]{StatusEnum.B.toString(), StatusEnum.C.toString()}));
+            QueryFieldBuilder positionAllowanceFieldBuilder = QueryFieldBuilder.create()
+                    .add(FormConstant.ID_KEY)
+                    .addIdNumberName(PositionStructureConstant.NCKD_PERSON);
+            DynamicObjectCollection positionAllowanceColl = QueryServiceHelper.query(PositionStructureConstant.MANAGERALLOWANCE_ENTITYID, positionAllowanceFieldBuilder.buildSelect(), new QFilter[]{positionAllowanceFilter});
+            // 获取有职位津贴的人员ID列表
+            List<Long> positionAllowancePersonIds = positionAllowanceColl.stream()
+                    .map(obj -> obj.getLong(String.join(".", PositionStructureConstant.NCKD_PERSON, FormConstant.ID_KEY)))
+                    .collect(Collectors.toList());
+            // 找出没有职位津贴的管理人员ID
+            List<Long> noAllowanceManagementPersonIds = managementPostFile.stream()
+                    .map(obj -> obj.getLong(String.join(".", FormConstant.NCKD_PERSON, FormConstant.ID_KEY)))
+                    .filter(personId -> !positionAllowancePersonIds.contains(personId))
+                    .collect(Collectors.toList());
+
+            //去掉"管理人员任命"及是"管理人员任命"但是没有津贴的人员
+            List<DynamicObject> posAllowFileCollect = personPosFileColl.stream()
+                    .filter(obj -> {
+                        Long personId = obj.getLong(String.join(".", FormConstant.NCKD_PERSON, FormConstant.ID_KEY));
+                        String typeState = obj.getString(PositionStructureConstant.NCKD_TYPESTATE);
+                        // 去掉类型为“管理人员任命”的记录
+                        if (TypeStateEnum.MANAGEMENT_SEQUENCE_EMPLOYMENT.getCode().equalsIgnoreCase(typeState)) {
+                            return false;
+                        }
+                        // 如果是管理人员但没有津贴,则该人员的所有记录都不保留
+                        if (noAllowanceManagementPersonIds.contains(personId)) {
+                            return false;
+                        }
+                        // 其他情况保留
+                        return true;
+                    })
+                    .collect(Collectors.toList());
+            //分组,取最新一条
+            Map<Long, DynamicObject> posAllowFileMap = posAllowFileCollect.stream()
+                    .collect(Collectors.groupingBy(
+                            obj -> obj.getLong(String.join(".", FormConstant.NCKD_PERSON, FormConstant.ID_KEY)),
+                            Collectors.collectingAndThen(
+                                    Collectors.maxBy((o1, o2) -> {
+                                        Date date1 = o1.getDate(PositionStructureConstant.NCKD_BEGINDATE);
+                                        Date date2 = o2.getDate(PositionStructureConstant.NCKD_BEGINDATE);
+                                        return date1 != null && date2 != null ? date1.compareTo(date2) : 0;
+                                    }),
+                                    optional -> optional.orElse(null)
+                            )
+                    ))
+                    .entrySet().stream()
+                    .filter(entry -> entry.getValue() != null) // 过滤掉值为null的条目
+                    .collect(Collectors.toMap(
+                            Map.Entry::getKey,
+                            Map.Entry::getValue));
+            for (Long calPersonId : calPersonIdList) {
+                Long personId = employeeToCalPersonMap.get(calPersonId);
+                DynamicObject dynamicObject = posAllowFileMap.get(personId);
+                Map<String, Object> result = new HashMap<String, Object>();
+                //享受返回1,不享受返回0
+                result.put("hasPosAllow",dynamicObject != null ? "1" : "0");
+                resultMap.put(calPersonId, result);
+            }
+        }
+        return resultMap;
+    }
+
+    @Override
+    public Map<String, Object> fetchDataCalTask(Long calTaskId, Map<String, Object> paramsMap, Map<String, Object> extParamMap) {
+        return null;
+    }
+}

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

@@ -24,6 +24,8 @@ public class PositionStructureConstant extends FormConstant {
     public static final String NCKD_DIPLOMA = "nckd_diploma";
     /** 岗位 */
     public static final String NCKD_POSITIONHR = "nckd_positionhr";
+    /** 岗位 */
+    public static final String NCKD_POSITION = "nckd_position";
     /** 职称名称 */
     public static final String NCKD_RANKNAME = "nckd_rankname";
     /** 职称级别 */
@@ -319,8 +321,17 @@ public class PositionStructureConstant extends FormConstant {
     public static final String NCKD_PERSON = "nckd_person";
     /** 科研、创新、创效成果 */
     public static final String NCKD_INNOVATE = "nckd_innovate";
+    /** 科研、创新、创效成果 */
+    public static final String NCKD_APPOINT = "nckd_appoint";
     /** 工作年限 */
     public static final String NCKD_WORKYEAR = "nckd_workyear";
     /** 匹配情况说明 */
     public static final String NCKD_MATCHCONDDESC = "nckd_matchconddesc";
+    /** 配置关键行为人才标准项目分录 */
+    public static final String NCKD_KEYBEHAVCONFENTRY = "nckd_keybehavconfentry";
+    /** 配置关键行为人才标准项目分录 */
+    public static final String NCKD_RESULT = "nckd_result";
+
+    /** 关键行为项目评价结果-实体标识 */
+    public static final String KEYBEHAVEVALPROJRSLT_ENTITYID = "nckd_keybehavevalprojrslt";
 }

+ 1 - 1
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/report/adjust/UnAdjustedReportFormPlugin.java → code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/form/adjust/report/UnAdjustedReportFormPlugin.java

@@ -1,4 +1,4 @@
-package nckd.jxccl.hr.psms.plugin.report.adjust;
+package nckd.jxccl.hr.psms.plugin.form.adjust.report;
 
 import kd.bos.dataentity.entity.DynamicObject;
 import kd.bos.entity.report.ReportQueryParam;

+ 13 - 2
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/report/adjust/UnAdjustedReportReportListDataPlugin.java → code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/form/adjust/report/UnAdjustedReportReportListDataPlugin.java

@@ -1,7 +1,8 @@
-package nckd.jxccl.hr.psms.plugin.report.adjust;
+package nckd.jxccl.hr.psms.plugin.form.adjust.report;
 
 import kd.bos.algo.DataSet;
 import kd.bos.common.enums.EnableEnum;
+import kd.bos.context.RequestContext;
 import kd.bos.entity.report.AbstractReportListDataPlugin;
 import kd.bos.entity.report.FastFilter;
 import kd.bos.entity.report.FilterItemInfo;
@@ -10,11 +11,14 @@ import kd.bos.orm.ORMHint;
 import kd.bos.orm.query.QCP;
 import kd.bos.orm.query.QFilter;
 import kd.bos.servicehelper.QueryServiceHelper;
+import kd.bos.servicehelper.model.PermissionStatus;
+import kd.sdk.hr.hbp.business.helper.permission.HRPermissionServiceHelper;
 import nckd.jxccl.base.common.constant.FormConstant;
 import nckd.jxccl.base.common.utils.ConvertUtil;
 import nckd.jxccl.base.common.utils.QueryFieldBuilder;
 import nckd.jxccl.hr.psms.common.PositionStructureConstant;
 
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.StringJoiner;
@@ -39,11 +43,18 @@ public class UnAdjustedReportReportListDataPlugin extends AbstractReportListData
 
         //其他过滤条件
         processFilter(reportQueryParam, qFilter);
+        //权限过滤
+        QFilter dataRule = HRPermissionServiceHelper.getDataRule(
+                RequestContext.get().getCurrUserId(), "nckd_psmsfile", "unadjustquery",
+                PermissionStatus.View, new HashMap<>());
+        if(dataRule != null){
+            qFilter.and(dataRule);
+        }
 
 
         // 执行基础查询
         DataSet dataSet = QueryServiceHelper.queryDataSet(PositionStructureConstant.PERSONPOSFILE_ENTITYID, "unadjustquery",
-                queryFieldBuilder.buildSelect(), new QFilter[]{qFilter}, null,10000);
+                queryFieldBuilder.buildSelect(), new QFilter[]{qFilter}, null,100000);
 
         // 添加扩展过滤条件
         DataSet filteredDataSet = addExtendedFilters(dataSet);

+ 8 - 1
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/form/annualadjust/AnnualAdjustmentFormPlugin.java

@@ -8,6 +8,7 @@ import kd.bos.list.ListShowParameter;
 import kd.bos.list.plugin.AbstractListPlugin;
 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;
@@ -59,7 +60,13 @@ public class AnnualAdjustmentFormPlugin extends AbstractListPlugin implements Ta
             openTargetPage(PositionStructureConstant.ANNUALADJUST_QUERY, PositionStructureConstant.NCKD_ADJUSTED,"已生成年度调整");
         } else if (PositionStructureConstant.NCKD_UNADJUSTED.equalsIgnoreCase(currentTab)) {
             //打开“未生成年度调整”列表
-            openTargetPage(PositionStructureConstant.UNANNUALADJUST_QUERY,PositionStructureConstant.NCKD_UNADJUSTED,"未生成年度调整");
+//            openTargetPage(PositionStructureConstant.UNANNUALADJUST_QUERY,PositionStructureConstant.NCKD_UNADJUSTED,"未生成年度调整");
+            ReportShowParameter reportShowParameter = new ReportShowParameter();
+            reportShowParameter.setFormId("nckd_unannualadjustreort");
+            reportShowParameter.getOpenStyle().setShowType(ShowType.InContainer);
+            reportShowParameter.getOpenStyle().setTargetKey(PositionStructureConstant.NCKD_UNADJUSTED);
+            reportShowParameter.setCaption("未生成年度调整");
+            this.getView().showForm(reportShowParameter);
         }
     }
 

+ 22 - 3
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/form/annualadjust/UnAnnualAdjustListPlugin.java

@@ -10,9 +10,11 @@ import kd.bos.form.CloseCallBack;
 import kd.bos.form.FormShowParameter;
 import kd.bos.form.ShowType;
 import kd.bos.form.control.events.ItemClickEvent;
+import kd.bos.form.events.BeforeCreateListDataProviderArgs;
 import kd.bos.form.events.FilterContainerInitArgs;
 import kd.bos.form.events.SetFilterEvent;
 import kd.bos.list.plugin.AbstractListPlugin;
+import kd.bos.orm.ORMHint;
 import kd.bos.orm.query.QCP;
 import kd.bos.orm.query.QFilter;
 import kd.bos.servicehelper.BusinessDataServiceHelper;
@@ -27,7 +29,10 @@ import nckd.jxccl.hr.psms.common.PositionStructureConstant;
 
 import java.time.LocalDateTime;
 import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 /**
 * 未生成年度调整列表
@@ -42,6 +47,7 @@ public class UnAnnualAdjustListPlugin extends AbstractListPlugin implements Plug
         super.filterContainerInit(args);
     }
 
+
     @Override
     public void setFilter(SetFilterEvent e) {
         //TODO 【待修改】-职位体系-默认过滤掉副科级及以上
@@ -60,7 +66,13 @@ public class UnAnnualAdjustListPlugin extends AbstractListPlugin implements Plug
             personIds.add(personId);
         }
 
+
+
+
+
         LocalDateTime lastYear = DateUtil.minusYears(localDateTime, 1);
+        LocalDateTime lastBegin = DateUtil.beginOfYear(lastYear);
+        LocalDateTime lastEnd = DateUtil.endOfYear(lastYear);
         QFilter qFilter = new QFilter(FormConstant.IS_PRIMARY, QCP.equals, EnableEnum.YES.getCode())
                 .and(FormConstant.IS_SEQLATESTRECORD, QCP.equals, EnableEnum.YES.getCode())
                 .and(FormConstant.IS_DELETED, QCP.equals, EnableEnum.NO.getCode())
@@ -71,12 +83,19 @@ public class UnAnnualAdjustListPlugin extends AbstractListPlugin implements Plug
                 //有初定的人员
                 .and(new QFilter(String.join(".", PositionStructureConstant.PERSONPOSFILE_ENTITYID+"init", PositionStructureConstant.NCKD_FIRSTRANK), QCP.equals, EnableEnum.YES.getCode()))
                 //初定时间不等于当年
-                .and(new QFilter(String.join(".", PositionStructureConstant.PERSONPOSFILE_ENTITYID+"init", PositionStructureConstant.NCKD_EXECUTEYEAR), QCP.not_equals2, localDateTime.getYear()))
+                .and(new QFilter(String.join(".", PositionStructureConstant.PERSONPOSFILE_ENTITYID+"init", PositionStructureConstant.NCKD_EXECUTEYEAR), QCP.not_equals2, localDateTime.getYear()));
                 //上年度有考核结果的人员
-                .and(new QFilter(String.join(".", PositionStructureConstant.PERFMANAGER_ENTITYID, PositionStructureConstant.PERFMANAGER_ENTRY_ENTITYID, PositionStructureConstant.APPRAISAL_YEAR_KEY), QCP.equals, DateUtil.toDate(lastYear)))
+               /* .and(new QFilter(String.join(".", PositionStructureConstant.PERFMANAGER_ENTITYID, PositionStructureConstant.PERFMANAGER_ENTRY_ENTITYID, PositionStructureConstant.APPRAISAL_YEAR_KEY), QCP.large_equals, DateUtil.toDate(lastBegin)))
+                .and(new QFilter(String.join(".", PositionStructureConstant.PERFMANAGER_ENTITYID, PositionStructureConstant.PERFMANAGER_ENTRY_ENTITYID, PositionStructureConstant.APPRAISAL_YEAR_KEY), QCP.less_equals, DateUtil.toDate(lastEnd)))*/
                 //当年还未年度调整的人员
-                .and(new QFilter(FormConstant.EMPLOYEE_KEY, QCP.not_in, personIds));
+                if(!personIds.isEmpty()) {
+                    qFilter.and(new QFilter(FormConstant.EMPLOYEE_KEY, QCP.not_in, personIds));
+                }
+        QFilter qFilter1 = QFilter.joinSQL(FormConstant.HRPI_EMPPOSORGREL,
+                "left join tk_nckd_perfmanager pm on pm.fk_nckd_personid = hrpi_empposorgrel.femployeeid",
+                null);
         e.addCustomQFilter(qFilter);
+//        e.getQFilters().add(qFilter1);
     }
 
     @Override

+ 78 - 0
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/form/annualadjust/report/UnAnnualAdjustReportFormPlugin.java

@@ -0,0 +1,78 @@
+package nckd.jxccl.hr.psms.plugin.form.annualadjust.report;
+
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+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.control.events.ItemClickEvent;
+import kd.bos.form.plugin.AbstractFormPlugin;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
+import kd.bos.report.ReportList;
+import kd.bos.report.plugin.AbstractReportFormPlugin;
+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.PositionStructureConstant;
+
+import java.util.ArrayList;
+import java.util.EventObject;
+import java.util.List;
+
+/**
+* TODO
+* 实体标识:TODO
+* @author W.Y.C
+* @date 2026/1/2 17:35
+* @version 1.0
+*/
+public class UnAnnualAdjustReportFormPlugin extends AbstractReportFormPlugin implements Plugin {
+
+    @Override
+    public void registerListener(EventObject e) {
+        this.addItemClickListeners(FormConstant.TOOLBARAP);
+    }
+
+    @Override
+    public void itemClick(ItemClickEvent evt) {
+        String itemKey = evt.getItemKey();
+
+        if("nckd_new".equals(itemKey) ) {
+            ReportList reportList = this.getView().getControl(FormConstant.REPORTLISTAP);
+            int[] selectedRowIndexes = reportList.getEntryState().getSelectedRows();
+            if (selectedRowIndexes == null || selectedRowIndexes.length == 0) {
+                this.getView().showTipNotification("请至少选择一条数据");
+                return;
+            }
+            //任职经历ID
+            List<Long> personIds = new ArrayList<>();
+            if(selectedRowIndexes != null && selectedRowIndexes.length > 0) {
+                for (int selectedRowIndex : selectedRowIndexes) {
+                    DynamicObject rowData = reportList.getReportModel().getRowData(selectedRowIndex);
+                    personIds.add(rowData.getLong(String.join(".", FormConstant.NCKD_EMPLOYEE,FormConstant.ID_KEY)));
+                }
+            }
+
+            if (personIds.isEmpty()) {
+                this.getView().showErrorNotification("请选择正确的数据");
+                return;
+            }
+            if ("nckd_new".equals(itemKey)) {
+                //弹出【批量】在职人员初定窗口
+                FormShowParameter showParameter = new FormShowParameter();
+                showParameter.setFormId(PositionStructureConstant.NEWANNUALADJUST_ENTITYID);
+                showParameter.getOpenStyle().setShowType(ShowType.Modal);
+                showParameter.setCaption("生成年度调整");
+                showParameter.setSendToClient(true);
+                showParameter.setCustomParam(FormConstant.NCKD_PERSON, personIds);
+                showParameter.setCloseCallBack(new CloseCallBack(this, PositionStructureConstant.NEWANNUALADJUST_ENTITYID));
+                this.getView().showForm(showParameter);
+
+            }
+        }
+    }
+}

+ 302 - 0
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/form/annualadjust/report/UnAnnualAdjustReportListDataPlugin.java

@@ -0,0 +1,302 @@
+package nckd.jxccl.hr.psms.plugin.form.annualadjust.report;
+
+import kd.bos.algo.DataSet;
+import kd.bos.algo.JoinType;
+import kd.bos.algo.Row;
+import kd.bos.common.enums.EnableEnum;
+import kd.bos.context.RequestContext;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.entity.report.AbstractReportListDataPlugin;
+import kd.bos.entity.report.FastFilter;
+import kd.bos.entity.report.ReportQueryParam;
+import kd.bos.orm.ORMHint;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
+import kd.bos.servicehelper.QueryServiceHelper;
+import kd.bos.servicehelper.model.PermissionStatus;
+import kd.sdk.hr.hbp.business.helper.permission.HRPermissionServiceHelper;
+import nckd.jxccl.base.common.constant.FormConstant;
+import nckd.jxccl.base.common.enums.psms.TypeStateEnum;
+import nckd.jxccl.base.common.utils.DateUtil;
+import nckd.jxccl.base.common.utils.QueryFieldBuilder;
+import nckd.jxccl.hr.psms.common.PositionStructureConstant;
+
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+* 未生成年度调整报表查询插件
+* 实体标识:nckd_unannualadjustreort
+* @author W.Y.C
+* @date 2026/1/2 17:44
+* @version 1.0
+*/
+public class UnAnnualAdjustReportListDataPlugin extends AbstractReportListDataPlugin {
+    @Override
+    public DataSet query(ReportQueryParam reportQueryParam, Object o) throws Throwable {
+        // 构建查询字段
+        QueryFieldBuilder queryFieldBuilder = buildQueryFieldBuilder();
+
+        // 构建基础查询条件
+        QFilter qFilter = buildBaseQueryFilter();
+
+        // 处理快速过滤条件
+        processFastFilter(reportQueryParam, qFilter);
+
+        //其他过滤条件
+        processFilter(reportQueryParam, qFilter);
+        //权限过滤
+        QFilter dataRule = HRPermissionServiceHelper.getDataRule(
+                RequestContext.get().getCurrUserId(), "nckd_psmsfile", "unannualadjustquery",
+                PermissionStatus.View, new HashMap<>());
+        if(dataRule != null){
+            qFilter.and(dataRule);
+        }
+
+        LocalDateTime localDateTime = DateUtil.beginOfYear(DateUtil.now());
+        LocalDateTime lastYear = DateUtil.minusYears(localDateTime, 1);
+        LocalDateTime lastBegin = DateUtil.beginOfYear(lastYear);
+        LocalDateTime lastEnd = DateUtil.endOfYear(lastYear);
+
+
+        // 执行基础查询
+        DataSet mainDataSet = QueryServiceHelper.queryDataSet(PositionStructureConstant.PERSONPOSFILE_ENTITYID, "unannualadjustquery",
+                queryFieldBuilder.buildSelect(), new QFilter[]{qFilter}, null,1000000);
+        String[] mainTableFieldNames = mainDataSet.getRowMeta().getFieldNames();
+        String[] newMainTableFieldNames = new String[mainTableFieldNames.length + 1];
+        System.arraycopy(mainTableFieldNames, 0, newMainTableFieldNames, 0, mainTableFieldNames.length);
+        // 添加当前年度
+        newMainTableFieldNames[mainTableFieldNames.length] = "'"+localDateTime.getYear()+"' as nckd_currentyear";
+
+        //--------------------- 获取上年度考核结果 begin---------------------
+        DataSet mainDataSetCopy = mainDataSet.copy();
+        Set<Long> personIds = new HashSet<>();
+        while (mainDataSetCopy.hasNext()) {
+            Row next = mainDataSetCopy.next();
+            Long personId = next.getLong(String.join(".", FormConstant.EMPLOYEE_KEY, FormConstant.ID_KEY));
+            personIds.add(personId);
+        }
+        if(!personIds.isEmpty()) {
+            DataSet lastAppraisalYearDateSet = lastAppraisalYear(personIds, DateUtil.toDate(lastBegin), DateUtil.toDate(lastEnd));
+            mainDataSet = mainDataSet.join(lastAppraisalYearDateSet, JoinType.INNER)
+                    .on(String.join(".", FormConstant.EMPLOYEE_KEY, FormConstant.ID_KEY), String.join(".", FormConstant.NCKD_PERSON, FormConstant.ID_KEY))
+                    .select(newMainTableFieldNames, QueryFieldBuilder.create().add(PositionStructureConstant.NCKD_PERFMANAGERENTRY,PositionStructureConstant.NCKD_APPRAISALRESULT).buildSelectArray()).finish();
+        }
+
+        //--------------------- 获取上年度考核结果 end---------------------
+
+        return mainDataSet;
+    }
+
+
+    private DataSet lastAppraisalYear(Set<Long> personIds,Date beginYear,Date endYear){
+        QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create()
+                .addIdNumberName(PositionStructureConstant.NCKD_PERSON)
+                .add(PositionStructureConstant.NCKD_PERFMANAGERENTRY,PositionStructureConstant.NCKD_APPRAISALRESULT);
+        QFilter qFilter = new QFilter(PositionStructureConstant.NCKD_PERSON, QCP.in, personIds)
+                .and(new QFilter(String.join(".", PositionStructureConstant.NCKD_PERFMANAGERENTRY, PositionStructureConstant.NCKD_APPRAISALYEAR), QCP.large_equals, beginYear))
+                .and(new QFilter(String.join(".", PositionStructureConstant.NCKD_PERFMANAGERENTRY, PositionStructureConstant.NCKD_APPRAISALYEAR), QCP.less_equals, endYear))
+                .and(new QFilter(String.join(".", PositionStructureConstant.NCKD_PERFMANAGERENTRY, PositionStructureConstant.NCKD_APPRAISALRESULT), QCP.is_notnull, null))
+                .and(new QFilter(String.join(".", PositionStructureConstant.NCKD_PERFMANAGERENTRY, PositionStructureConstant.NCKD_APPRAISALRESULT), QCP.not_equals2, 0));
+
+        return QueryServiceHelper.queryDataSet(this.getClass().getName()+"nckd_perfmanager", "nckd_perfmanager",
+                queryFieldBuilder.buildSelect(), new QFilter[]{qFilter}, null,10000);
+    }
+
+    /**
+     * 构建基础查询条件
+     */
+    private QFilter buildBaseQueryFilter() {
+        LocalDateTime localDateTime = DateUtil.beginOfYear(DateUtil.now());
+        //查询当年已执行年度调整的人员
+        QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create().addIdNumberName(FormConstant.NCKD_PERSON);
+        QFilter yearFilter = new QFilter(PositionStructureConstant.NCKD_EXECUTEYEAR, QCP.equals, localDateTime.getYear())
+                .and(new QFilter(PositionStructureConstant.NCKD_DISABLE, QCP.equals, EnableEnum.NO.getCode()))
+                .and(new QFilter(PositionStructureConstant.NCKD_TYPESTATE, QCP.equals, TypeStateEnum.ANNUAL_ADJUSTMENT.getCode()));
+        DynamicObjectCollection query = QueryServiceHelper.query(PositionStructureConstant.PERSONPOSFILE_ENTITYID, queryFieldBuilder.buildSelect(), new QFilter[]{yearFilter});
+        List<Long> personIds = new ArrayList<>(query.size());
+        for (DynamicObject dynamicObject : query) {
+            long personId = dynamicObject.getLong(String.join(".", FormConstant.NCKD_PERSON, FormConstant.ID_KEY));
+            personIds.add(personId);
+        }
+        QFilter qFilter = new QFilter(FormConstant.IS_PRIMARY, QCP.equals, EnableEnum.YES.getCode())
+                .and(FormConstant.IS_SEQLATESTRECORD, QCP.equals, EnableEnum.YES.getCode())
+                .and(FormConstant.IS_DELETED, QCP.equals, EnableEnum.NO.getCode())
+                .and(String.join(".", FormConstant.ASSIGNMENT, FormConstant.IS_PRIMARY), QCP.equals, EnableEnum.YES.getCode())
+                .and(String.join(".", FormConstant.ASSIGNMENT, FormConstant.IS_DELETED), QCP.equals, EnableEnum.NO.getCode())
+                .and(String.join(".", PositionStructureConstant.PERSONPOSFILE_ENTITYID, PositionStructureConstant.NCKD_DISABLE), QCP.equals, EnableEnum.NO.getCode())
+                .and(String.join(".", PositionStructureConstant.PERSONPOSFILE_ENTITYID, PositionStructureConstant.NCKD_ISCURRENTNEWEST), QCP.equals, EnableEnum.YES.getCode())
+                //在岗
+                .and(String.join( ".", FormConstant.POS_STATUS, FormConstant.POST_STATE_CLS, FormConstant.NUMBER_KEY),QCP.equals,"1010_S")
+                //有初定的人员
+                .and(new QFilter(String.join(".", PositionStructureConstant.PERSONPOSFILE_ENTITYID+"init", PositionStructureConstant.NCKD_FIRSTRANK), QCP.equals, EnableEnum.YES.getCode()))
+                //初定时间不等于当年
+                .and(new QFilter(String.join(".", PositionStructureConstant.PERSONPOSFILE_ENTITYID+"init", PositionStructureConstant.NCKD_EXECUTEYEAR), QCP.not_equals2, localDateTime.getYear()))
+
+
+                .and(QFilter.join(FormConstant.EMPLOYEE_KEY, String.join(".", FormConstant.HRPI_PERPROTITLE, FormConstant.EMPLOYEE_KEY), new QFilter(String.join(".", FormConstant.HRPI_PERPROTITLE, "iscompany"),
+                        QCP.equals, EnableEnum.YES.getCode()),
+                ORMHint.JoinHint.LEFT, Boolean.FALSE))
+                .and(QFilter.join(FormConstant.EMPLOYEE_KEY, String.join(".", FormConstant.HRPI_PEROCPQUAL, FormConstant.EMPLOYEE_KEY), new QFilter(String.join(".", FormConstant.HRPI_PEROCPQUAL, "ismajor"),
+                                QCP.equals, EnableEnum.YES.getCode()),
+                        ORMHint.JoinHint.LEFT, Boolean.FALSE))
+                .and(QFilter.join(FormConstant.EMPLOYEE_KEY, String.join(".", FormConstant.HRPI_PEREDUEXP, FormConstant.EMPLOYEE_KEY), new QFilter(String.join(".", FormConstant.HRPI_PEREDUEXP, "ishighestdegree"),
+                                QCP.equals, EnableEnum.YES.getCode()),
+                        ORMHint.JoinHint.LEFT, Boolean.FALSE));
+
+        //当年还未年度调整的人员
+        if(!personIds.isEmpty()) {
+            qFilter.and(new QFilter(FormConstant.EMPLOYEE_KEY, QCP.not_in, personIds));
+        }
+
+        return qFilter;
+    }
+
+
+    /**
+     * 处理快速过滤条件
+     */
+    private void processFastFilter(ReportQueryParam reportQueryParam, QFilter qFilter) {
+        FastFilter fastFilter = reportQueryParam.getFilter().getFastFilter();
+        if (fastFilter != null) {
+            List<Map<String, List<Object>>> fastFilterList = fastFilter.getFastFilter();
+            for (Map<String, List<Object>> stringListMap : fastFilterList) {
+                //nckd_empnumfastfilter转为employee.empnumber,nckd_namefastfilter转换为employee.name,转换后添加到fields中
+                List<Object> fieldList = stringListMap.get("FieldName");
+                List<Object> valueList = stringListMap.get("Value");
+                String[] fields = new String[fieldList.size()];
+                for (int i = 0; i < fieldList.size(); i++) {
+                    fields[i] = fieldList.get(i).toString()
+                            .replace("nckd_empnumfastfilter", "employee.empnumber")
+                            .replace("nckd_namefastfilter", "employee.name");
+                }
+                //valueList转到values
+                String[] values = new String[valueList.size()];
+                for (int i = 0; i < valueList.size(); i++) {
+                    values[i] = valueList.get(i).toString();
+                }
+                qFilter.and(QFilter.ftlike(values, fields));
+            }
+        }
+    }
+
+    /**
+     * 处理过滤条件
+     */
+    private void processFilter(ReportQueryParam reportQueryParam, QFilter qFilter) {
+        List<QFilter> qFilters = reportQueryParam.getFilter().getQFilters();
+        for (QFilter filter : qFilters) {
+            //由于页面命名限制不允许配置对应数据库字段(例如:position.id的格式),这里只能手动转换为数据库实际的字段
+            String property = filter.getProperty();
+            if ("nckd_positionfilter.id".equalsIgnoreCase(property)){
+                qFilter.and(new QFilter(String.join(".", FormConstant.POSITION_KEY, FormConstant.ID_KEY),filter.getCP(),filter.getValue()));
+            }
+            if("nckd_orgfilter.id".equalsIgnoreCase(property)){
+                qFilter.and(new QFilter(String.join(".", FormConstant.COMPANY_KEY, FormConstant.ID_KEY),filter.getCP(),filter.getValue()));
+            }
+            if("nckd_joblevelhrffilter.id".equalsIgnoreCase(property)){
+                qFilter.and(new QFilter(String.join(".", PositionStructureConstant.PERSONPOSFILE_ENTITYID, PositionStructureConstant.NCKD_JOBLEVELHR,FormConstant.ID_KEY),filter.getCP(),filter.getValue()));
+            }
+            if("nckd_begindatefilter".equalsIgnoreCase(property)){
+                qFilter.and(new QFilter(String.join(".", PositionStructureConstant.PERSONPOSFILE_ENTITYID, PositionStructureConstant.NCKD_BEGINDATE),filter.getCP(),filter.getValue()));
+            }
+            if ("nckd_secondorg.id".equalsIgnoreCase(property)){
+                qFilter.and(new QFilter(String.join(".", FormConstant.ADMINORG,FormConstant.NCKD_SECONDORG,FormConstant.ID_KEY),filter.getCP(),filter.getValue()));
+            }
+            if ("nckd_thirdorg.id".equalsIgnoreCase(property)){
+                qFilter.and(new QFilter(String.join(".", FormConstant.ADMINORG,FormConstant.NCKD_THIRDORG,FormConstant.ID_KEY),filter.getCP(),filter.getValue()));
+            }
+            if ("nckd_fourthorg.id".equalsIgnoreCase(property)){
+                qFilter.and(new QFilter(String.join(".", FormConstant.ADMINORG,FormConstant.NCKD_FOURTHORG,FormConstant.ID_KEY),filter.getCP(),filter.getValue()));
+            }
+            if ("nckd_fifthorg.id".equalsIgnoreCase(property)){
+                qFilter.and(new QFilter(String.join(".", FormConstant.ADMINORG,FormConstant.NCKD_FIFTHORG,FormConstant.ID_KEY),filter.getCP(),filter.getValue()));
+            }
+            if ("nckd_sixthorg.id".equalsIgnoreCase(property)){
+                qFilter.and(new QFilter(String.join(".", FormConstant.ADMINORG,FormConstant.NCKD_SIXTHORG,FormConstant.ID_KEY),filter.getCP(),filter.getValue()));
+            }
+            if ("nckd_position.id".equalsIgnoreCase(property)){
+                qFilter.and(new QFilter(String.join(".", FormConstant.POSITION_KEY,FormConstant.ID_KEY),filter.getCP(),filter.getValue()));
+            }
+            if ("nckd_jobseq.id".equalsIgnoreCase(property)){
+                qFilter.and(new QFilter(String.join(".", PositionStructureConstant.PERSONPOSFILE_ENTITYID,PositionStructureConstant.NCKD_JOBSEQHR,FormConstant.ID_KEY),filter.getCP(),filter.getValue()));
+            }
+            if ("nckd_begindate".equalsIgnoreCase(property)){
+                qFilter.and(new QFilter(String.join(".", "nckd_personposfileinit",PositionStructureConstant.NCKD_BEGINDATE),filter.getCP(),filter.getValue()));
+            }
+        }
+    }
+
+    /**
+     * 构建查询字段
+     */
+    private QueryFieldBuilder buildQueryFieldBuilder() {
+        return QueryFieldBuilder.create()
+                .add(FormConstant.ID_KEY)
+                .add(FormConstant.EMPLOYEE_KEY)
+                .addGroup(new String[]{FormConstant.EMPLOYEE_KEY},FormConstant.ID_KEY, FormConstant.EMP_NUMBER_KEY, FormConstant.NAME_KEY)
+                .addGroup(new String[]{FormConstant.ADMINORG},
+                        FormConstant.NCKD_FIRSTORG,
+                        FormConstant.NCKD_SECONDORG,
+                        FormConstant.NCKD_THIRDORG,
+                        FormConstant.NCKD_FOURTHORG,
+                        FormConstant.NCKD_FIFTHORG,
+                        FormConstant.NCKD_SIXTHORG)
+                .add("nckd_personposfileinit",PositionStructureConstant.NCKD_BEGINDATE)
+                .addGroup(new String[]{PositionStructureConstant.PERSONPOSFILE_ENTITYID},
+                        PositionStructureConstant.NCKD_POSITIONHR,
+                        PositionStructureConstant.NCKD_JOBSEQHR,
+                        PositionStructureConstant.NCKD_PROTITLELEVEL,
+                        PositionStructureConstant.NCKD_OCPQUALLEVEL,
+                        PositionStructureConstant.NCKD_DIPLOMA,
+                        PositionStructureConstant.NCKD_ALLSUMSCORE,
+                        PositionStructureConstant.NCKD_BEGINDATE,
+                        PositionStructureConstant.NCKD_JOBLEVELHR,
+                        PositionStructureConstant.NCKD_PERSON,
+                        PositionStructureConstant.NCKD_DEP,
+                        PositionStructureConstant.NCKD_ALLOWANCERANKMARK,
+                        PositionStructureConstant.NCKD_ALLOWANCERANKSEL,
+                        PositionStructureConstant.NCKD_COEFFICIENT,
+                        PositionStructureConstant.NCKD_CURRENTPOSTSALARY,
+                        PositionStructureConstant.NCKD_POSTALLOWANCE,
+                        PositionStructureConstant.NCKD_TYPESTATE,
+                        PositionStructureConstant.NCKD_APPRAISALRESULT,
+                        PositionStructureConstant.NCKD_RANKSCORE,
+                        PositionStructureConstant.NCKD_JOBSTATUSSCORE,
+                        PositionStructureConstant.NCKD_DIPLOMASCORE,
+                        PositionStructureConstant.NCKD_ORGINSSCORE,
+                        PositionStructureConstant.NCKD_SUMSCORE,
+                        PositionStructureConstant.NCKD_RESULTSCORE,
+                        PositionStructureConstant.NCKD_LYRCONTRIBSCORE,
+                        PositionStructureConstant.NCKD_YEARSCORESUMA,
+                        PositionStructureConstant.NCKD_YEARSCORESUMB,
+                        PositionStructureConstant.NCKD_YEARSCORESUMC,
+                        PositionStructureConstant.NCKD_YEARSCORESUMD,
+                        PositionStructureConstant.NCKD_YEARSCORESUME,
+                        PositionStructureConstant.NCKD_YEARSCORESUMF,
+                        PositionStructureConstant.NCKD_YEARSCORESUMG,
+                        PositionStructureConstant.NCKD_YEARSCORESUMH,
+                        PositionStructureConstant.NCKD_YEARSCORESUMI,
+                        PositionStructureConstant.NCKD_ALLYEARSCORESUM
+
+                )
+                .addGroup(new String[]{FormConstant.HRPI_PERPROTITLE}, FormConstant.PROLEVEL_KEY)
+                .addGroup(new String[]{FormConstant.HRPI_PEROCPQUAL}, FormConstant.QUALIFICATION_KEY)
+                .addGroup(new String[]{FormConstant.HRPI_PEREDUEXP}, FormConstant.EDUCATION_KEY)
+                .add(FormConstant.COMPANY_KEY)
+                .addIdNumberName(FormConstant.COMPANY_KEY)
+                .add(FormConstant.ADMINORG)
+                .addIdNumberName(FormConstant.POSITION_KEY)
+                .addGroup(new String[]{FormConstant.HBPM_POSITIONHR}, PositionStructureConstant.NCKD_JOBSEQ)
+                .addGroup(new String[]{FormConstant.HBPM_POSITIONHR, PositionStructureConstant.NCKD_JOBSEQ}, FormConstant.NUMBER_KEY);
+
+
+    }
+}

+ 72 - 1
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/form/contribution/ContribBillFormPlugin.java

@@ -1,16 +1,25 @@
 package nckd.jxccl.hr.psms.plugin.form.contribution;
 
+import kd.bos.bill.BillShowParameter;
 import kd.bos.bill.OperationStatus;
 import kd.bos.dataentity.entity.DynamicObject;
 import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.dataentity.entity.ILocaleString;
+import kd.bos.dataentity.metadata.IDataEntityProperty;
+import kd.bos.entity.BasedataEntityType;
 import kd.bos.entity.datamodel.events.ChangeData;
+import kd.bos.entity.datamodel.events.IDataModelChangeListener;
 import kd.bos.entity.datamodel.events.PropertyChangedArgs;
+import kd.bos.entity.property.BasedataProp;
 import kd.bos.form.FormShowParameter;
 import kd.bos.form.field.BasedataEdit;
+import kd.bos.form.field.events.AfterBindingDataEvent;
+import kd.bos.form.field.events.BasedataEditListener;
 import kd.bos.form.field.events.BeforeF7SelectEvent;
 import kd.bos.form.field.events.BeforeF7SelectListener;
 import kd.bos.form.plugin.AbstractFormPlugin;
 import kd.bos.list.ListShowParameter;
+import kd.bos.mvc.bill.BillView;
 import kd.bos.orm.query.QCP;
 import kd.bos.orm.query.QFilter;
 import kd.bos.servicehelper.QueryServiceHelper;
@@ -37,7 +46,69 @@ import java.util.Objects;
 * @date 2025/10/25 22:57
 * @version 1.0
 */
-public class ContribBillFormPlugin extends AbstractFormPlugin implements Plugin, BeforeF7SelectListener {
+public class ContribBillFormPlugin extends AbstractFormPlugin implements Plugin, BeforeF7SelectListener, BasedataEditListener, IDataModelChangeListener {
+
+    @Override
+    public void initialize() {
+        this.getModel().addDataModelChangeListener(this);
+        BasedataEdit mulEdit = this.getControl("nckd_scoreitemsub");
+        mulEdit.addBasedataEditListener(this);
+    }
+
+    @Override
+    public void afterBindingData(AfterBindingDataEvent evt) {
+        BillShowParameter showParameter = (BillShowParameter) this.getView().getFormShowParameter();
+        String formId = showParameter.getFormId();
+        if(formId.equalsIgnoreCase("nckd_contribbill_i") || formId.equalsIgnoreCase("nckd_contribbill_g")){
+            BasedataEdit edit = (BasedataEdit) evt.getSource();
+            Object v = evt.getDataEntity();
+            Object editSearchProp = null;
+            Object displayProp = "";
+            if (v == null) {
+                return;
+            }
+
+            BasedataEntityType dt;
+            if (((DynamicObject) v).getDataEntityType() instanceof BasedataEntityType) {
+                dt = (BasedataEntityType) ((DynamicObject) v).getDataEntityType();
+            } else {
+                dt = (BasedataEntityType) ((BasedataProp) edit.getProperty()).getComplexType();
+            }
+
+            //获取数据包中的名称字段值
+            String nameKey = dt.getNameProperty();
+            IDataEntityProperty p2 = dt.findProperty(nameKey);
+            if (p2 != null) {
+                displayProp = p2.getValueFast(v);
+                if (displayProp instanceof ILocaleString) {
+                    displayProp = displayProp.toString();
+                }
+            }
+
+            //动态修改多选基础资料的显示属性为名称(部门)
+            if ("nckd_scoreitemsub".equals(edit.getKey())) {
+                nameKey = "nckd_scoreitemlevel";
+            }
+            IDataEntityProperty p4 = dt.findProperty(nameKey);
+            if (p4 != null) {
+                Object valueFast = p4.getValueFast(v);
+                if(valueFast instanceof DynamicObject){
+                    displayProp = ConvertUtil.toDynamicObjectOrNull(valueFast).getString(FormConstant.NAME_KEY);
+                    editSearchProp = ConvertUtil.toDynamicObjectOrNull(valueFast).getString(FormConstant.NUMBER_KEY);
+
+                }
+            }
+
+            //设置显示属性
+            evt.setDisplayProp(displayProp.toString());
+            //设置编辑显示属性
+            evt.setEditSearchProp(editSearchProp == null ? "" : editSearchProp.toString());
+        }
+
+       /* //修改"单项奖项目",F7显示字段
+        */
+    }
+
 
     @Override
     public void afterCreateNewData(EventObject e) {

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

@@ -1,20 +1,56 @@
 package nckd.jxccl.hr.psms.plugin.form.other;
 
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import kd.bos.consts.PermItemConst;
+import kd.bos.context.RequestContext;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.dataentity.entity.LocaleString;
 import kd.bos.entity.datamodel.ListSelectedRow;
 import kd.bos.entity.datamodel.ListSelectedRowCollection;
+import kd.bos.entity.datamodel.events.PackageDataEvent;
 import kd.bos.form.CloseCallBack;
 import kd.bos.form.FormShowParameter;
+import kd.bos.form.IPageCache;
+import kd.bos.form.ListVisible;
 import kd.bos.form.ShowType;
+import kd.bos.form.control.grid.DataGrid;
+import kd.bos.form.control.grid.events.BeforeCreateDataGridColumnsEvent;
+import kd.bos.form.control.grid.events.BeforeCreateDataGridColumnsListener;
+import kd.bos.form.control.grid.events.DataGridBindDataEvent;
+import kd.bos.form.control.grid.events.DataGridBindDataListener;
 import kd.bos.form.events.AfterDoOperationEventArgs;
+import kd.bos.form.events.BeforeCreateListColumnsArgs;
+import kd.bos.form.events.BeforeCreateListDataProviderArgs;
 import kd.bos.form.events.ClosedCallBackEvent;
+import kd.bos.list.IListColumn;
+import kd.bos.list.ListColumn;
 import kd.bos.list.ListShowParameter;
 import kd.bos.list.events.ListRowClickEvent;
 import kd.bos.list.plugin.AbstractListPlugin;
+import kd.bos.mvc.list.ListDataProvider;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
+import kd.bos.servicehelper.QueryServiceHelper;
+import kd.hr.hbp.common.model.AuthorizedOrgResultWithSub;
+import kd.hr.hbp.common.model.OrgSubInfo;
+import kd.sdk.hr.hbp.business.helper.permission.HRPermissionServiceHelper;
 import kd.sdk.plugin.Plugin;
 import nckd.jxccl.base.common.constant.FormConstant;
+import nckd.jxccl.base.common.utils.QueryFieldBuilder;
 import nckd.jxccl.hr.psms.common.PositionStructureConstant;
+import org.apache.commons.lang3.StringUtils;
 
+import java.util.ArrayList;
 import java.util.EventObject;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
 
 /**
 * 关键行为评价表
@@ -68,4 +104,12 @@ public class KeyBeHavEvalListPlugin extends AbstractListPlugin implements Plugin
             }
         }
     }
+
+
+    private static List<Long> extractOrgIds(List<OrgSubInfo> orgSubInfos) {
+        return orgSubInfos.stream()
+                .map(OrgSubInfo::getOrgId)
+                .collect(Collectors.toList());
+    }
+
 }

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

@@ -0,0 +1,48 @@
+package nckd.jxccl.hr.psms.plugin.form.other;
+
+import kd.bos.form.control.grid.DataGrid;
+import kd.bos.form.control.grid.events.BeforeCreateDataGridColumnsEvent;
+import kd.bos.form.control.grid.events.BeforeCreateDataGridColumnsListener;
+import kd.bos.form.control.grid.events.DataGridBindDataEvent;
+import kd.bos.form.control.grid.events.DataGridBindDataListener;
+import kd.bos.form.plugin.AbstractFormPlugin;
+import kd.sdk.plugin.Plugin;
+
+import java.util.EventObject;
+
+/**
+ * 动态表单插件
+ */
+public class KeyBeHavEvalReptFormPlugin extends AbstractFormPlugin implements  Plugin, BeforeCreateDataGridColumnsListener, DataGridBindDataListener {
+
+    /**
+     * 注册监听事件
+     * @param event
+     */
+    @Override
+    public void registerListener(EventObject event) {
+        registerDataGridListener();
+    }
+
+    /**
+     * 通过事件监听,注册数据表格监听事件
+     */
+    private void registerDataGridListener() {
+        DataGrid dataGrid = this.getControl("reportlistap");
+        // 注册创建列监听事件
+        dataGrid.addBeforeCreateDataGridColumnsListener(this);
+        // 注册绑定数据监听事件
+        dataGrid.addBindDataListener(this);
+
+    }
+
+    @Override
+    public void beforeCreateDataGridColumns(BeforeCreateDataGridColumnsEvent beforeCreateDataGridColumnsEvent) {
+
+    }
+
+    @Override
+    public void dataGridBindData(DataGridBindDataEvent dataGridBindDataEvent) {
+
+    }
+}

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

@@ -58,7 +58,13 @@ public class SeniorAppointMgmtFormPlugin extends AbstractFormPlugin implements T
             openTargetPage("nckd_seniorappoint", "nckd_seniorappoint");
         } else if ("nckd_keybehaveval".equalsIgnoreCase(currentTab)) {
             //打开“关键行为人员”列表
-            openTargetPage("nckd_keybehaveval","nckd_keybehaveval");
+//            openTargetPage("nckd_keybehavevalrept","nckd_keybehaveval");
+            ReportShowParameter reportShowParameter = new ReportShowParameter();
+            reportShowParameter.setFormId("nckd_keybehavevalrept");
+            reportShowParameter.getOpenStyle().setShowType(ShowType.InContainer);
+            reportShowParameter.getOpenStyle().setTargetKey("nckd_keybehaveval");
+            reportShowParameter.setCaption("关键行为人员");
+            this.getView().showForm(reportShowParameter);
         }
     }
 

+ 38 - 0
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/form/other/impt/KeyBeHavEvalProjRsltImportPlugin.java

@@ -0,0 +1,38 @@
+package nckd.jxccl.hr.psms.plugin.form.other.impt;
+
+import kd.bos.orm.query.QFilter;
+import kd.hr.hbp.formplugin.web.HRDataBaseList;
+import kd.hr.impt.common.plugin.AfterLoadStartPageEventArgs;
+import kd.hr.impt.common.plugin.BeforeQueryRefBdEventArgs;
+import kd.hr.impt.common.plugin.HRImportPlugin;
+
+import java.util.LinkedHashSet;
+
+/**
+* 关键行为项目评价结果
+* 实体标识:nckd_keybehavevalprojrslt
+* @author W.Y.C
+* @date 2025/12/26 14:43
+* @version 1.0
+*/
+public class KeyBeHavEvalProjRsltImportPlugin extends HRDataBaseList implements HRImportPlugin {
+    @Override
+    public void afterLoadStartPage(AfterLoadStartPageEventArgs args) {
+        args.setFormId("nckd_keybehavevalprojrslt");
+    }
+
+    @Override
+    public void beforeQueryRefBd(BeforeQueryRefBdEventArgs args) {
+        String fieldId = args.getFieldId();
+        if(fieldId.equalsIgnoreCase("nckd_keybehavconfentry")){
+            LinkedHashSet<String> select = new LinkedHashSet<>();
+            select.add("id");
+            select.add("number");
+            select.add("name");
+            select.add("nckd_keybehavconf.nckd_org.name");
+            select.add("nckd_keybehavconf.nckd_jobseqhr.name");
+            args.setSelectFields(select);
+            args.setFilters( new QFilter[]{QFilter.of("1=1")});
+        }
+    }
+}

+ 124 - 0
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/form/other/report/KeyBeHavEvalReptQueryFromPlugin.java

@@ -0,0 +1,124 @@
+package nckd.jxccl.hr.psms.plugin.form.other.report;
+
+import kd.bos.dataentity.entity.DynamicObject;
+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.control.Control;
+import kd.bos.form.control.events.BeforeItemClickEvent;
+import kd.bos.form.control.events.RowClickEvent;
+import kd.bos.form.control.events.RowClickEventListener;
+import kd.bos.form.events.AfterDoOperationEventArgs;
+import kd.bos.form.events.ClosedCallBackEvent;
+import kd.bos.form.plugin.AbstractFormPlugin;
+import kd.bos.list.ListShowParameter;
+import kd.bos.list.events.BackPressedEvent;
+import kd.bos.list.events.EndSelectEvent;
+import kd.bos.list.events.ItemSelectEvent;
+import kd.bos.list.events.ListSelectedListener;
+import kd.bos.list.events.QueryListEvent;
+import kd.bos.list.events.SelectEvent;
+import kd.bos.plugin.sample.dynamicform.pcform.entrygrid.template.EntryRowClick;
+import kd.bos.report.ReportList;
+import kd.bos.report.ReportShowParameter;
+import kd.sdk.plugin.Plugin;
+import nckd.jxccl.base.common.constant.FormConstant;
+import scala.Int;
+
+import java.util.ArrayList;
+import java.util.EventObject;
+import java.util.List;
+
+/**
+ * 动态表单插件
+ */
+public class KeyBeHavEvalReptQueryFromPlugin extends AbstractFormPlugin implements Plugin {
+
+    @Override
+    public void registerListener(EventObject e) {
+        ReportList reportList = getControl("reportlistap");
+        Integer currentPageIndex = reportList.getEntryState().getCurrentPageIndex();
+        Integer pageRows = reportList.getEntryState().getPageRows();
+        //报表行点击事件
+        reportList.addRowClickListener(new RowClickEventListener() {
+            //列表选择行事件监听
+            @Override
+            public void entryRowClick(RowClickEvent evt) {
+                int rowCount = reportList.getReportModel().getRowCount();
+                int row = evt.getRow();
+                int startRow = row - 3;
+                if(startRow <= 1){
+                    startRow = 1;
+                }
+                int endRow = row + 3;
+                if(endRow >= rowCount){
+                    endRow = rowCount;
+                }
+
+                DynamicObject selectRowData = reportList.getReportModel().getRowData(row);
+                if(selectRowData != null) {
+                    reportList.clearSelection();
+                    long selectPerson = selectRowData.getLong(String.join(".", FormConstant.NCKD_PERSON, FormConstant.ID_KEY));
+                    List<Integer> selectRows = new ArrayList<>();
+                    for (int i = startRow; i <= endRow; i++) {
+                        DynamicObject rowDate = reportList.getReportModel().getRowData(i);
+                        long personid = rowDate.getLong(String.join(".", FormConstant.NCKD_PERSON, FormConstant.ID_KEY));
+                        if(personid == selectPerson){
+                            selectRows.add( i);
+                        }
+                    }
+                    if(!selectRows.isEmpty()){
+                        int[] selectRowsArray = selectRows.stream().mapToInt(Integer::intValue).toArray();
+                        reportList.selectRows(selectRowsArray, selectRows.get(selectRows.size() - 1));
+                    }
+
+                }
+            }
+        });
+        this.addItemClickListeners(FormConstant.TOOLBARAP);
+        this.addItemClickListeners(new String[]{"btnclose"});
+    }
+
+    public void beforeItemClick(BeforeItemClickEvent evt) {
+        super.beforeItemClick(evt);
+        String itemKey = evt.getItemKey();
+        if ("nckd_tblclose".equals(itemKey)) {
+            this.getView().getParentView().invokeOperation("close");
+            this.getView().sendFormAction(this.getView().getParentView());
+        }
+
+    }
+
+    @Override
+    public void afterDoOperation(AfterDoOperationEventArgs e) {
+        String operateKey = e.getOperateKey();
+        if(e.getOperationResult() != null && e.getOperationResult().isSuccess()){
+            if("newappointment".equalsIgnoreCase(operateKey)) {
+                ReportList reportList = this.getView().getControl("reportlistap");
+                int[] selectedRows = reportList.getEntryState().getSelectedRows();
+                if(selectedRows != null && selectedRows.length > 0) {
+                    DynamicObject rowData = reportList.getReportModel().getRowData(selectedRows[0]);
+                    FormShowParameter showParameter = new FormShowParameter();
+                    showParameter.setFormId("nckd_newseniorappoint");
+                    showParameter.getOpenStyle().setShowType(ShowType.Modal);
+                    showParameter.setCaption("新建聘任");
+                    showParameter.setCustomParam("selectRow", rowData.getLong(FormConstant.ID_KEY));
+                    showParameter.setCloseCallBack(new CloseCallBack(this, "nckd_newseniorappoint"));
+                    this.getView().showForm(showParameter);
+                }
+            }
+        }
+    }
+
+    @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("聘任成功!");
+            }
+        }
+    }
+}

+ 449 - 0
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/form/other/report/KeyBeHavEvalReptQueryPlugin.java

@@ -0,0 +1,449 @@
+package nckd.jxccl.hr.psms.plugin.form.other.report;
+
+import kd.bos.algo.DataSet;
+import kd.bos.algo.GroupbyDataSet;
+import kd.bos.algo.JoinType;
+import kd.bos.algo.Row;
+import kd.bos.consts.PermItemConst;
+import kd.bos.context.RequestContext;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.dataentity.entity.LocaleString;
+import kd.bos.entity.report.AbstractReportColumn;
+import kd.bos.entity.report.AbstractReportListDataPlugin;
+import kd.bos.entity.report.DynamicReportColumnEvent;
+import kd.bos.entity.report.FastFilter;
+import kd.bos.entity.report.ReportColumn;
+import kd.bos.entity.report.ReportQueryParam;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
+import kd.bos.servicehelper.QueryServiceHelper;
+import kd.hr.hbp.common.model.AuthorizedOrgResultWithSub;
+import kd.hr.hbp.common.model.OrgSubInfo;
+import kd.sdk.hr.hbp.business.helper.permission.HRPermissionServiceHelper;
+import kd.sdk.plugin.Plugin;
+import nckd.jxccl.base.common.algo.GroupMaxStrFunction;
+import nckd.jxccl.base.common.constant.FormConstant;
+import nckd.jxccl.base.common.utils.QueryFieldBuilder;
+import nckd.jxccl.hr.psms.common.PositionStructureConstant;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+* 关键行为评价报表查询插件
+* 该插件用于查询和展示关键行为评价结果,支持动态列和行转列功能
+* 实体标识:nckd_keybehavevalrept
+* @author W.Y.C
+* @date 2025/12/27 18:05
+* @version 1.0
+*/
+public class KeyBeHavEvalReptQueryPlugin extends AbstractReportListDataPlugin implements Plugin {
+
+    // 常量定义
+    private static final String PERSON_ID_FIELD = String.join(".", FormConstant.NCKD_PERSON, FormConstant.ID_KEY);
+    private static final String PROJECT_NUMBER_FIELD = String.join(".", PositionStructureConstant.NCKD_KEYBEHAVCONFENTRY, FormConstant.NUMBER_KEY);
+    private static final String PROJECT_NAME_FIELD = String.join(".", PositionStructureConstant.NCKD_KEYBEHAVCONFENTRY, FormConstant.NAME_KEY);
+    private static final String RESULT_FIELD = "case when "+PositionStructureConstant.NCKD_RESULT+" = '1' then '满足' else '不满足' end";
+
+//    private static final String RESULT_FIELD = PositionStructureConstant.NCKD_RESULT;
+
+    @Override
+    public void getDynamicColumns(DynamicReportColumnEvent event) {
+        super.getDynamicColumns(event);
+    }
+
+    /**
+     * 查询报表数据
+     * 实现行转列逻辑,将评价项目结果转换为报表列
+     */
+    @Override
+    public DataSet query(ReportQueryParam reportQueryParam, Object o) throws Throwable {
+
+        // 1. 获取权限范围内的组织ID
+//        List<Long> authorizedOrgIds = getAuthorizedOrgIds();
+        
+        // 2. 查询关键行为评价项目结果数据
+        DataSet keyBeHavEvalProjRsltDataSet = queryKeyBeHavEvalProjRsltDataSet();
+        
+        // 3. 获取唯一项目编号(需要用于动态列的项目)
+        Set<String> uniqueProjectNumbers = extractUniqueProjectNumbers(keyBeHavEvalProjRsltDataSet);
+        
+        // 4. 行转列处理
+        DataSet pivotResultDataSet = transformRowsToColumns(keyBeHavEvalProjRsltDataSet, uniqueProjectNumbers);
+
+        // 5. 查询主表数据
+        // 处理快速过滤条件
+        QFilter qFilter = QFilter.of("1=1");
+        //按权限范围过滤
+        QFilter dataRule = HRPermissionServiceHelper.getDataRule(
+                RequestContext.get().getCurrUserId(), "nckd_psmsfile", PositionStructureConstant.PERSONPOSFILE_ENTITYID,
+                PermItemConst.ITEM_VIEW, new HashMap<>());
+        if (dataRule != null) {
+            Object value = dataRule.getValue();
+            qFilter.and(String.join(".",FormConstant.NCKD_PERSON,FormConstant.HRPI_EMPPOSORGREL, FormConstant.ADMINORG), QCP.in, value);
+        }
+
+        processFastFilter(reportQueryParam, qFilter);
+        //其他过滤条件
+        processFilter(reportQueryParam, qFilter);
+
+        DataSet mainTableDataSet = queryMainTableDataSet(qFilter);
+
+        // 6. 关联主表和行转列结果
+        DataSet finalResultDataSet = joinMainAndPivotData(mainTableDataSet, pivotResultDataSet);
+        
+        return finalResultDataSet;
+    }
+
+    /**
+     * 获取报表列定义
+     * 根据数据库中的项目动态生成报表列
+     */
+    @Override
+    public List<AbstractReportColumn> getColumns(List<AbstractReportColumn> columns) throws Throwable {
+        
+        // 获取唯一项目信息
+        List<ProjectInfo> projectInfoList = getUniqueProjectInfo();
+        
+        // 为每个唯一项目创建列
+        for (ProjectInfo projectInfo : projectInfoList) {
+            ReportColumn newColumn = createReportColumn(projectInfo);
+            columns.add(newColumn);
+        }
+        
+        return columns;
+    }
+
+    /**
+     * 创建报表列
+     */
+    private ReportColumn createReportColumn(ProjectInfo projectInfo) {
+        ReportColumn column = new ReportColumn();
+        column.setCaption(new LocaleString(projectInfo.getProjectName()));
+        column.setFieldKey("p_"+projectInfo.getProjectNumber());
+        column.setFieldType(ReportColumn.TYPE_TEXT);
+        return column;
+
+/*
+        // 1. 创建下拉列表列
+        ComboReportColumn comboColumn = new ComboReportColumn();
+        // 2. 设置关键属性
+        comboColumn.setFieldKey("fruitname"); // 与查询结果字段对应
+        comboColumn.setFieldType(ReportColumn.TYPE_COMBO); // 类型必须为 COMBO
+        comboColumn.setCaption(new LocaleString("水果名称")); // 列标题
+
+        // 3. (可选)设置下拉选项。这里示例是静态的,实际可从数据库或上下文动态获取。
+        List<ValueMapItem> items = new ArrayList<>();
+        items.add(new ValueMapItem("apple", "苹果"));
+        items.add(new ValueMapItem("banana", "香蕉"));
+        comboColumn.setComboItems(items);
+
+        // 4. 将列添加到列集合
+        columns.add(comboColumn);*/
+    }
+
+    /**
+     * 获取项目信息列表
+     */
+    private List<ProjectInfo> getUniqueProjectInfo() {
+        QueryFieldBuilder resultFieldBuilder = createResultFieldBuilder();
+//        QFilter filter = createOrgFilter(orgIds);
+
+        QFilter filter = QFilter.of("1=1");
+        QFilter dataRule = HRPermissionServiceHelper.getDataRule(
+                RequestContext.get().getCurrUserId(), "nckd_psmsfile", PositionStructureConstant.PERSONPOSFILE_ENTITYID,
+                PermItemConst.ITEM_VIEW, new HashMap<>());
+        if (dataRule != null) {
+            Object value = dataRule.getValue();
+            filter.and(String.join(".",PositionStructureConstant.NCKD_KEYBEHAVCONFENTRY,"nckd_keybehavconf",FormConstant.NCKD_ORG, FormConstant.ID_KEY), QCP.in, value);
+            filter.and(String.join(".",FormConstant.NCKD_PERSON,FormConstant.HRPI_EMPPOSORGREL, FormConstant.ADMINORG), QCP.in, value);
+        }
+        DynamicObjectCollection keyBeHavEvalProjRslt = QueryServiceHelper.query(
+                PositionStructureConstant.KEYBEHAVEVALPROJRSLT_ENTITYID, 
+                resultFieldBuilder.buildSelect(), 
+                new QFilter[]{filter}
+        );
+        
+        // 根据项目编码去重
+        Set<String> processedProjectNumbers = new HashSet<>();
+        List<ProjectInfo> uniqueProjectList = new ArrayList<>();
+        for (DynamicObject obj : keyBeHavEvalProjRslt) {
+            String projectNumber = obj.getString(PROJECT_NUMBER_FIELD);
+            String projectName = obj.getString(PROJECT_NAME_FIELD);
+            
+            if (projectNumber != null && processedProjectNumbers.add(projectNumber)) {
+                uniqueProjectList.add(new ProjectInfo(projectNumber, projectName));
+            }
+        }
+        
+        return uniqueProjectList;
+    }
+
+    /**
+     * 获取用户有权限的组织ID列表
+     */
+    private List<Long> getAuthorizedOrgIds() {
+        Long currentUserId = RequestContext.get().getCurrUserId();
+        AuthorizedOrgResultWithSub userAdminOrgWithSub = HRPermissionServiceHelper.getUserAdminOrgsWithSub(
+                currentUserId, "nckd_psmsbase", "nckd_keybehavconf",
+                PermItemConst.ITEM_VIEW, "nckd_org", new HashMap<>());
+
+        if (userAdminOrgWithSub.isHasAllOrgPerm()) {
+            return new ArrayList<>(); // 如果有所有组织权限,返回空列表表示无限制
+        }
+        
+        return extractOrgIds(userAdminOrgWithSub.getHasPermOrgsWithSub());
+    }
+
+    /**
+     * 查询关键行为评价项目结果数据集
+     */
+    private DataSet queryKeyBeHavEvalProjRsltDataSet() {
+        QueryFieldBuilder resultFieldBuilder = createResultFieldBuilder();
+//        QFilter filter = createOrgFilter(orgIds);
+        QFilter filter = QFilter.of("1=1");
+        QFilter dataRule = HRPermissionServiceHelper.getDataRule(
+                RequestContext.get().getCurrUserId(), "nckd_psmsfile", PositionStructureConstant.PERSONPOSFILE_ENTITYID,
+                PermItemConst.ITEM_VIEW, new HashMap<>());
+        if (dataRule != null) {
+            Object value = dataRule.getValue();
+            filter.and("nckd_person.hrpi_empposorgrel.adminorg",QCP.in, value);
+        }
+        return QueryServiceHelper.queryDataSet(this.getClass().getName(),
+                PositionStructureConstant.KEYBEHAVEVALPROJRSLT_ENTITYID, 
+                resultFieldBuilder.buildSelect(), 
+                new QFilter[]{filter}, 
+                null);
+    }
+
+    /**
+     * 创建结果字段构建器
+     */
+    private QueryFieldBuilder createResultFieldBuilder() {
+        return QueryFieldBuilder.create()
+                .add(FormConstant.ID_KEY)
+                .addIdNumberName(FormConstant.NCKD_PERSON)
+                .addIdNumberName(PositionStructureConstant.NCKD_KEYBEHAVCONFENTRY)
+                .add(PositionStructureConstant.NCKD_RESULT);
+    }
+
+
+    /**
+     * 提取唯一的项目编号
+     */
+    private Set<String> extractUniqueProjectNumbers(DataSet keyBeHavEvalProjRsltDataSet) {
+        DataSet copyDataSet = keyBeHavEvalProjRsltDataSet.copy();
+        Set<String> uniqueProjectNumbers = new HashSet<>();
+        
+        while (copyDataSet.hasNext()) {
+            Row row = copyDataSet.next();
+            String projectNumber = row.getString(PROJECT_NUMBER_FIELD);
+            if (projectNumber != null) {
+                uniqueProjectNumbers.add(projectNumber);
+            }
+        }
+        
+        return uniqueProjectNumbers;
+    }
+
+    /**
+     * 将行数据转换为列数据(行转列)
+     */
+    private DataSet transformRowsToColumns(DataSet originalDataSet, Set<String> projectNumbers) {
+        DataSet workingDataSet = originalDataSet;
+        
+        // 为每个项目编号添加计算字段(行转列)
+        List<String> columnFieldNames = new ArrayList<>();
+        for (String projectNumber : projectNumbers) {
+            String caseExpression = String.format(
+                "CASE WHEN %s = '%s' THEN %s ELSE '' END",
+                PROJECT_NUMBER_FIELD,
+                projectNumber,
+                RESULT_FIELD
+            );
+            
+            workingDataSet = workingDataSet.addField(caseExpression, "p_"+projectNumber);
+            columnFieldNames.add("p_"+projectNumber);
+        }
+
+        GroupMaxStrFunction groupMaxStr = new GroupMaxStrFunction();
+        GroupbyDataSet groupbyDataSet = workingDataSet.groupBy(new String[]{PERSON_ID_FIELD});
+        for (String projectNumber : projectNumbers) {
+            groupbyDataSet
+                    .agg(groupMaxStr,"p_"+projectNumber, "p_"+projectNumber);
+        }
+        // 添加人员ID字段用于关联
+        columnFieldNames.add(PERSON_ID_FIELD);
+        return groupbyDataSet.finish();
+    }
+
+    /**
+     * 查询主表数据
+     */
+    private DataSet queryMainTableDataSet(QFilter qFilter) {
+        QueryFieldBuilder queryFieldBuilder = buildQueryFieldBuilder();
+        return QueryServiceHelper.queryDataSet("KeyBeHavEvalReptQueryPlugin", 
+                PositionStructureConstant.KEYBEHAVEVAL_ENTITYID, 
+                queryFieldBuilder.buildSelect(),
+                new QFilter[]{qFilter},
+                queryFieldBuilder.buildOrder());
+    }
+
+    /**
+     * 关联主表和行转列结果
+     */
+    private DataSet joinMainAndPivotData(DataSet mainTableDataSet, DataSet pivotDataSet) {
+        String[] mainTableFieldNames = mainTableDataSet.getRowMeta().getFieldNames();
+        String[] pivotFieldNames = pivotDataSet.getRowMeta().getFieldNames();
+        
+        return mainTableDataSet.join(pivotDataSet, JoinType.LEFT)
+                .on(String.join(".", FormConstant.NCKD_PERSON), 
+                    PERSON_ID_FIELD)
+                .select(mainTableFieldNames, pivotFieldNames)
+                .finish();
+    }
+
+    /**
+     * 构建主表查询字段
+     */
+    private QueryFieldBuilder buildQueryFieldBuilder() {
+        return QueryFieldBuilder.create()
+                .add(FormConstant.ID_KEY)
+                .add(FormConstant.NCKD_PERSON)
+                .add(FormConstant.NCKD_DEP)
+                .add(FormConstant.NCKD_DEP, FormConstant.NCKD_FIRSTORG)
+                .add(FormConstant.NCKD_DEP, FormConstant.NCKD_SECONDORG)
+                .add(FormConstant.NCKD_DEP, FormConstant.NCKD_THIRDORG)
+                .add(FormConstant.NCKD_DEP, FormConstant.NCKD_FOURTHORG)
+                .add(FormConstant.NCKD_DEP, FormConstant.NCKD_FIFTHORG)
+                .add(FormConstant.NCKD_DEP, FormConstant.NCKD_SIXTHORG)
+                .add(FormConstant.NCKD_JOBSEQ)
+                .add(PositionStructureConstant.NCKD_POSITION)
+                .add(PositionStructureConstant.NCKD_JOBLEVEL)
+                .add(PositionStructureConstant.NCKD_APPRAISALRESULT)
+                .add(PositionStructureConstant.NCKD_APPOINT)
+                .add(PositionStructureConstant.NCKD_MATCHCONDDESC)
+                .orderDesc(String.join(".",FormConstant.NCKD_PERSON,FormConstant.EMP_NUMBER_KEY))
+                .orderAsc(PositionStructureConstant.NCKD_JOBLEVEL);
+    }
+
+    /**
+     * 提取组织ID列表
+     */
+    private static List<Long> extractOrgIds(List<OrgSubInfo> orgSubInfos) {
+        return orgSubInfos.stream()
+                .map(OrgSubInfo::getOrgId)
+                .collect(Collectors.toList());
+    }
+
+    /**
+     * 项目信息内部类
+     */
+    private static class ProjectInfo {
+        private final String projectNumber;
+        private final String projectName;
+
+        public ProjectInfo(String projectNumber, String projectName) {
+            this.projectNumber = projectNumber;
+            this.projectName = projectName;
+        }
+
+        public String getProjectNumber() {
+            return projectNumber;
+        }
+
+        public String getProjectName() {
+            return projectName;
+        }
+    }
+
+    /**
+     * 关键行为评价项目结果值对象(保留原有类,用于兼容性)
+     */
+    class KeyBeHavEvalProjRsltVo {
+        private Long personId;
+        private String projectNumber;
+        private String projectName;
+        private String projectResult;
+
+        public KeyBeHavEvalProjRsltVo(Long personId, String projectNumber, String projectName, String projectResult) {
+            this.personId = personId;
+            this.projectNumber = projectNumber;
+            this.projectName = projectName;
+            this.projectResult = projectResult;
+        }
+    }
+
+    private void processFastFilter(ReportQueryParam reportQueryParam, QFilter qFilter) {
+        FastFilter fastFilter = reportQueryParam.getFilter().getFastFilter();
+        if (fastFilter != null) {
+            List<Map<String, List<Object>>> fastFilterList = fastFilter.getFastFilter();
+            for (Map<String, List<Object>> stringListMap : fastFilterList) {
+                //nckd_empnumfastfilter转为employee.empnumber,nckd_namefastfilter转换为employee.name,转换后添加到fields中
+                List<Object> fieldList = stringListMap.get("FieldName");
+                List<Object> valueList = stringListMap.get("Value");
+                String[] fields = new String[fieldList.size()];
+                for (int i = 0; i < fieldList.size(); i++) {
+                    fields[i] = fieldList.get(i).toString()
+                            .replace("nckd_empnumfastfilter", String.join(".", FormConstant.NCKD_PERSON,FormConstant.EMP_NUMBER_KEY))
+                            .replace("nckd_namefastfilter", String.join(".", FormConstant.NCKD_PERSON,FormConstant.NAME_KEY));
+                }
+                //valueList转到values
+                String[] values = new String[valueList.size()];
+                for (int i = 0; i < valueList.size(); i++) {
+                    values[i] = valueList.get(i).toString();
+                }
+                QFilter orFilter = null;
+                for (String field : fields) {
+                    for (String value : values) {
+                        if (orFilter == null) {
+                            orFilter = new QFilter(field, QCP.like, "%" + value + "%");
+                        } else {
+                            orFilter = orFilter.or(field, QCP.like, "%" + value + "%");
+                        }
+                    }
+
+                }
+
+                if(orFilter != null) {
+                    qFilter.and(orFilter);
+                }
+            }
+        }
+    }
+
+    /**
+     * 处理过滤条件
+     */
+    private void processFilter(ReportQueryParam reportQueryParam, QFilter qFilter) {
+        List<QFilter> qFilters = reportQueryParam.getFilter().getQFilters();
+        for (QFilter filter : qFilters) {
+            //由于页面命名限制不允许配置对应数据库字段(例如:position.id的格式),这里只能手动转换为数据库实际的字段
+            String property = filter.getProperty();
+            if ("nckd_secondorg.id".equalsIgnoreCase(property)){
+                qFilter.and(new QFilter(String.join(".", FormConstant.NCKD_DEP,FormConstant.NCKD_SECONDORG,FormConstant.ID_KEY),filter.getCP(),filter.getValue()));
+            }
+            if ("nckd_thirdorg.id".equalsIgnoreCase(property)){
+                qFilter.and(new QFilter(String.join(".", FormConstant.NCKD_DEP,FormConstant.NCKD_THIRDORG,FormConstant.ID_KEY),filter.getCP(),filter.getValue()));
+            }
+            if ("nckd_fourthorg.id".equalsIgnoreCase(property)){
+                qFilter.and(new QFilter(String.join(".", FormConstant.NCKD_DEP,FormConstant.NCKD_FOURTHORG,FormConstant.ID_KEY),filter.getCP(),filter.getValue()));
+            }
+            if ("nckd_fifthorg.id".equalsIgnoreCase(property)){
+                qFilter.and(new QFilter(String.join(".", FormConstant.NCKD_DEP,FormConstant.NCKD_FIFTHORG,FormConstant.ID_KEY),filter.getCP(),filter.getValue()));
+            }
+            if ("nckd_sixthorg.id".equalsIgnoreCase(property)){
+                qFilter.and(new QFilter(String.join(".", FormConstant.NCKD_DEP,FormConstant.NCKD_SIXTHORG,FormConstant.ID_KEY),filter.getCP(),filter.getValue()));
+            }
+            if ("nckd_position.id".equalsIgnoreCase(property)){
+                qFilter.and(new QFilter(String.join(".", FormConstant.NCKD_POSITION_KEY,FormConstant.ID_KEY),filter.getCP(),filter.getValue()));
+            }
+        }
+    }
+}

+ 1 - 1
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/operate/annualadjust/AnnualAdjustmentOperationPlugin.java

@@ -124,7 +124,7 @@ public class AnnualAdjustmentOperationPlugin extends AbstractOperationServicePlu
                 LocalDateTime lastYear = DateUtil.minusYears(DateUtil.toLocalDateTime(adjustDate), 1);
                 DynamicObject performanceResult = PerformanceManagerHelper.getPerformanceResult(personId, lastYear);
                 if(performanceResult == null){
-                    addFatalErrorMessage(rowDataEntity,StrFormatter.format("人员【{}】缺少【{}】年考核结果", personName,lastYear));
+                    addFatalErrorMessage(rowDataEntity,StrFormatter.format("人员【{}】缺少【{}】年考核结果", personName,lastYear.getYear()));
                 }
 
                 PositionAppointmentBO positionAppointment = PositionFileHelper.positionAppointmentQuery(personId, adjustDate);

+ 19 - 1
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/operate/other/MgrAppointMgmtTransferAfterEffectOp.java

@@ -35,6 +35,7 @@ import nckd.jxccl.hr.psms.common.PositionStructureConstant;
 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;
@@ -127,6 +128,22 @@ public class MgrAppointMgmtTransferAfterEffectOp extends AbstractOperationServic
 
         List<DynamicObject> newMgrAppointMgmt = new ArrayList<>();
         List<DynamicObject> endMgrAppointMgmt = new ArrayList<>();
+        List<Long> afectPersonIdList = new ArrayList<>();
+        for (DynamicObject dataEntity : e.getDataEntities()) {
+            DynamicObject afterPosition = dataEntity.getDynamicObject(FormConstant.APOSITION);
+            afectPersonIdList.add(afterPosition.getLong(FormConstant.ID_KEY));
+        }
+        Map<Long, DynamicObject> positionMap = new HashMap<>();
+        if(!afectPersonIdList.isEmpty()){
+            MainEntityType positionHrEntityType = EntityMetadataCache.getDataEntityType(FormConstant.HBPM_POSITIONHR);
+            DynamicObject[] positionArray = BusinessDataServiceHelper.load(afectPersonIdList.toArray(new Long[0]), positionHrEntityType);
+            positionMap = java.util.Arrays.stream(positionArray)
+                    .collect(Collectors.toMap(
+                            obj -> obj.getLong(FormConstant.ID_KEY),
+                            obj -> obj,
+                            (existing, replacement) -> existing // 如果有重复key,保留现有的值
+                    ));
+        }
         for (DynamicObject dataEntity : e.getDataEntities()) {
             //人员
             DynamicObject employee = dataEntity.getDynamicObject(FormConstant.BB_EM_TID);
@@ -137,8 +154,9 @@ public class MgrAppointMgmtTransferAfterEffectOp extends AbstractOperationServic
             DynamicObject beforeJobSeq = beforePosition.getDynamicObject(FormConstant.NCKD_JOBSEQ);*/
             //调入岗位
             DynamicObject afterPosition = dataEntity.getDynamicObject(FormConstant.APOSITION);
+            DynamicObject dbAfterPosition = positionMap.get(afterPosition.getLong(FormConstant.ID_KEY));
             //调入岗位
-            DynamicObject afterJobSeq = afterPosition.getDynamicObject(FormConstant.NCKD_JOBSEQ);
+            DynamicObject afterJobSeq = dbAfterPosition.getDynamicObject(FormConstant.NCKD_JOBSEQ);
             String afterJobSeqNumber = afterJobSeq != null ? afterJobSeq.getString(FormConstant.NUMBER_KEY) : null;
             //调动生效日期
             Date effectiveDate = dataEntity.getDate(FormConstant.B_EFFECTIVEDATE);

+ 21 - 197
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/task/KeyBeHavEvalTask.java

@@ -73,7 +73,7 @@ public class KeyBeHavEvalTask extends AbstractTask implements Plugin {
     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))
+            .put(JobSeqEnum.SKILL.getCode(), Lists.newArrayList(13,14,15))
             .build();
 
     @Override
@@ -101,57 +101,14 @@ public class KeyBeHavEvalTask extends AbstractTask implements Plugin {
                 ));
         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());
-
 
+        //TODO 职称/技能
 
         //查询近3年考核结果
         logger.info("开始查询近3年考核结果");
-        int threeYearsAgo = LocalDate.now().minusYears(2).getYear();
+        int threeYearsAgo = LocalDate.now().minusYears(3).getYear();
         Date beginDate = DateUtil.toDate(LocalDate.of(threeYearsAgo, 1, 1));
-        int currentYear = LocalDate.now().getYear();
+        int currentYear = LocalDate.now().getYear()-1;
         Date endDate = DateUtil.endOfYear(DateUtil.toDate(LocalDate.of(currentYear, 1, 1)));
         logger.info("考核结果查询时间范围: {} 到 {}", DateUtil.getYear(beginDate), DateUtil.getYear(endDate));
         //查询最近3年的数据
@@ -170,53 +127,6 @@ public class KeyBeHavEvalTask extends AbstractTask implements Plugin {
                 ));
         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());
@@ -225,39 +135,20 @@ public class KeyBeHavEvalTask extends AbstractTask implements Plugin {
         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);
+            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);
+                }
             }
             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);
@@ -277,27 +168,24 @@ public class KeyBeHavEvalTask extends AbstractTask implements Plugin {
                     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) {
+                        if (year == currentYear) {
                             appraisalResultYear1 = appraisalResult;
                             appraisalResultYearName1 = StringUtils.isBlank(appraisalResultName) ? "无" : appraisalResultName;
-                        } else if (year == currentYear - 2) {
+                        } else if (year == currentYear - 1) {
                             appraisalResultYear2 = appraisalResult;
                             appraisalResultYearName2 = StringUtils.isBlank(appraisalResultName) ? "无" : appraisalResultName;
-                        } else if (year == currentYear - 3) {
+                        } else if (year == currentYear - 2) {
                             appraisalResultYear3 = appraisalResult;
                             appraisalResultYearName3 = StringUtils.isBlank(appraisalResultName) ? "无" : appraisalResultName;
                         }
                     }
                 }
                 logger.debug("员工ID {} 考核结果: 第一年({})={}, 第二年({})={}, 第三年({})={}", 
-                    personId, currentYear - 1, appraisalResultYearName1, 
-                    currentYear - 2, appraisalResultYearName2, 
-                    currentYear - 3, appraisalResultYearName3);
+                    personId, currentYear, appraisalResultYearName1,
+                    currentYear - 1, appraisalResultYearName2,
+                    currentYear - 2, 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){
@@ -309,110 +197,56 @@ public class KeyBeHavEvalTask extends AbstractTask implements Plugin {
             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;
+                boolean isAppoint = 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("、",
@@ -420,30 +254,20 @@ public class KeyBeHavEvalTask extends AbstractTask implements Plugin {
                         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("职位序列:{}",jobSeq.getName()));
                 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_APPOINT, isAppoint ? 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++;
             }

+ 70 - 33
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/sdm/plugin/operate/SendTaskOpPlugin.java

@@ -17,18 +17,22 @@ import kd.bos.entity.plugin.args.BeginOperationTransactionArgs;
 import kd.bos.entity.plugin.args.EndOperationTransactionArgs;
 import kd.bos.exception.ErrorCode;
 import kd.bos.exception.KDBizException;
-import kd.bos.message.util.MessageUtils;
+import kd.bos.logging.Log;
+import kd.bos.logging.LogFactory;
 import kd.bos.orm.ORM;
 import kd.bos.orm.query.QCP;
 import kd.bos.orm.query.QFilter;
 import kd.bos.servicehelper.coderule.CodeRuleServiceHelper;
 import kd.bos.servicehelper.operation.SaveServiceHelper;
 import kd.bos.servicehelper.user.UserServiceHelper;
+import kd.bos.servicehelper.workflow.MessageCenterServiceHelper;
 import kd.bos.url.UrlService;
+import kd.bos.util.JSONUtils;
 import kd.bos.workflow.engine.msg.info.MessageInfo;
 import kd.hr.hbp.business.servicehelper.HRBaseServiceHelper;
 import kd.hr.hbp.business.servicehelper.HRQueryEntityHelper;
 import kd.hr.hbp.common.constants.history.HisModelDataStatusEnum;
+import kd.hr.hbp.common.util.HRCollUtil;
 import kd.hr.hbp.common.util.HRDateTimeUtils;
 import kd.hr.hbp.common.util.HRObjectUtils;
 import kd.sdk.hr.hrpi.business.helper.HRPIEmployeeServiceHelper;
@@ -40,6 +44,7 @@ import nckd.jxccl.hr.sdm.business.SdmBusinessService;
 import nckd.jxccl.hr.sdm.common.SanDingConstant;
 import nckd.jxccl.hr.sdm.common.SanDingPlanEntryStatus;
 
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -60,6 +65,7 @@ import java.util.stream.Collectors;
  * @date: 2025/12/3 15:01
  */
 public class SendTaskOpPlugin extends AbstractOperationServicePlugIn {
+    private static final Log logger = LogFactory.getLog(SendTaskOpPlugin.class);
 
     /** 特殊借调变动操作编码 */
     private static final String TSJD_CHGACTION_NUMBER = "JTCC_1001";
@@ -97,10 +103,39 @@ public class SendTaskOpPlugin extends AbstractOperationServicePlugIn {
         try {
             DynamicObject[] dyos = e.getDataEntities();
             // 推送消息
+            List<MessageInfo> messageInfos = new ArrayList<MessageInfo>();
             for (DynamicObject dyo : dyos) {
                 DynamicObjectCollection entryDyoColl = dyo.getDynamicObjectCollection(SanDingConstant.NCKD_ENTRYENTITY);
                 for (DynamicObject entryDyo : entryDyoColl) {
-                    //sendMessage(entryDyo);
+                    buildMessage(messageInfos, entryDyo);
+                }
+            }
+            if (HRCollUtil.isNotEmpty(messageInfos)) {
+                try {
+                    Map<String, Object> sendMsgResult = MessageCenterServiceHelper.batchSendMessages(messageInfos);
+                    boolean success = (Boolean)sendMsgResult.get("success");
+                    String description = (String)sendMsgResult.get("description");
+                    logger.info(String.format("successToSendMessageSanDingTaskSendTask: messageInfos.size: %s, success: %s, description: %s", messageInfos.size(), success, description));
+                    Map<String, Object> data = (Map<String, Object>) sendMsgResult.getOrDefault("data", new HashMap());
+                    if (!data.isEmpty()) {
+                        for(Long successMsgId : (List<Long>) data.getOrDefault("successMsgIds", new ArrayList())) {
+                            logger.info(String.format("successToSendMessageSanDingTaskSendTask-success: %s, messageID: %s", null, successMsgId));
+                        }
+
+                        Map<MessageInfo, String> failMsgs = (Map<MessageInfo, String>) data.getOrDefault("failMsgs", new HashMap());
+
+                        for(Map.Entry<MessageInfo, String> failMsg : failMsgs.entrySet()) {
+                            MessageInfo failMessageInfo = failMsg.getKey();
+                            String failDescription = failMsg.getValue();
+                            logger.info(String.format("successToSendMessageSanDingTaskSendTask-fail: %s, messageID: %s, description: %s", JSONUtils.toString(failMessageInfo), failMessageInfo.getId(), failDescription));
+                        }
+                    }
+                } catch (Exception var45) {
+                    try {
+                        logger.error("FailedSendMessageSanDingTaskSendTask: " + JSONUtils.toString(messageInfos));
+                    } catch (IOException var43) {
+                        logger.error("Failed to parse message: " + messageInfos);
+                    }
                 }
             }
         } catch (Exception ex) {
@@ -338,35 +373,34 @@ public class SendTaskOpPlugin extends AbstractOperationServicePlugIn {
             // 构建单据体
             DynamicObjectCollection sanDingTaskEntryDyoColl = sanDingTaskDyo.getDynamicObjectCollection(SanDingConstant.NCKD_ENTRYENTITY);
             List<Map<String, Long>> positionBoIdList = companyPositionMap.get(entryDyo.getLong(companyBoIdKey));
-            if (positionBoIdList == null || positionBoIdList.isEmpty()) {
-                continue;
-            }
-            for (Map<String, Long> positionOrgMap : positionBoIdList) {
-                DynamicObject sanDingTaskEntryDyo = sanDingTaskEntryDyoColl.addNew();
-                // 岗位BOID
-                Long positionBoId = positionOrgMap.get("positionBoId");
-                // 设置 组织
-                sanDingTaskEntryDyo.set(SanDingConstant.NCKD_ADMINORG, EntityHelper.newEntity(SanDingConstant.ADMINORG_ENTITYID, positionOrgMap.get("adminOrgSourceVid")));
-                // 设置 岗位
-                sanDingTaskEntryDyo.set(SanDingConstant.NCKD_POSITION_KEY, EntityHelper.newEntity(SanDingConstant.HBPM_POSITIONHR, positionOrgMap.get("positionSourceVid")));
-                // 设置 定员数
-                sanDingTaskEntryDyo.set(SanDingConstant.NCKD_AUTHORIZEDSTRENGTH_KEY, lastSanDingTaskMap.getOrDefault(entryDyo.getLong(companyBoIdKey)+"@"+positionBoId, 0));
-                // 设置 实际占编人数
-                sanDingTaskEntryDyo.set(SanDingConstant.NCKD_ACTUALSTAFFCOUNT_KEY, positionInStaffEmployeeCountMap.getOrDefault(positionBoId, 0));
-                // 设置 缺编人数
-                sanDingTaskEntryDyo.set(SanDingConstant.NCKD_STAFFINGSHORTFALL_KEY, 0);
-                // 设置 前一年流失人数(系统数)
-                sanDingTaskEntryDyo.set(SanDingConstant.NCKD_Y1OUT_SYS_KEY, y1OutSysMap.getOrDefault(positionBoId + "@" + y1, 0) + kgsddEmpPosOrgRelMap.getOrDefault(positionBoId + "@" + y1, 0));
-                // 设置 前两年流失人数(系统数)
-                sanDingTaskEntryDyo.set(SanDingConstant.NCKD_Y2OUT_SYS_KEY, y2OutSysMap.getOrDefault(positionBoId + "@" + y2, 0) + kgsddEmpPosOrgRelMap.getOrDefault(positionBoId + "@" + y2, 0));
-                // 设置 前三年流失人数(系统数)
-                sanDingTaskEntryDyo.set(SanDingConstant.NCKD_Y3OUT_SYS_KEY, y3OutSysMap.getOrDefault(positionBoId + "@" + y3, 0) + kgsddEmpPosOrgRelMap.getOrDefault(positionBoId + "@" + y3, 0));
-                // 设置 前一年流失人数(确认数)
-                sanDingTaskEntryDyo.set(SanDingConstant.NCKD_Y1OUT_CONF_KEY, sanDingTaskEntryDyo.get(SanDingConstant.NCKD_Y1OUT_SYS_KEY));
-                // 设置 前两年流失人数(确认数)
-                sanDingTaskEntryDyo.set(SanDingConstant.NCKD_Y2OUT_CONF_KEY, sanDingTaskEntryDyo.get(SanDingConstant.NCKD_Y2OUT_SYS_KEY));
-                // 设置 前三年流失人数(确认数)
-                sanDingTaskEntryDyo.set(SanDingConstant.NCKD_Y3OUT_CONF_KEY, sanDingTaskEntryDyo.get(SanDingConstant.NCKD_Y3OUT_SYS_KEY));
+            if (HRCollUtil.isNotEmpty(positionBoIdList)) {
+                for (Map<String, Long> positionOrgMap : positionBoIdList) {
+                    DynamicObject sanDingTaskEntryDyo = sanDingTaskEntryDyoColl.addNew();
+                    // 岗位BOID
+                    Long positionBoId = positionOrgMap.get("positionBoId");
+                    // 设置 组织
+                    sanDingTaskEntryDyo.set(SanDingConstant.NCKD_ADMINORG, EntityHelper.newEntity(SanDingConstant.ADMINORG_ENTITYID, positionOrgMap.get("adminOrgSourceVid")));
+                    // 设置 岗位
+                    sanDingTaskEntryDyo.set(SanDingConstant.NCKD_POSITION_KEY, EntityHelper.newEntity(SanDingConstant.HBPM_POSITIONHR, positionOrgMap.get("positionSourceVid")));
+                    // 设置 定员数
+                    sanDingTaskEntryDyo.set(SanDingConstant.NCKD_AUTHORIZEDSTRENGTH_KEY, lastSanDingTaskMap.getOrDefault(entryDyo.getLong(companyBoIdKey)+"@"+positionBoId, 0));
+                    // 设置 实际占编人数
+                    sanDingTaskEntryDyo.set(SanDingConstant.NCKD_ACTUALSTAFFCOUNT_KEY, positionInStaffEmployeeCountMap.getOrDefault(positionBoId, 0));
+                    // 设置 缺编人数
+                    sanDingTaskEntryDyo.set(SanDingConstant.NCKD_STAFFINGSHORTFALL_KEY, 0);
+                    // 设置 前一年流失人数(系统数)
+                    sanDingTaskEntryDyo.set(SanDingConstant.NCKD_Y1OUT_SYS_KEY, y1OutSysMap.getOrDefault(positionBoId + "@" + y1, 0) + kgsddEmpPosOrgRelMap.getOrDefault(positionBoId + "@" + y1, 0));
+                    // 设置 前两年流失人数(系统数)
+                    sanDingTaskEntryDyo.set(SanDingConstant.NCKD_Y2OUT_SYS_KEY, y2OutSysMap.getOrDefault(positionBoId + "@" + y2, 0) + kgsddEmpPosOrgRelMap.getOrDefault(positionBoId + "@" + y2, 0));
+                    // 设置 前三年流失人数(系统数)
+                    sanDingTaskEntryDyo.set(SanDingConstant.NCKD_Y3OUT_SYS_KEY, y3OutSysMap.getOrDefault(positionBoId + "@" + y3, 0) + kgsddEmpPosOrgRelMap.getOrDefault(positionBoId + "@" + y3, 0));
+                    // 设置 前一年流失人数(确认数)
+                    sanDingTaskEntryDyo.set(SanDingConstant.NCKD_Y1OUT_CONF_KEY, sanDingTaskEntryDyo.get(SanDingConstant.NCKD_Y1OUT_SYS_KEY));
+                    // 设置 前两年流失人数(确认数)
+                    sanDingTaskEntryDyo.set(SanDingConstant.NCKD_Y2OUT_CONF_KEY, sanDingTaskEntryDyo.get(SanDingConstant.NCKD_Y2OUT_SYS_KEY));
+                    // 设置 前三年流失人数(确认数)
+                    sanDingTaskEntryDyo.set(SanDingConstant.NCKD_Y3OUT_CONF_KEY, sanDingTaskEntryDyo.get(SanDingConstant.NCKD_Y3OUT_SYS_KEY));
+                }
             }
             sanDingTaskDyoList.add(sanDingTaskDyo);
             SANDING_TASK_MAP.put(entryDyo.getLong(SanDingConstant.ID_KEY), sanDingTaskDyo.getLong(SanDingConstant.ID_KEY));
@@ -399,7 +433,7 @@ public class SendTaskOpPlugin extends AbstractOperationServicePlugIn {
         SaveServiceHelper.save(dyos);
     }
 
-    private void sendMessage(DynamicObject entryDyo) {
+    private void buildMessage(List<MessageInfo> messageInfos, DynamicObject entryDyo) {
         // 构建 消息
         MessageInfo messageInfo = new MessageInfo();
         // 设置 消息标题
@@ -410,6 +444,7 @@ public class SendTaskOpPlugin extends AbstractOperationServicePlugIn {
         messageInfo.setType(MessageInfo.TYPE_MESSAGE);
         // 设置 实体编码
         messageInfo.setEntityNumber(SanDingConstant.NCKD_SANDINGTASK_ENTITY);
+        // 设置 业务单据ID
         messageInfo.setBizDataId(SANDING_TASK_MAP.get(entryDyo.getLong(SanDingConstant.ID_KEY)));
         // 设置 标签
         messageInfo.setTag("三定管理");
@@ -419,7 +454,9 @@ public class SendTaskOpPlugin extends AbstractOperationServicePlugIn {
         messageInfo.setUserIds(userIds);
         // 设置 消息Web端url
         messageInfo.setContentUrl(UrlService.getDomainContextUrl() + "/index.html?formId="+SanDingConstant.NCKD_SANDINGTASK_ENTITY+"&pkId=" + SANDING_TASK_MAP.get(entryDyo.getLong(SanDingConstant.ID_KEY)));
-        MessageUtils.sendMessage(messageInfo);
+        // 设置发送人
+        messageInfo.setSenderId(UserServiceHelper.getCurrentUserId());
+        messageInfos.add(messageInfo);
     }
 
     private List<Long> getUserIds(List<Long> managerBoIdList) {

+ 4 - 4
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/haos/plugin/operate/adminorg/AdminOrgDetailConfirmChangeOpPlugin.java

@@ -53,8 +53,8 @@ public class AdminOrgDetailConfirmChangeOpPlugin extends AbstractOperationServic
             return;
         }
 
-        String changtype = data.getDynamicObject(AdminOrgConstant.CHANGETYPE).getString(AdminOrgConstant.NUMBER_KEY);
-        if (CHANGETYPE_PARENT.equals(changtype)) {
+        String changeType = data.getDynamicObject(AdminOrgConstant.CHANGETYPE).getString(AdminOrgConstant.NUMBER_KEY);
+        if (CHANGETYPE_PARENT.equals(changeType)) {
             beginOpParentHandler(dataEntities);
         }
     }
@@ -83,8 +83,8 @@ public class AdminOrgDetailConfirmChangeOpPlugin extends AbstractOperationServic
             return;
         }
 
-        String changtype = data.getDynamicObject(AdminOrgConstant.CHANGETYPE).getString(AdminOrgConstant.NUMBER_KEY);
-        switch (changtype) {
+        String changeType = data.getDynamicObject(AdminOrgConstant.CHANGETYPE).getString(AdminOrgConstant.NUMBER_KEY);
+        switch (changeType) {
             case CHANGETYPE_PARENT:
                 endOpParentHandler();
                 break;

+ 0 - 119
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/business/hr/PositionBillClosedCallBackService.java

@@ -1,119 +0,0 @@
-package nckd.jxccl.hrmp.hbpm.business.hr;
-
-import com.google.common.collect.Lists;
-import kd.bos.dataentity.entity.DynamicObject;
-import kd.bos.dataentity.metadata.IDataEntityProperty;
-import kd.bos.dataentity.metadata.IMetadata;
-import kd.bos.dataentity.metadata.clr.DataEntityPropertyCollection;
-import kd.bos.entity.EntityMetadataCache;
-import kd.bos.entity.MainEntityType;
-import kd.bos.entity.datamodel.AbstractFormDataModel;
-import kd.bos.entity.datamodel.TableValueSetter;
-import kd.bos.form.IFormView;
-import kd.bos.form.events.ClosedCallBackEvent;
-import kd.bos.orm.query.QCP;
-import kd.bos.orm.query.QFilter;
-import kd.hr.hbp.business.servicehelper.HRBaseServiceHelper;
-import nckd.jxccl.hrmp.hbpm.common.hr.PositionBillConstant;
-import nckd.jxccl.hrmp.hbpm.common.hr.PositionChangeTypeEnum;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.function.Function;
-import java.util.stream.Collectors;
-
-/**
- * 岗位申请单关闭回调服务类
- * @author: jtd
- * @date: 2025/12/20 17:29
- */
-public class PositionBillClosedCallBackService extends PositionBillBaseService {
-
-    public PositionBillClosedCallBackService(IFormView view) {
-        super(view);
-    }
-
-    public void closedCallBack(ClosedCallBackEvent closedCallBackEvent) {
-        switch (closedCallBackEvent.getActionId()) {
-            case PositionBillConstant.ADD_TAG:
-            case PositionBillConstant.CHANGE_TAG:
-                if (onlyForView(closedCallBackEvent)) {
-                    return;
-                }
-                updateEntryEntity(closedCallBackEvent.getActionId());
-        }
-    }
-
-    private boolean onlyForView(ClosedCallBackEvent closedCallBackEvent) {
-        return closedCallBackEvent.getReturnData() == null;
-    }
-
-    private void updateEntryEntity(String tag) {
-        DataEntityPropertyCollection entryEntityInfo = getModel().getDataEntity(true).getDynamicObjectCollection(PositionBillConstant.NCKD_ENTRYENTITY_ADD_KEY).getDynamicObjectType().getProperties();
-        MainEntityType entityType = EntityMetadataCache.getDataEntityType(PositionBillConstant.NCKD_POSBILLENTRYADD_ENTITY);
-        DataEntityPropertyCollection addEntityInfo = entityType.getProperties();
-        Map<String, IDataEntityProperty> addNamePropMap = addEntityInfo.stream().collect(Collectors.toMap(IMetadata::getName, Function.identity()));
-        List<String> selectPropList = new ArrayList<String>();
-        Set<String> toSetValueEntryPropList = new HashSet<String>();
-
-        String suffix = "_"+tag;
-        for(IDataEntityProperty iDataEntityProperty : entryEntityInfo) {
-            String entryPropName = iDataEntityProperty.getName();
-            if (entryPropName.endsWith(suffix)) {
-                String entryPropNameSub = entryPropName.replace(suffix, "");
-                if (addNamePropMap.containsKey(entryPropNameSub)) {
-                    selectPropList.add(entryPropNameSub);
-                    toSetValueEntryPropList.add(entryPropName);
-                }
-            }
-        }
-
-        // 获取需要转换的键值
-        Map<String, String> transKeyMap = PositionBillServiceHelper.getPosBillEntryReverseTransKeyMap();
-        transKeyMap.forEach((key, value) -> {
-            selectPropList.add(value);
-            toSetValueEntryPropList.add(key);
-        });
-        toSetValueEntryPropList.add(PositionBillConstant.ID_KEY);
-
-        HRBaseServiceHelper posBillEntryAddServiceHelper = new HRBaseServiceHelper(PositionBillConstant.NCKD_POSBILLENTRYADD_ENTITY);
-        Long billId = getModel().getDataEntity().getLong(PositionBillConstant.ID_KEY);
-        QFilter qFilter = (new QFilter(PositionBillConstant.NCKD_BILLID, QCP.equals, billId)).and(new QFilter(String.join(".", PositionBillConstant.NCKD_CHANGETYPE, PositionBillConstant.NUMBER_KEY), QCP.equals, PositionChangeTypeEnum.ADD.getNumber()));
-        DynamicObject[] addPositionDyArr = posBillEntryAddServiceHelper.load(String.join(",", selectPropList), qFilter.toArray(), PositionBillConstant.NCKD_SEQUENCE);
-
-        getModel().deleteEntryData(PositionBillConstant.NCKD_ENTRYENTITY_ADD_KEY);
-        TableValueSetter vs = new TableValueSetter();
-        toSetValueEntryPropList.forEach((prop) -> vs.addField(prop, new Object[0]));
-
-        for(DynamicObject addPositionDy : addPositionDyArr) {
-            List<Object> values = Lists.newArrayListWithCapacity(addPositionDyArr.length);
-
-            for(String entryPropName : toSetValueEntryPropList) {
-                if (entryPropName.equals(PositionBillConstant.ID_KEY)) {
-                    values.add(addPositionDy.getLong(PositionBillConstant.ID_KEY));
-                } else if (transKeyMap.containsKey(entryPropName)) {
-                    values.add(addPositionDy.get(transKeyMap.get(entryPropName)));
-                } else {
-                    String propName = entryPropName.replace(suffix, "");
-                    if (addPositionDy.get(propName) instanceof DynamicObject) {
-                        values.add(((DynamicObject) addPositionDy.get(propName)).getLong(PositionBillConstant.ID_KEY));
-                    } else {
-                        values.add(addPositionDy.get(propName));
-                    }
-                }
-            }
-
-            vs.addRow(values.toArray());
-        }
-
-        AbstractFormDataModel model = (AbstractFormDataModel) getModel();
-        model.beginInit();
-        model.batchCreateNewEntryRow(PositionBillConstant.NCKD_ENTRYENTITY_ADD_KEY, vs);
-        model.endInit();
-        getView().updateView(PositionBillConstant.NCKD_ENTRYENTITY_ADD_KEY);
-    }
-
-}

+ 0 - 347
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/business/hr/PositionBillServiceHelper.java

@@ -1,347 +0,0 @@
-package nckd.jxccl.hrmp.hbpm.business.hr;
-
-import com.google.common.collect.Maps;
-import com.kingdee.util.StringUtils;
-import kd.bos.bill.BillShowParameter;
-import kd.bos.bill.OperationStatus;
-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.serialization.SerializationUtils;
-import kd.bos.entity.constant.StatusEnum;
-import kd.bos.entity.datamodel.IDataModel;
-import kd.bos.entity.operate.OperateOptionConst;
-import kd.bos.entity.operate.result.OperationResult;
-import kd.bos.form.CloseCallBack;
-import kd.bos.form.IFormView;
-import kd.bos.form.ShowType;
-import kd.bos.form.control.EntryGrid;
-import kd.bos.list.ListShowParameter;
-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.servicehelper.MetadataServiceHelper;
-import kd.bos.servicehelper.operation.OperationServiceHelper;
-import kd.hr.hbp.business.servicehelper.HRBaseServiceHelper;
-import kd.hr.hbp.business.servicehelper.HRMServiceHelper;
-import kd.hr.hbp.common.constants.history.HisModelDataStatusEnum;
-import kd.hr.hbp.common.model.AuthorizedOrgResult;
-import kd.hr.hbp.common.util.HRDateTimeUtils;
-import kd.hr.hbp.common.util.HRDynamicObjectUtils;
-import kd.hr.hbp.common.util.HRObjectUtils;
-import kd.hr.hbp.common.util.HRStringUtils;
-import kd.sdk.hr.hdm.common.enums.reg.RegBillStatusEnum;
-import nckd.jxccl.base.common.utils.QueryFieldBuilder;
-import nckd.jxccl.hrmp.hbpm.common.hr.PositionBillConstant;
-import nckd.jxccl.hrmp.hbpm.common.hr.PositionChangeTypeEnum;
-
-import java.util.Arrays;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
-
-/**
- * 岗位申请单帮组类
- * @author: jtd
- * @date: 2025-10-31 14:33
- */
-public class PositionBillServiceHelper {
-
-    private static final Log log = LogFactory.getLog(PositionBillServiceHelper.class);
-
-    /**
-     * 获取分录序号
-     * @param iDataModel
-     * @param changeTypeNumber
-     * @return
-     */
-    public static int getEntrySeq(IDataModel iDataModel, String changeTypeNumber) {
-        Long billId = iDataModel.getDataEntity().getLong(PositionBillConstant.ID_KEY);
-        HRBaseServiceHelper positionBillEntryServiceHelper = new HRBaseServiceHelper(PositionBillConstant.NCKD_POSITIONBILLENTRY_ENTITY);
-        QFilter qFilter = new QFilter(PositionBillConstant.NCKD_BILLID, QCP.equals, billId);
-        qFilter.and(String.join(".", PositionBillConstant.NCKD_CHANGETYPE, PositionBillConstant.NUMBER_KEY), QCP.equals, changeTypeNumber);
-        String selectProps = String.join(",", PositionBillConstant.ID_KEY, PositionBillConstant.NCKD_SEQUENCE);
-        String order = String.format("%s desc", PositionBillConstant.NCKD_SEQUENCE);
-        DynamicObject dynamicObject = positionBillEntryServiceHelper.queryOne(selectProps, qFilter.toArray(), order);
-        return dynamicObject == null ? 1 : dynamicObject.getInt(PositionBillConstant.NCKD_SEQUENCE) + 1;
-    }
-
-    /**
-     * 打开表单界面
-     * @param iFormView
-     * @param operation
-     * @param pluginName
-     */
-    public static void openViewForm(IFormView iFormView, String operation, String pluginName, QFilter filter) {
-        if (iFormView.getModel().getValue(PositionBillConstant.ORG_KEY) == null) {
-            iFormView.showTipNotification("请先填写组织体系管理组织。");
-        } else {
-            HRBaseServiceHelper positionBillHelper = new HRBaseServiceHelper(PositionBillConstant.NCKD_POSITIONBILL_ENTITY);
-            QFilter idFilter = new QFilter(PositionBillConstant.ID_KEY, "=", iFormView.getModel().getDataEntity().getLong(PositionBillConstant.ID_KEY));
-            DynamicObject dynamicObject = positionBillHelper.loadDynamicObject(idFilter);
-            if (dynamicObject != null) {
-                String billStatus = dynamicObject.getString(PositionBillConstant.BILL_STATUS_KEY);
-                if (!billStatus.equals(RegBillStatusEnum.TEMPSTORAGE.getCode()) && !billStatus.equals(RegBillStatusEnum.WAITRESUBMIT.getCode()) && !billStatus.equals(RegBillStatusEnum.APPROVING.getCode()) && (!billStatus.equals(RegBillStatusEnum.ALREADYSUBMIT.getCode()) || !StringUtils.equals(iFormView.getFormShowParameter().getAppId(), PositionBillConstant.WFTASK_APP))) {
-                    String operateLocaleName = PositionChangeTypeEnum.getTipByTag(operation);
-                    String auditstatusName = RegBillStatusEnum.getName(dynamicObject.getString(PositionBillConstant.BILL_STATUS_KEY));
-                    iFormView.showErrorNotification(String.format("“%1$s”的单据不能“%2$s”。", auditstatusName, operateLocaleName));
-                    return;
-                }
-            }
-
-            ListShowParameter listShowParameter = new ListShowParameter();
-            if (filter != null) {// 200
-                listShowParameter.getListFilterParameter().getQFilters().add(filter);
-            }
-
-            switch (operation) {
-                case PositionBillConstant.ADD_TAG:
-                    BillShowParameter formShowParameter = new BillShowParameter();
-                    formShowParameter.setCustomParam("position_bsed", iFormView.getModel().getValue(PositionBillConstant.NCKD_EFFDT) == null ? HRDateTimeUtils.getNowDateTime().getTime() : ((Date)iFormView.getModel().getValue(PositionBillConstant.NCKD_EFFDT)).getTime());
-                    formShowParameter.setFormId(PositionBillConstant.NCKD_POSBILLENTRYADD_ENTITY);
-                    formShowParameter.getOpenStyle().setShowType(ShowType.Modal);
-                    formShowParameter.setCustomParam("billid", iFormView.getModel().getDataEntity().getLong(PositionBillConstant.ID_KEY));
-                    formShowParameter.setCustomParam("billBsed", iFormView.getModel().getDataEntity().getDate(PositionBillConstant.NCKD_EFFDT));
-                    formShowParameter.setCloseCallBack(new CloseCallBack(pluginName, operation));
-                    if (HRStringUtils.equals(EnableEnum.NO.getCode(), iFormView.getPageCache().get("isList"))) {
-                        formShowParameter.setCustomParam("parentId", iFormView.getPageCache().get("parentId"));
-                    }
-
-                    if (HRStringUtils.equals(iFormView.getFormShowParameter().getAppId(), PositionBillConstant.WFTASK_APP)) {
-                        formShowParameter.setHasRight(true);
-                    }
-                    formShowParameter.setCustomParam("org", iFormView.getModel().getDataEntity().getLong(String.join(".", PositionBillConstant.ORG_KEY, PositionBillConstant.ID_KEY)));
-                    int sequence = getEntrySeq(iFormView.getModel(), PositionChangeTypeEnum.ADD.getNumber());
-                    formShowParameter.setCustomParam("sequence", sequence);
-                    //formShowParameter.setCustomParam("OP_VALIDATOR_BILL_ORG_ALL_CHANGE_ORG_KEY", getThisBillAllValidateDataStr(dynamicObject));
-                    //formShowParameter.setCustomParam("OP_VALIDATOR_BILL_ORG_NEW_ORG_NUMBERS_KEY", getThisBillOrgNumbersStr(dynamicObject));
-                    iFormView.showForm(formShowParameter);
-                default:
-            }
-        }
-    }
-
-    public static AuthorizedOrgResult getOrgAuth(IFormView iFormView) {
-        Long userId = RequestContext.get().getCurrUserId();
-        String permItemId = "47150e89000000ac";
-        String appId = iFormView.getFormShowParameter().getCheckRightAppId();
-        AuthorizedOrgResult permResult = HRMServiceHelper.invokeHRMPService("hrcs", "IHRCSBizDataPermissionService", "getUserAdminOrgsF7", new Object[]{userId, appId, PositionBillConstant.NCKD_POSITIONBILL_ENTITY, permItemId, "adminorgboid", Maps.newHashMapWithExpectedSize(0)});
-        return permResult;
-    }
-
-    /**
-     * 删除岗位新设暂存数据
-     * @param positionIdList
-     */
-    public static void delAddMaster(List<Long> positionIdList) {
-//        HisDeleteParam hisDeleteParam = new HisDeleteParam();
-//        hisDeleteParam.setEntityNumber(PositionBillConstant.HBPM_POSITIONHR);
-//        hisDeleteParam.setDataList(Arrays.asList(HRBaseServiceHelper.create(PositionBillConstant.HBPM_POSITIONHR).loadDynamicObjectArray(positionIdList.toArray())));
-//        HisModelServiceHelper.deleteBo(hisDeleteParam);
-        HRBaseServiceHelper positionHrHelper = new HRBaseServiceHelper(PositionBillConstant.HBPM_POSITIONHR);
-        positionHrHelper.deleteByFilter(new QFilter[]{new QFilter(PositionBillConstant.BOID_KEY, QCP.in, positionIdList)});
-    }
-
-    public static DynamicObject getFocusEntry(String suffix, IFormView view, int row) {
-        EntryGrid entryGrid = view.getControl(String.join("_", PositionBillConstant.NCKD_ENTRYENTITY, suffix));
-        if (row == -1) {
-            row = entryGrid.getEntryState().getFocusRow();
-        }
-
-        DynamicObject entryEntityDyn = view.getModel().getDataEntity(true).getDynamicObjectCollection(String.join("_", PositionBillConstant.NCKD_ENTRYENTITY, suffix)).get(row);
-        long entityId = entryEntityDyn.getLong(PositionBillConstant.ID_KEY);
-        if (entityId != 0L) {
-            HRBaseServiceHelper serviceHelper = new HRBaseServiceHelper(PositionBillConstant.NCKD_POSITIONBILLENTRY_ENTITY);
-            serviceHelper.deleteOne(entityId);
-            entryEntityDyn.set(PositionBillConstant.ID_KEY, 0L);
-        }
-
-        return entryEntityDyn;
-    }
-
-    /**
-     * 获取岗位转换键值
-     * @return 目标字段: 源字段
-     */
-    public static Map<String, String> getPositionTransKeyMap() {
-        String selectFields = QueryFieldBuilder.create().add(PositionBillConstant.NUMBER_KEY).add(PositionBillConstant.NAME_KEY).buildSelect();
-        DynamicObject[] transKeyDyos = HRBaseServiceHelper.create(PositionBillConstant.NCKD_POSITION_TRANSKEY_ENTITY).queryOriginalArray(selectFields, null);
-        Map<String, String> transKeyMap = Arrays.stream(transKeyDyos).collect(Collectors.toMap(
-                transKeyDyo -> transKeyDyo.getString(PositionBillConstant.NAME_KEY),
-                transKeyDyo -> transKeyDyo.getString(PositionBillConstant.NUMBER_KEY),
-                (oldValue, newValue) -> newValue)
-        );
-        return transKeyMap;
-    }
-
-    /**
-     * 获取岗位申请分录转换键值
-     * @return 单据分录字段: 分录页面字段
-     */
-    public static Map<String, String> getPosBillEntryTransKeyMap() {
-        return getPosBillEntryTransKeyMap(false);
-    }
-
-    /**
-     * 获取岗位申请分录转换键值(倒转)
-     * @return 分录页面字段: 单据分录字段
-     */
-    public static Map<String, String> getPosBillEntryReverseTransKeyMap() {
-        return getPosBillEntryTransKeyMap(true);
-    }
-
-    /**
-     * 获取岗位申请分录转换键值
-     * @return
-     */
-    private static Map<String, String> getPosBillEntryTransKeyMap(Boolean isReverse) {
-        String selectFields = QueryFieldBuilder.create().add(PositionBillConstant.NUMBER_KEY).add(PositionBillConstant.NAME_KEY).buildSelect();
-        DynamicObject[] transKeyDyos = HRBaseServiceHelper.create(PositionBillConstant.NCKD_PBENTRY_TRANSKEY_ENTITY).queryOriginalArray(selectFields, null);
-        Map<String, String> transKeyMap = Arrays.stream(transKeyDyos).collect(Collectors.toMap(
-                transKeyDyo -> isReverse ? transKeyDyo.getString(PositionBillConstant.NUMBER_KEY) : transKeyDyo.getString(PositionBillConstant.NAME_KEY),
-                transKeyDyo -> isReverse ? transKeyDyo.getString(PositionBillConstant.NAME_KEY) : transKeyDyo.getString(PositionBillConstant.NUMBER_KEY),
-                (oldValue, newValue) -> newValue)
-        );
-        return transKeyMap;
-    }
-
-    public static List<String> getPositionExcludeKeyList() {
-        DynamicObject[] positionExcludeKeyList = HRBaseServiceHelper.create(PositionBillConstant.NCKD_POSITION_EXCLUDEKEY_ENTITY).queryOriginalArray(PositionBillConstant.NUMBER_KEY, null);
-        List<String> excludeKeyList = Arrays.stream(positionExcludeKeyList).map(positionExcludeKeyDyo -> positionExcludeKeyDyo.getString(PositionBillConstant.NUMBER_KEY)).collect(Collectors.toList());
-        return excludeKeyList;
-    }
-
-    /**
-     * 构建岗位
-     * 用于校验岗位数据或获取/回收岗位编码
-     * @param addDy
-     * @return
-     */
-    public static DynamicObject getPositionHrDy(DynamicObject addDy) {
-        return getPositionHrDy(addDy, getPositionTransKeyMap());
-    }
-
-    /**
-     * 构建岗位
-     * 用于校验岗位数据或获取/回收岗位编码
-     * @param addDy
-     * @param transKeyMap
-     * @return
-     */
-    public static DynamicObject getPositionHrDy(DynamicObject addDy, Map<String, String> transKeyMap) {
-        DynamicObject positionHrDy = new DynamicObject(MetadataServiceHelper.getDataEntityType(PositionBillConstant.HBPM_POSITIONHR));
-        getPositionHrDy(addDy, positionHrDy, transKeyMap);
-        // 设置 是否标准岗位
-        positionHrDy.set(PositionBillConstant.ISSTANDARDPOS_KEY, EnableEnum.NO.getCode());
-        // 设置 业务状态
-        positionHrDy.set(PositionBillConstant.ENABLE, EnableEnum.YES.getCode());
-        // 设置 数据状态
-        positionHrDy.set(PositionBillConstant.STATUS, StatusEnum.C);
-        // 设置 数据版本状态
-        positionHrDy.set(PositionBillConstant.DATA_STATUS, HisModelDataStatusEnum.EFFECTING);
-        // 设置 行政组织
-        DynamicObject adminOrgVersionDy = addDy.getDynamicObject(PositionBillConstant.NCKD_ADMINORG);
-        if (HRObjectUtils.isEmpty(adminOrgVersionDy)) {
-            positionHrDy.set(PositionBillConstant.ADMINORG, null);
-        } else {
-            positionHrDy.set(PositionBillConstant.ADMINORG, HRBaseServiceHelper.create(PositionBillConstant.ADMINORG_ENTITYID).loadSingle(adminOrgVersionDy.getLong(PositionBillConstant.BOID_KEY)));
-        }
-        // 设置 上级岗位
-        DynamicObject parentPositionVersionDy = addDy.getDynamicObject(PositionBillConstant.NCKD_PARENT);
-        if (HRObjectUtils.isEmpty(parentPositionVersionDy)) {
-            positionHrDy.set(PositionBillConstant.PARENT_KEY, null);
-        } else {
-            positionHrDy.set(PositionBillConstant.PARENT_KEY, HRBaseServiceHelper.create(PositionBillConstant.HBPM_POSITIONHR).loadSingle(parentPositionVersionDy.getLong(PositionBillConstant.BOID_KEY)));
-        }
-        return positionHrDy;
-    }
-
-    /**
-     * 构建岗位
-     * @param addDy
-     * @param positionDyo
-     * @param transKeyMap
-     * @return
-     */
-    public static DynamicObject getPositionHrDy(DynamicObject addDy, DynamicObject positionDyo, Map<String, String> transKeyMap) {
-        // 将表单中的信息赋值到岗位信息中
-        HRDynamicObjectUtils.copy(addDy, positionDyo, transKeyMap);
-        // 设置ID
-        positionDyo.set(PositionBillConstant.ID_KEY, addDy.getLong(PositionBillConstant.ID_KEY));
-        // 设置 业务状态
-        //positionDyo.set(PositionBillConstant.ENABLE, EnableEnum.YES.getCode());
-        // 设置 数据状态
-        //positionDyo.set(PositionBillConstant.STATUS, StatusEnum.A);
-        // 设置 数据版本状态
-        //positionDyo.set(PositionBillConstant.DATA_STATUS, " ");
-        return positionDyo;
-    }
-
-    public static void entryEntityMore(IDataModel iDataModel, IFormView iFormView, String tag, OperationStatus status) {
-        EntryGrid entryEntity = iFormView.getControl(String.join("_", PositionBillConstant.NCKD_ENTRYENTITY, tag));
-        int row = entryEntity.getEntryState().getFocusRow();
-        DynamicObject dynamicObject = iDataModel.getDataEntity(true).getDynamicObjectCollection(String.join("_", PositionBillConstant.NCKD_ENTRYENTITY, tag)).get(row);
-        Map map = HRDynamicObjectUtils.convertDynamicObjectToMap(dynamicObject);
-        long id = dynamicObject.getLong(PositionBillConstant.ID_KEY);
-        BillShowParameter formShowParameter = new BillShowParameter();
-        Object dy = dynamicObject.get(String.join("_", PositionBillConstant.NCKD_POSITION, tag));
-        if (dy == null) {// 1977
-            iFormView.showTipNotification("请先选择岗位。");
-        } else {
-            if (PositionBillConstant.CHANGE_TAG.equals(tag)) {
-                formShowParameter.setFormId(PositionBillConstant.NCKD_POSBILLENTRYCHANGE_ENTITY);
-            }
-
-            // 获取岗位申请单分录服务
-            HRBaseServiceHelper helper = new HRBaseServiceHelper(PositionBillConstant.NCKD_POSITIONBILLENTRY_ENTITY);
-            boolean exists = helper.isExists(id);
-            if (exists) {
-                formShowParameter.setPkId(id);
-            } else {
-                formShowParameter.setCustomParam("id", id);
-            }
-
-            if (HRStringUtils.equals(iFormView.getFormShowParameter().getAppId(), PositionBillConstant.WFTASK_APP)) {
-                formShowParameter.setHasRight(true);
-            }
-
-            formShowParameter.setStatus(status);
-            formShowParameter.setCustomParam("id", id);
-            formShowParameter.getOpenStyle().setShowType(ShowType.Modal);
-            formShowParameter.setCustomParam("selectObject", SerializationUtils.toJsonString(map));
-            formShowParameter.setCustomParam("billid", iDataModel.getValue(PositionBillConstant.ID_KEY));
-            formShowParameter.setCustomParam("positionid", String.valueOf(dynamicObject.getLong(String.join("_", PositionBillConstant.NCKD_POSITION, tag))));
-            formShowParameter.setCustomParam("iscard", "isCardFalse");
-            formShowParameter.setCustomParam("position_bsed", iDataModel.getValue(PositionBillConstant.NCKD_EFFDT) == null ? HRDateTimeUtils.getNowDateTime().getTime() : ((Date) iDataModel.getValue(PositionBillConstant.NCKD_EFFDT)).getTime());
-            formShowParameter.setCustomParam("org", iDataModel.getDataEntity().getLong(String.join(".", PositionBillConstant.ORG_KEY, PositionBillConstant.ID_KEY)));
-            formShowParameter.setCustomParam("billstatus", iDataModel.getDataEntity().get(PositionBillConstant.BILL_STATUS_KEY));
-            int sequence = getEntrySeq(iFormView.getModel(), PositionChangeTypeEnum.getNumberByTag(tag));
-            formShowParameter.setCustomParam("sequence", sequence);
-            formShowParameter.setCloseCallBack(new CloseCallBack("nckd.jxccl.hrmp.hbpm.plugin.form.hr.PositionBillFormPlugin", tag));
-            //formShowParameter.setCustomParam("OP_VALIDATOR_BILL_ORG_ALL_CHANGE_ORG_KEY", getThisBillAllValidateDataStr(iDataModel.getDataEntity(true)));
-            //formShowParameter.setCustomParam("OP_VALIDATOR_BILL_ORG_NEW_ORG_NUMBERS_KEY", getThisBillOrgNumbersStr(iDataModel.getDataEntity(true)));
-            iFormView.showForm(formShowParameter);
-        }
-    }
-
-    public static OperationResult executeOperateOnlyValidate(String operationKey, DynamicObject[] positionDys, OperateOption option) {
-        OperateOption operateOption = option;
-        if (option == null) {
-            operateOption = OperateOption.create();
-        }
-
-        operateOption.setVariableValue(OperateOptionConst.ISHASRIGHT, Boolean.TRUE.toString());
-        operateOption.setVariableValue(OperateOptionConst.ONLY_VALIDATE, Boolean.TRUE.toString());
-
-        try {
-            return OperationServiceHelper.executeOperate(operationKey, PositionBillConstant.HBPM_POSITIONHR, positionDys, operateOption);
-        } catch (Exception ex) {
-            log.error("executeOperate  error", ex);
-            throw ex;
-        }
-    }
-
-}

+ 135 - 0
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/business/hr/service/impl/PosBillEntryFastChgHelper.java

@@ -0,0 +1,135 @@
+package nckd.jxccl.hrmp.hbpm.business.hr.service.impl;
+
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.dataentity.metadata.IDataEntityProperty;
+import kd.bos.dataentity.metadata.IDataEntityType;
+import kd.bos.dataentity.utils.StringUtils;
+import kd.bos.db.DB;
+import kd.bos.db.DBRoute;
+import kd.bos.entity.EntityMetadataCache;
+import kd.bos.entity.MainEntityType;
+import kd.bos.entity.datamodel.IDataModel;
+import kd.bos.entity.datamodel.events.ChangeData;
+import kd.bos.entity.datamodel.events.PropertyChangedArgs;
+import kd.bos.entity.property.BasedataProp;
+import kd.bos.form.ConfirmCallBackListener;
+import kd.bos.form.IFormView;
+import kd.bos.form.MessageBoxOptions;
+import kd.bos.form.plugin.IFormPlugin;
+import kd.bos.orm.util.CollectionUtils;
+import kd.bos.servicehelper.basedata.BaseDataServiceHelper;
+import kd.hr.hbp.business.servicehelper.HRBaseServiceHelper;
+import nckd.jxccl.hrmp.hbpm.common.hr.PositionBillConstant;
+
+import java.sql.ResultSet;
+
+/**
+ * 岗位申请分录快速变更帮助类
+ * @from: kd.hr.homs.business.domain.orgfast.repository.AdminOrgFastChgHelper
+ * @author: jtd
+ * @date: 2025/12/27 17:19
+ */
+public class PosBillEntryFastChgHelper {
+
+    public static void orgPropertyChanged(PropertyChangedArgs changedArgs, IFormView iFormView, IFormPlugin formPlugin) {
+        ChangeData changeData = changedArgs.getChangeSet()[0];
+        DynamicObject newDy = (DynamicObject) changeData.getNewValue();
+        DynamicObject oldDy = (DynamicObject) changeData.getOldValue();
+        String masterOrg = iFormView.getPageCache().get(PositionBillConstant.PC_MASTERORG);
+        if (changedArgs.getChangeSet()[0].getNewValue() != null) {
+            HRBaseServiceHelper hrBaseServiceHelper = new HRBaseServiceHelper(PositionBillConstant.NCKD_POSITIONBILL_ENTITY);
+            boolean exists = hrBaseServiceHelper.isExists(iFormView.getModel().getDataEntity().getLong(PositionBillConstant.ID_KEY));
+            if (!exists) {
+                Long orgIdNew = newDy.getLong(PositionBillConstant.ID_KEY);
+                if (StringUtils.isNotEmpty(masterOrg) && !StringUtils.equals(masterOrg, String.valueOf(orgIdNew))) {
+                    Long orgIDOld = oldDy == null ? 0L : oldDy.getLong(PositionBillConstant.ID_KEY);
+                    iFormView.getPageCache().put(PositionBillConstant.PC_MASTERORG, String.valueOf(orgIDOld));
+                    ConfirmCallBackListener confirmCallBackListener = new ConfirmCallBackListener(PositionBillConstant.CB_CHG_ORG, formPlugin);
+                    iFormView.showConfirm("切换组织体系管理组织后,将清除该组织不可使用的基础资料信息,是否切换?", MessageBoxOptions.OKCancel, confirmCallBackListener);
+                }
+
+            }
+        }
+    }
+
+    public static void cleanOrgBaseInfo(long orgId, IFormView iFormView) {
+        MainEntityType entityType = EntityMetadataCache.getDataEntityType(iFormView.getEntityId());
+        IDataModel model = iFormView.getModel();
+
+        for(IDataEntityProperty property : entityType.getAllFields().values()) {
+            if (property instanceof BasedataProp) {
+                IDataEntityType parent = property.getParent();
+                if (parent != null) {
+                    if (!parent.getName().equals(iFormView.getEntityId())) {
+                        if (model.getDataEntity().containsProperty(property.getParent().getName())) {
+                            DynamicObjectCollection dynamicObjectCollection = model.getDataEntity(true).getDynamicObjectCollection(property.getParent().getName());
+                            if (!CollectionUtils.isEmpty(dynamicObjectCollection)) {
+                                for(int i = 0; i < dynamicObjectCollection.size(); ++i) {
+                                    DynamicObject entrtyDy = dynamicObjectCollection.get(i);
+                                    DynamicObject baseDy = entrtyDy.getDynamicObject(property.getName());
+                                    if (baseDy != null && cleanBastInfo(baseDy, property, iFormView, orgId)) {
+                                        model.setValue(property.getName(), null, i);
+                                        iFormView.updateView(property.getName(), i);
+                                    }
+                                }
+                            }
+                        }
+                    } else if (model.getDataEntity().containsProperty(property.getName())) {
+                        DynamicObject baseDy = model.getDataEntity().getDynamicObject(property.getName());
+                        if (baseDy != null && cleanBastInfo(baseDy, property, iFormView, orgId)) {
+                            model.setValue(property.getName(), null);
+                            iFormView.updateView(property.getName());
+                        }
+                    }
+                }
+            }
+        }
+
+    }
+
+    public static void cleanOrgBaseInfoForBillEntry(IFormView iFormView, int row, String fieldKey, String entryId) {
+        IDataModel model = iFormView.getModel();
+        DynamicObjectCollection collection = model.getDataEntity(true).getDynamicObjectCollection(entryId);
+        if (collection != null && collection.size() != 0) {
+            for(IDataEntityProperty entityProperty : collection.getDynamicObjectType().getProperties()) {
+                if (!entityProperty.getName().equals(fieldKey) && entityProperty instanceof BasedataProp) {
+                    DynamicObject entrtyDy = collection.get(row);
+                    DynamicObject orgId = entrtyDy.getDynamicObject(fieldKey);
+                    DynamicObject baseDy = entrtyDy.getDynamicObject(entityProperty.getName());
+                    if (baseDy != null && cleanBastInfo(baseDy, entityProperty, iFormView, orgId.getLong(PositionBillConstant.ID_KEY))) {
+                        iFormView.getModel().beginInit();
+                        model.setValue(entityProperty.getName(), null, row);
+                        iFormView.updateView(entityProperty.getName(), row);
+                        iFormView.getModel().endInit();
+                    }
+                }
+            }
+
+        }
+    }
+
+    private static boolean cleanBastInfo(DynamicObject baseDy, IDataEntityProperty property, IFormView iFormView, long orgId) {
+        Boolean baseDataCtrl = BaseDataServiceHelper.checkBaseDataCtrl(((BasedataProp) property).getBaseEntityId());
+        if (baseDataCtrl) {
+            if (!checkAssign(iFormView, property, baseDy, orgId)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    private static boolean checkAssign(IFormView iFormView, IDataEntityProperty property, DynamicObject baseDy, long orgId) {
+        IDataEntityType dataEntityType = baseDy.getDataEntityType();
+        String baseDataTableName = dataEntityType.getAlias();
+        String dbRouteKey = dataEntityType.getDBRouteKey();
+        DBRoute dbRoute = DBRoute.of(dbRouteKey);
+        String bsaeDataUseRegTableName = baseDataTableName + "UseReg";
+        String countUseRegSql = "select FDataID from " + bsaeDataUseRegTableName + " where FDataID = ? and fuseorgid = ? ";
+        Object[] params = new Object[]{baseDy.get(PositionBillConstant.ID_KEY), orgId};
+        Boolean assign = DB.query(dbRoute, countUseRegSql, params, ResultSet::next);
+        return assign;
+    }
+
+}

+ 196 - 0
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/business/hr/service/impl/PositionBillAfterBindDataService.java

@@ -0,0 +1,196 @@
+package nckd.jxccl.hrmp.hbpm.business.hr.service.impl;
+
+import com.google.common.collect.Maps;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.dataentity.metadata.IDataEntityProperty;
+import kd.bos.dataentity.metadata.clr.DataEntityPropertyCollection;
+import kd.bos.dataentity.metadata.dynamicobject.DynamicObjectType;
+import kd.bos.entity.datamodel.AbstractFormDataModel;
+import kd.bos.entity.datamodel.TableValueSetter;
+import kd.bos.form.FieldTip;
+import kd.bos.form.IFormView;
+import kd.bos.form.IPageCache;
+import kd.bos.mvc.cache.PageCache;
+import kd.bos.orm.ORM;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
+import kd.bos.orm.util.CollectionUtils;
+import kd.hr.hbp.business.servicehelper.HRBaseServiceHelper;
+import kd.hr.hbp.common.util.HRArrayUtils;
+import kd.hr.hbp.common.util.HRStringUtils;
+import nckd.jxccl.hrmp.hbpm.common.hr.PatternUtil;;
+import nckd.jxccl.base.common.utils.QueryFieldBuilder;
+import nckd.jxccl.hrmp.hbpm.common.hr.PositionBillConstant;
+import nckd.jxccl.hrmp.hbpm.common.hr.PositionChangeTypeEnum;
+
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+/**
+ * 岗位申请单后置绑定数据服务
+ * @from: kd.hr.homs.business.domain.batchbill.service.impl.AdminOrgBatchBillAfterBindDataService
+ * @author: jtd
+ * @date: 2025/12/27 21:48
+ */
+public class PositionBillAfterBindDataService extends PositionBillBaseService {
+    public PositionBillAfterBindDataService(IFormView view) {
+        super(view);
+    }
+
+    public void afterBindData() {
+        genBillIdIfNotExist();
+        deleteAllEntryData();
+        updateAllChangeTypeEntry();
+        deleteAddEntryIfChangeOrg();
+        changeOrgFiledTip();
+        getModel().setDataChanged(false);
+    }
+
+    private void changeOrgFiledTip() {
+        FieldTip orgTip = new FieldTip();
+        orgTip.setFieldKey(PositionBillConstant.ORG_KEY);
+        orgTip.setSuccess(true);
+        getView().showFieldTip(orgTip);
+    }
+
+    private void deleteAddEntryIfChangeOrg() {
+        String orgCache = getView().getPageCache().get(PositionBillConstant.PC_ORGCACHE);
+        Object org = getModel().getValue(PositionBillConstant.ORG_KEY);
+        if (Objects.isNull(orgCache)) {
+            if (Objects.nonNull(org)) {
+                DynamicObject dy = (DynamicObject) org;
+                getView().getPageCache().put(PositionBillConstant.PC_ORGCACHE, dy.getLong(PositionBillConstant.ID_KEY) + "");
+            }
+        } else if (Objects.nonNull(org)) {
+            DynamicObject dy = (DynamicObject) org;
+            String newId = dy.getLong(PositionBillConstant.ID_KEY) + "";
+            if (!orgCache.equals(newId)) {
+                long billId = getModel().getDataEntity().getLong(PositionBillConstant.ID_KEY);
+                HRBaseServiceHelper positionBillEntryHelper = new HRBaseServiceHelper(PositionBillConstant.NCKD_POSITIONBILLENTRY_ENTITY);
+                QFilter billIdFilter = new QFilter(PositionBillConstant.NCKD_BILLID, QCP.equals, billId);
+                String selectProperties = QueryFieldBuilder.create().add(PositionBillConstant.ID_KEY)
+                        .add(PositionBillConstant.NUMBER_KEY)
+                        .add(PositionBillConstant.NCKD_CHANGETYPE, PositionBillConstant.NUMBER_KEY)
+                        .add(PositionBillConstant.NCKD_POSITION_KEY)
+                        .buildSelect();
+                DynamicObject[] positionBillEntryDynArr = positionBillEntryHelper.query(selectProperties, new QFilter[]{billIdFilter});
+                positionBillEntryHelper.deleteByFilter(new QFilter[]{billIdFilter});
+                List<Long> addPositionIdList = Arrays.stream(positionBillEntryDynArr).filter((dyn) -> HRStringUtils.equals(dyn.getString(String.join(".", PositionBillConstant.NCKD_CHANGETYPE, PositionBillConstant.NUMBER_KEY)), PositionChangeTypeEnum.ADD.getNumber())).map((dyn) -> dyn.getLong(String.join(".", PositionBillConstant.NCKD_POSITION_KEY, PositionBillConstant.ID_KEY))).collect(Collectors.toList());
+                getView().getPageCache().put(PositionBillConstant.PC_ORGCACHE, newId);
+                if (addPositionIdList.size() == 0) {
+                    return;
+                }
+
+                PositionBillServiceHelper.delAddMaster(addPositionIdList);
+            }
+        }
+
+    }
+
+    private void genBillIdIfNotExist() {
+        long billId = getModel().getDataEntity().getLong(PositionBillConstant.ID_KEY);
+        if (billId == 0L) {
+            billId = ORM.create().genLongId(getView().getEntityId());
+            getModel().setValue(PositionBillConstant.ID_KEY, billId);
+        }
+    }
+
+    private void deleteAllEntryData() {
+        IPageCache pageCache = new PageCache(getView().getPageId());
+        Object importPageClose = pageCache.get(PositionBillConstant.PC_CACHE_KEY_IMPORT_START_CLOSE);
+        Object entryImport = pageCache.get(PositionBillConstant.PC_CACHE_KEY_IMPORT_DATA_FLAG);
+        if (!Boolean.TRUE.toString().equals(importPageClose) || Boolean.TRUE.toString().equals(entryImport)) {
+            Arrays.stream(PositionChangeTypeEnum.values()).forEach((changeTypeEnum) -> getModel().deleteEntryData(changeTypeEnum.getTag(PositionBillConstant.NCKD_ENTRYENTITYUNDERLINE_KEY)));
+        }
+    }
+
+    private void updateAllChangeTypeEntry() {
+        IPageCache pageCache = new PageCache(getView().getPageId());
+        Object importPageClose = pageCache.get(PositionBillConstant.PC_CACHE_KEY_IMPORT_START_CLOSE);
+        Object entryImport = pageCache.get(PositionBillConstant.PC_CACHE_KEY_IMPORT_DATA_FLAG);
+        if (Boolean.TRUE.toString().equals(importPageClose) && !Boolean.TRUE.toString().equals(entryImport)) {
+            pageCache.remove(PositionBillConstant.PC_CACHE_KEY_IMPORT_START_CLOSE);
+            pageCache.remove(PositionBillConstant.PC_CACHE_KEY_IMPORT_DATA_FLAG);
+        } else {
+            Long billId = getModel().getDataEntity().getLong(PositionBillConstant.ID_KEY);
+            HRBaseServiceHelper positionBillEntryEntityHelper = new HRBaseServiceHelper(PositionBillConstant.NCKD_POSITIONBILLENTRY_ENTITY);
+            QFilter billIdFilter = new QFilter(PositionBillConstant.NCKD_BILLID, QCP.equals, billId);
+            DynamicObject[] batchOrgEntryEntityDynArr = positionBillEntryEntityHelper.loadDynamicObjectArray(new QFilter[]{billIdFilter});
+            Arrays.sort(batchOrgEntryEntityDynArr, Comparator.comparingLong((dyn) -> dyn.getLong(PositionBillConstant.NCKD_SEQUENCE)));
+            Map<String, List<DynamicObject>> changeTypeForBillDynMap = Maps.newHashMap();
+            if (!HRArrayUtils.isEmpty(batchOrgEntryEntityDynArr)) {
+                changeTypeForBillDynMap = Arrays.stream(batchOrgEntryEntityDynArr).collect(Collectors.groupingBy((dyn) -> dyn.getString(String.join(".", PositionBillConstant.NCKD_CHANGETYPE, PositionBillConstant.NUMBER_KEY))));
+            }
+
+            // 获取分录要转换的键值
+            Map<String, String> posBillEntryTransKeyMap = PositionBillServiceHelper.getPosBillEntryTransKeyMap();
+            for(Map.Entry<String, List<DynamicObject>> stringListEntry : changeTypeForBillDynMap.entrySet()) {
+                String changeTypeNumber = stringListEntry.getKey();
+                List<DynamicObject> entryEntityDynList = stringListEntry.getValue();
+                String suffix = PositionChangeTypeEnum.getTagByNumber(changeTypeNumber);
+                String entryEntity = String.join("_", PositionBillConstant.NCKD_ENTRYENTITY, suffix);
+                DynamicObjectCollection dynamicObjectCollection = getModel().getDataEntity(true).getDynamicObjectCollection(entryEntity);
+                DynamicObjectType dynamicObjectType = dynamicObjectCollection.getDynamicObjectType();
+                DataEntityPropertyCollection properties = dynamicObjectType.getProperties();
+                TableValueSetter tableValueSetter = new TableValueSetter();
+                setTableValueSetterField(suffix, tableValueSetter, properties);
+                setTableValueSetterValue(suffix, tableValueSetter, properties, entryEntityDynList, posBillEntryTransKeyMap);
+                batchCreateNewEntryRow(tableValueSetter, entryEntity);
+            }
+
+        }
+    }
+
+    private void setTableValueSetterField(String suffix, TableValueSetter tableValueSetter, DataEntityPropertyCollection properties) {
+        if (!HRStringUtils.isEmpty(suffix)) {
+            for(IDataEntityProperty property : properties) {
+                String propName = property.getName();
+                if (PatternUtil.isExProperty(propName) && propName.endsWith("_"+suffix)) {
+                    tableValueSetter.addField(propName);
+                }
+            }
+            tableValueSetter.addField(PositionBillConstant.ID_KEY);
+        }
+    }
+
+    private void setTableValueSetterValue(String suffix, TableValueSetter tableValueSetter, DataEntityPropertyCollection properties, List<DynamicObject> entryEntityDynList, Map<String, String> posBillEntryTransKeyMap) {
+        if (!HRStringUtils.isEmpty(suffix)) {
+            for(int i = 0; i < entryEntityDynList.size(); ++i) {
+                for(IDataEntityProperty property : properties) {
+                    String propName = property.getName();
+                    if (PatternUtil.isExProperty(propName) && propName.endsWith("_"+suffix)) {
+                        String propNameSub = PositionBillServiceHelper.getNoLineSuffixProp(propName, "_"+suffix);
+                        tableValueSetter.set(propName, getValue(entryEntityDynList.get(i).get(posBillEntryTransKeyMap.getOrDefault(propNameSub, propNameSub))), i);
+                    }
+                }
+                tableValueSetter.set(PositionBillConstant.ID_KEY, entryEntityDynList.get(i).get(PositionBillConstant.ID_KEY), i);
+
+                if (PositionBillConstant.ADD_TAG.equals(suffix)) {
+                    tableValueSetter.set(String.join("_", PositionBillConstant.NCKD_POSITION_KEY, suffix), entryEntityDynList.get(i).getLong(String.join(".", PositionBillConstant.NCKD_POSITION_KEY, PositionBillConstant.ID_KEY)), i);
+                }
+
+            }
+
+        }
+    }
+
+    private Object getValue(Object object) {
+        return object instanceof DynamicObject ? ((DynamicObject) object).get(PositionBillConstant.ID_KEY) : object;
+    }
+
+    private void batchCreateNewEntryRow(TableValueSetter tableValueSetter, String entryEntity) {
+        if (!CollectionUtils.isEmpty(tableValueSetter.getFields())) {
+            AbstractFormDataModel model = (AbstractFormDataModel) getModel();
+            model.beginInit();
+            model.batchCreateNewEntryRow(entryEntity, tableValueSetter);
+            model.endInit();
+            getView().updateView(entryEntity);
+        }
+    }
+
+}

+ 2 - 1
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/business/hr/PositionBillBaseService.java → code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/business/hr/service/impl/PositionBillBaseService.java

@@ -1,10 +1,11 @@
-package nckd.jxccl.hrmp.hbpm.business.hr;
+package nckd.jxccl.hrmp.hbpm.business.hr.service.impl;
 
 import kd.bos.entity.datamodel.IDataModel;
 import kd.bos.form.IFormView;
 
 /**
  * 岗位申请单基础服务类
+ * @from: kd.hr.homs.business.domain.batchbill.service.impl.AdminOrgBatchBillBaseService
  * @author: jtd
  * @date: 2025/12/20 17:47
  */

+ 101 - 0
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/business/hr/service/impl/PositionBillBeforeBindDataService.java

@@ -0,0 +1,101 @@
+package nckd.jxccl.hrmp.hbpm.business.hr.service.impl;
+
+import kd.bos.common.enums.EnableEnum;
+import kd.bos.context.RequestContext;
+import kd.bos.form.IFormView;
+import kd.bos.form.container.Container;
+import kd.bos.logging.Log;
+import kd.bos.logging.LogFactory;
+import kd.bos.permission.api.HasPermOrgResult;
+import kd.bos.servicehelper.model.PermissionStatus;
+import kd.bos.servicehelper.org.OrgUnitServiceHelper;
+import kd.bos.servicehelper.org.OrgViewType;
+import kd.bos.servicehelper.permission.PermissionServiceHelper;
+import kd.hr.hbp.common.util.HRStringUtils;
+import kd.sdk.hr.hdm.common.enums.reg.RegBillStatusEnum;
+import nckd.jxccl.hrmp.hbpm.common.hr.PositionBillConstant;
+
+import java.util.EventObject;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * 岗位申请单前置绑定数据服务
+ * @from: kd.hr.homs.business.domain.batchbill.service.impl.AdminOrgBatchBillBeforeBindDataService
+ * @author: jtd
+ * @date: 2025/12/30 22:05
+ */
+public class PositionBillBeforeBindDataService extends PositionBillBaseService {
+    private static final Log LOGGER = LogFactory.getLog(PositionBillBeforeBindDataService.class);
+
+    public PositionBillBeforeBindDataService(IFormView view) {
+        super(view);
+    }
+
+    public void beforeBindData(EventObject e) {
+        changePageCacheFromWhatVie();
+        getView().getPageCache().put(PositionBillConstant.PC_ISLIST, EnableEnum.YES.getCode());
+        if (HRStringUtils.equals(getView().getFormShowParameter().getAppId(), PositionBillConstant.WFTASK_APP)) {
+            Container baseInfo = getView().getControl(PositionBillConstant.FS_BASEINFO_KEY);
+            baseInfo.setCollapse(true);
+        } else {
+            Container baseInfo = getView().getControl(PositionBillConstant.FS_BASEINFO_KEY);
+            baseInfo.setCollapse(false);
+        }
+
+        if (getModel().getDataEntity(true).getDynamicObject(PositionBillConstant.ORG_KEY) == null) {
+            getView().getModel().setValue(PositionBillConstant.ORG_KEY, OrgUnitServiceHelper.getRootOrgId());
+        }
+
+        String billstatus = getModel().getDataEntity().getString(PositionBillConstant.BILL_STATUS_KEY);
+        // 显示/隐藏 查看流程图
+        if (HRStringUtils.equalsAny(billstatus, RegBillStatusEnum.ALREADYSUBMIT.getCode(), RegBillStatusEnum.APPROVEPASSED.getCode(), RegBillStatusEnum.APPROVING.getCode(), RegBillStatusEnum.APPROVEREJECTED.getCode()) && getModel().getDataEntity().getBoolean(PositionBillConstant.ISEXISTSWORKFLOW_KEY)) {
+            getView().setVisible(true, new String[]{PositionBillConstant.BAR_VIEWFLOWCHART_KEY});
+        } else {
+            getView().setVisible(false, new String[]{PositionBillConstant.BAR_VIEWFLOWCHART_KEY});
+        }
+
+    }
+
+    private void changePageCacheFromWhatVie() {
+        if (Boolean.TRUE.toString().equals(getView().getFormShowParameter().getCustomParam(PositionBillConstant.CP_FROMLIST))) {
+            Object businessUnit = getView().getFormShowParameter().getCustomParam(PositionBillConstant.CP_BUSINESSUNIT);
+            if (businessUnit != null) {
+                getModel().setValue(PositionBillConstant.ORG_KEY, businessUnit);
+            } else if (!Boolean.TRUE.toString().equals(getView().getFormShowParameter().getCustomParam(PositionBillConstant.CP_ISFROMBILLCLICK))) {
+                HasPermOrgResult hrPermOrg = PermissionServiceHelper.getAllPermOrgs(RequestContext.get().getCurrUserId(), "21", PositionBillConstant.HOMS_APP, PositionBillConstant.HAOS_ADMINORGDETAIL_ENTITY, PermissionStatus.View, false);
+                List<Long> hasPermOrgs = hrPermOrg.getHasPermOrgs();
+                if (!Objects.isNull(hasPermOrgs) && hasPermOrgs.size() != 0) {
+                    if (hasPermOrgs.contains(RequestContext.get().getOrgId())) {
+                        getModel().setValue(PositionBillConstant.ORG_KEY, RequestContext.get().getOrgId());
+                    } else {
+                        getModel().setValue(PositionBillConstant.ORG_KEY, hasPermOrgs.get(0));
+                    }
+                }
+            }
+
+            getView().getFormShowParameter().setCustomParam(PositionBillConstant.CP_FROMLIST, Boolean.FALSE.toString());
+            getView().cacheFormShowParameter();
+        } else if (Boolean.TRUE.toString().equals(getView().getPageCache().get(PositionBillConstant.PC_ISFROMIMPORT)) || getView().getParentView() != null && (PositionBillConstant.NCKD_POSTMGR_APPHOME_ENTITY.equals(getView().getParentView().getEntityId()) || getView().getParentView().getEntityId().startsWith("wf_"))) {
+            if (getView().getParentView() != null && PositionBillConstant.NCKD_POSTMGR_APPHOME_ENTITY.equals(getView().getParentView().getEntityId()) && getView().getPageCache().get(PositionBillConstant.PC_ISFROMHOMEPAGE) == null) {
+                HasPermOrgResult hrPermOrg = PermissionServiceHelper.getAllPermOrgs(RequestContext.get().getCurrUserId(), "21", PositionBillConstant.HOMS_APP, PositionBillConstant.HAOS_ADMINORGDETAIL_ENTITY, PermissionStatus.View, false);
+                List<Long> hasPermOrgs = hrPermOrg.getHasPermOrgs();
+                if (!Objects.isNull(hasPermOrgs) && hasPermOrgs.size() != 0) {
+                    if (hasPermOrgs.contains(RequestContext.get().getOrgId())) {
+                        getModel().setValue(PositionBillConstant.ORG_KEY, RequestContext.get().getOrgId());
+                    } else {
+                        getModel().setValue(PositionBillConstant.ORG_KEY, hasPermOrgs.get(0));
+                    }
+
+                    getView().getPageCache().put(PositionBillConstant.PC_ISFROMHOMEPAGE, Boolean.TRUE.toString());
+                }
+            }
+
+            getView().getPageCache().put(PositionBillConstant.PC_ISFROMIMPORT, Boolean.FALSE.toString());
+        } else {
+            String parentView = getView().getParentView() != null ? getView().getParentView().getEntityId() : "null";
+            LOGGER.info("method changePageCacheFromWhatVie parentView is [{}]", parentView);
+        }
+
+    }
+}

+ 195 - 0
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/business/hr/service/impl/PositionBillClosedCallBackService.java

@@ -0,0 +1,195 @@
+package nckd.jxccl.hrmp.hbpm.business.hr.service.impl;
+
+import com.google.common.collect.Lists;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.dataentity.metadata.IDataEntityProperty;
+import kd.bos.dataentity.metadata.IMetadata;
+import kd.bos.dataentity.metadata.clr.DataEntityPropertyCollection;
+import kd.bos.entity.EntityMetadataCache;
+import kd.bos.entity.MainEntityType;
+import kd.bos.entity.datamodel.AbstractFormDataModel;
+import kd.bos.entity.datamodel.TableValueSetter;
+import kd.bos.form.IFormView;
+import kd.bos.form.events.ClosedCallBackEvent;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
+import kd.hr.hbp.business.servicehelper.HRBaseServiceHelper;
+import kd.hr.hbp.common.util.HRDyObjectPropUtil;
+import nckd.jxccl.hrmp.hbpm.common.hr.PatternUtil;;
+import nckd.jxccl.hrmp.hbpm.common.hr.PositionBillConstant;
+import nckd.jxccl.hrmp.hbpm.common.hr.PositionChangeTypeEnum;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+/**
+ * 岗位申请单关闭回调服务类
+ * @from: kd.hr.homs.business.domain.batchbill.service.impl.AdminOrgBatchBillClosedCallBackService
+ * @author: jtd
+ * @date: 2025/12/20 17:29
+ */
+public class PositionBillClosedCallBackService extends PositionBillBaseService {
+
+    public PositionBillClosedCallBackService(IFormView view) {
+        super(view);
+    }
+
+    public void closedCallBack(ClosedCallBackEvent closedCallBackEvent) {
+        switch (closedCallBackEvent.getActionId()) {
+            case PositionBillConstant.NCKD_ENTRYENTITY_ADD_KEY:
+                if (onlyForView(closedCallBackEvent)) {
+                    return;
+                }
+                updateAddEntryEntity();
+
+                if (getView().getPageCache().get(PositionBillConstant.PC_LASTTIMEADDENTRYID) != null) {
+                    getView().invokeOperation(PositionBillConstant.NEWENTRY_ADD_OP);
+                }
+                break;
+            case  PositionBillConstant.NCKD_ENTRYENTITY_CHANGE_KEY:
+                saveReturn(closedCallBackEvent.getReturnData(), PositionBillConstant.NCKD_ENTRYENTITY_CHANGE_KEY);
+        }
+    }
+
+    private boolean onlyForView(ClosedCallBackEvent closedCallBackEvent) {
+        return closedCallBackEvent.getReturnData() == null;
+    }
+
+    private void updateAddEntryEntity() {
+        DataEntityPropertyCollection entryEntityInfo = getModel().getDataEntity(true).getDynamicObjectCollection(PositionBillConstant.NCKD_ENTRYENTITY_ADD_KEY).getDynamicObjectType().getProperties();
+        MainEntityType entityType = EntityMetadataCache.getDataEntityType(PositionBillConstant.NCKD_POSBILLENTRYADD_ENTITY);
+        DataEntityPropertyCollection addEntityInfo = entityType.getProperties();
+        Map<String, IDataEntityProperty> addNamePropMap = addEntityInfo.stream().collect(Collectors.toMap(IMetadata::getName, Function.identity()));
+        List<String> selectPropList = new ArrayList<String>();
+        Set<String> toSetValueEntryPropList = new HashSet<String>();
+
+        String lineSuffix = "_"+PositionBillConstant.ADD_TAG;
+        // 获取分录要转换的键值,将单据分录字段转换转成分录页面字段
+        Map<String, String> posBillEntryTransKeyMap = PositionBillServiceHelper.getPosBillEntryTransKeyMap();
+        for(IDataEntityProperty iDataEntityProperty : entryEntityInfo) {
+            String entryPropName = iDataEntityProperty.getName();
+            if (entryPropName.endsWith(lineSuffix)) {
+                String entryPropNameSub = PositionBillServiceHelper.getNoLineSuffixProp(entryPropName, lineSuffix);
+                if (posBillEntryTransKeyMap.containsKey(entryPropNameSub)) {
+                    selectPropList.add(posBillEntryTransKeyMap.get(entryPropNameSub));
+                    toSetValueEntryPropList.add(entryPropName);
+                } else if (addNamePropMap.containsKey(entryPropNameSub)) {
+                    selectPropList.add(entryPropNameSub);
+                    toSetValueEntryPropList.add(entryPropName);
+                }
+            }
+        }
+
+        toSetValueEntryPropList.add(PositionBillConstant.ID_KEY);
+        HRBaseServiceHelper posBillEntryAddServiceHelper = new HRBaseServiceHelper(PositionBillConstant.NCKD_POSBILLENTRYADD_ENTITY);
+        Long billId = getModel().getDataEntity().getLong(PositionBillConstant.ID_KEY);
+        QFilter qFilter = (new QFilter(PositionBillConstant.NCKD_BILLID, QCP.equals, billId)).and(new QFilter(String.join(".", PositionBillConstant.NCKD_CHANGETYPE, PositionBillConstant.NUMBER_KEY), QCP.equals, PositionChangeTypeEnum.ADD.getNumber()));
+        DynamicObject[] addPositionDyArr = posBillEntryAddServiceHelper.load(String.join(",", selectPropList), qFilter.toArray(), PositionBillConstant.NCKD_SEQUENCE);
+
+        getModel().deleteEntryData(PositionBillConstant.NCKD_ENTRYENTITY_ADD_KEY);
+        TableValueSetter vs = new TableValueSetter();
+        toSetValueEntryPropList.forEach((prop) -> vs.addField(prop, new Object[0]));
+
+        for(DynamicObject addPositionDy : addPositionDyArr) {
+            List<Object> values = Lists.newArrayListWithCapacity(addPositionDyArr.length);
+
+            for(String entryPropName : toSetValueEntryPropList) {
+                if (entryPropName.equals(PositionBillConstant.ID_KEY)) {
+                    values.add(addPositionDy.getLong(PositionBillConstant.ID_KEY));
+                } else {
+                    String propName = PositionBillServiceHelper.getNoLineSuffixProp(entryPropName, lineSuffix);
+                    propName = posBillEntryTransKeyMap.getOrDefault(propName, propName);
+                    if (addPositionDy.get(propName) instanceof DynamicObject) {
+                        values.add(HRDyObjectPropUtil.getIdLongObject(addPositionDy.getDynamicObject(propName)));
+                    } else {
+                        values.add(addPositionDy.get(propName));
+                    }
+                }
+            }
+
+            vs.addRow(values.toArray());
+        }
+
+        AbstractFormDataModel model = (AbstractFormDataModel) getModel();
+        model.beginInit();
+        model.batchCreateNewEntryRow(PositionBillConstant.NCKD_ENTRYENTITY_ADD_KEY, vs);
+        model.endInit();
+        getView().updateView(PositionBillConstant.NCKD_ENTRYENTITY_ADD_KEY);
+    }
+
+    private void saveReturn(Object data, String entryEntityInfo) {
+        if (data instanceof Map) {
+            Map<String, Object> map = (Map) data;
+            DynamicObjectCollection info = getModel().getDataEntity(true).getDynamicObjectCollection(entryEntityInfo);
+            DataEntityPropertyCollection properties = info.getDynamicObjectType().getProperties();
+            Optional<DynamicObject> changeEntry = info.stream().filter((entry) -> entry.getLong(PositionBillConstant.ID_KEY) == (Long) map.get(PositionBillConstant.ID_KEY)).findFirst();
+            if (changeEntry.isPresent()) {
+                DynamicObject dynamicObject = changeEntry.get();
+                DataEntityPropertyCollection propers = dynamicObject.getDataEntityType().getProperties();
+                map.keySet().forEach((item) -> {
+                    if (propers.containsKey(item)) {
+                        dynamicObject.set(item, map.get(item));
+                    }
+
+                });
+                getView().updateView(entryEntityInfo);
+            } else {
+                String lineSuffix = entryEntityInfo.substring(entryEntityInfo.lastIndexOf("_"));
+                TableValueSetter vs = new TableValueSetter();
+                List<String> propList = new ArrayList();
+
+                for(IDataEntityProperty property : properties) {
+                    String propName = property.getName();
+                    if (PatternUtil.isExProperty(propName) && propName.endsWith(lineSuffix)) {
+                        vs.addField(property.getName());
+                        propList.add(property.getName());
+                    }
+                }
+
+                vs.addField(PositionBillConstant.ID_KEY);
+                propList.add(PositionBillConstant.ID_KEY);
+                List<Object> values = Lists.newArrayListWithCapacity(16);
+
+                for(String prop : propList) {
+                    Object obj = map.get(prop);
+                    // 原上级岗位特殊处理
+                    if (PositionBillConstant.NCKD_ORIPARENT_KEY.equals(prop)) {
+                        values.add(getLongId(map.get(PositionBillConstant.NCKD_PARENT)));
+                        continue;
+                    }
+
+                    if (obj instanceof DynamicObject) {
+                        values.add(getLongId(obj));
+                    } else {
+                        values.add(obj);
+                    }
+                }
+
+                vs.addRow(values.toArray());
+                AbstractFormDataModel model = (AbstractFormDataModel) getModel();
+                model.beginInit();
+                model.batchCreateNewEntryRow(PositionBillConstant.NCKD_ENTRYENTITY_CHANGE_KEY, vs);
+                model.endInit();
+                getView().updateView(PositionBillConstant.NCKD_ENTRYENTITY_CHANGE_KEY);
+            }
+        }
+
+    }
+
+    private Object getLongId(Object mapValue) {
+        if (Objects.isNull(mapValue)) {
+            return null;
+        } else {
+            return mapValue instanceof DynamicObject ? ((DynamicObject) mapValue).getLong(PositionBillConstant.ID_KEY) : mapValue;
+        }
+    }
+
+}

+ 70 - 39
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/business/hr/PositionBillConfirmCallBackService.java → code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/business/hr/service/impl/PositionBillConfirmCallBackService.java

@@ -1,4 +1,4 @@
-package nckd.jxccl.hrmp.hbpm.business.hr;
+package nckd.jxccl.hrmp.hbpm.business.hr.service.impl;
 
 import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
@@ -18,10 +18,10 @@ import kd.bos.orm.query.QCP;
 import kd.bos.orm.query.QFilter;
 import kd.hr.hbp.business.servicehelper.HRBaseServiceHelper;
 import kd.hr.hbp.common.util.HRStringUtils;
-import kd.hr.homs.business.domain.orgfast.repository.AdminOrgFastChgHelper;
-import kd.hr.homs.business.utils.PatternUtil;
 import nckd.jxccl.base.common.utils.QueryFieldBuilder;
+import nckd.jxccl.hrmp.hbpm.common.hr.PatternUtil;
 import nckd.jxccl.hrmp.hbpm.common.hr.PositionBillConstant;
+import nckd.jxccl.hrmp.hbpm.common.hr.PositionChangeTypeEnum;
 
 import java.util.Arrays;
 import java.util.HashMap;
@@ -33,6 +33,7 @@ import java.util.stream.Collectors;
 
 /**
  * 岗位申请单确认回调服务类
+ * @from: kd.hr.homs.business.domain.batchbill.service.impl.AdminOrgBatchBillConfirmCallBackService
  * @author: jtd
  * @date: 2025/12/21 21:59
  */
@@ -50,8 +51,8 @@ public class PositionBillConfirmCallBackService extends PositionBillBaseService
                     return;
                 }
 
-                EntryGrid coopRelEntryGrid = getView().getControl(PositionBillConstant.NCKD_ENTRYENTITY_ADD_KEY);
-                int[] selectRows = coopRelEntryGrid.getSelectRows();
+                EntryGrid strategyEntryGrid = getView().getControl(String.join("_", PositionBillConstant.NCKD_ENTRYENTITY, callBackId.substring(callBackId.lastIndexOf("_")+1)));
+                int[] selectRows = strategyEntryGrid.getSelectRows();
                 HRBaseServiceHelper hrBaseServiceHelper = new HRBaseServiceHelper(PositionBillConstant.NCKD_POSITIONBILLENTRY_ENTITY);
                 List<Long> entryIdList = Lists.newArrayListWithExpectedSize(selectRows.length);
                 if (PositionBillConstant.DELETE_ROWS_ADD_OP.equals(callBackId)) {
@@ -64,7 +65,7 @@ public class PositionBillConfirmCallBackService extends PositionBillBaseService
                     for (int i = 0; i < deleteRows.length; ++i) {
                         int row = deleteRows[i];
                         entryIdList.add(getModel().getEntryEntity(PositionBillConstant.NCKD_ENTRYENTITY_ADD_KEY).get(row).getLong(PositionBillConstant.ID_KEY));
-                        positionIds.add(getModel().getEntryEntity(PositionBillConstant.NCKD_ENTRYENTITY_ADD_KEY).get(row).getLong(String.join("_", PositionBillConstant.NCKD_POSITION, PositionBillConstant.ADD_TAG)));
+                        positionIds.add(getModel().getEntryEntity(PositionBillConstant.NCKD_ENTRYENTITY_ADD_KEY).get(row).getLong(String.join("_", PositionBillConstant.NCKD_POSITION_KEY, PositionBillConstant.ADD_TAG)));
                     }
 
                     getModel().deleteEntryRows(PositionBillConstant.NCKD_ENTRYENTITY_ADD_KEY, deleteRows);
@@ -76,10 +77,36 @@ public class PositionBillConfirmCallBackService extends PositionBillBaseService
 
                 getView().showSuccessNotification("删除成功");
                 hrBaseServiceHelper.delete(entryIdList.toArray(new Long[0]));
+            } else if (!PositionBillConstant.CB_CLOSE_BILL.equals(callBackId)) {
+                // 避免正常的回调操作误入else,需要增加这个判断(比如select_position_的回调)
+            } else {
+                if (PositionBillConstant.CB_CLOSE_BILL.equals(callBackId) && event.getResult() == MessageBoxResult.Cancel) {
+                    return;
+                }
+
+                for (PositionChangeTypeEnum changeTypeEnum : PositionChangeTypeEnum.values()) {
+                    getModel().deleteEntryData(changeTypeEnum.getTag(PositionBillConstant.NCKD_ENTRYENTITYUNDERLINE_KEY));
+                }
+
+                long billId = getModel().getDataEntity().getLong(PositionBillConstant.ID_KEY);
+                HRBaseServiceHelper positionBillEntryHelper = new HRBaseServiceHelper(PositionBillConstant.NCKD_POSITIONBILLENTRY_ENTITY);
+                QFilter billIdFilter = new QFilter(PositionBillConstant.NCKD_BILLID, QCP.equals, billId);
+                String selectProperties = QueryFieldBuilder.create().add(PositionBillConstant.ID_KEY)
+                        .add(PositionBillConstant.NUMBER_KEY)
+                        .add(PositionBillConstant.NCKD_CHANGETYPE, PositionBillConstant.NUMBER_KEY)
+                        .add(PositionBillConstant.NCKD_POSITION_KEY)
+                        .buildSelect();
+                DynamicObject[] positionBillEntryDynArr = positionBillEntryHelper.query(selectProperties, new QFilter[]{billIdFilter});
+                positionBillEntryHelper.deleteByFilter(new QFilter[]{billIdFilter});
+                List<Long> addPositionIdList = Arrays.stream(positionBillEntryDynArr).filter((dynx) -> HRStringUtils.equals(dynx.getDynamicObject(PositionBillConstant.NCKD_CHANGETYPE).getString(PositionBillConstant.NUMBER_KEY), PositionBillConstant.ADD_TAG)).map((dynx) -> dynx.getLong(String.join(".", PositionBillConstant.NCKD_POSITION_KEY, PositionBillConstant.ID_KEY))).collect(Collectors.toList());
+                PositionBillServiceHelper.delAddMaster(addPositionIdList);
+
+                getView().getPageCache().put(PositionBillConstant.PC_ISCANCELOVER, Boolean.TRUE.toString());
+                getView().invokeOperation(PositionBillConstant.CLOSE_OP);
             }
         }
 
-        changePositionConfirm(event, callBackId);
+        changeOrgOrPositionConfirm(event, callBackId);
     }
 
     private int[] validateHasChildPositionAndDelete() {
@@ -94,7 +121,7 @@ public class PositionBillConfirmCallBackService extends PositionBillBaseService
         List<Integer> rowList = Arrays.stream(rows).boxed().collect(Collectors.toList());
 
         // 岗位标识-新增岗位
-        String positionAddKey = String.join("_", PositionBillConstant.NCKD_POSITION, PositionBillConstant.ADD_TAG);
+        String positionAddKey = String.join("_", PositionBillConstant.NCKD_POSITION_KEY, PositionBillConstant.ADD_TAG);
         for(int i = 0; i < count; ++i) {
             DynamicObject dynamicObject = getModel().getEntryEntity(PositionBillConstant.NCKD_ENTRYENTITY_ADD_KEY).get(i);
             long positionId = dynamicObject.getLong(positionAddKey);
@@ -159,23 +186,22 @@ public class PositionBillConfirmCallBackService extends PositionBillBaseService
         return deleteRowIndexList.stream().mapToInt(Integer::intValue).toArray();
     }
 
-    private void changePositionConfirm(MessageBoxClosedEvent messageBoxClosedEvent, String callBackId) {
-        if (callBackId.startsWith("select_position_")) {
-            String suffix = callBackId.replace("select_position_", "");
+    private void changeOrgOrPositionConfirm(MessageBoxClosedEvent messageBoxClosedEvent, String callBackId) {
+        if (callBackId.startsWith(PositionBillConstant.CB_SELECT_POSITION)) {
+            String suffix = callBackId.substring(16);
             String lineSuffix = "_" + suffix;
             HRBaseServiceHelper helper = new HRBaseServiceHelper(PositionBillConstant.HBPM_POSITIONHR);
-            EntryGrid entryGrid = getView().getControl(PositionBillConstant.NCKD_ENTRYENTITY + lineSuffix);
-            String positionRow = getView().getPageCache().get("positionRow");
+            String positionRow = getView().getPageCache().get(PositionBillConstant.PC_POSITIONROW);
             int row = Integer.parseInt(positionRow);
             if (messageBoxClosedEvent.getResult() != MessageBoxResult.Yes) {
                 DynamicObject entryEntityDyn = getModel().getDataEntity(true).getDynamicObjectCollection(PositionBillConstant.NCKD_ENTRYENTITY + lineSuffix).get(row);
-                String positionOld = getView().getPageCache().get("positionOld");
-                if (HRStringUtils.isNotEmpty(positionOld)) {// 461
+                String positionOld = getView().getPageCache().get(PositionBillConstant.PC_POSITIONOLD);
+                if (HRStringUtils.isNotEmpty(positionOld)) {
                     QFilter filter = new QFilter(PositionBillConstant.ID_KEY, QCP.equals, Long.parseLong(positionOld));
                     DynamicObject position = helper.queryOne(String.join(",", PositionBillConstant.ID_KEY, PositionBillConstant.NAME_KEY, PositionBillConstant.NUMBER_KEY), filter.toArray());
-                    entryEntityDyn.set(PositionBillConstant.NCKD_POSITION + lineSuffix, position);
+                    entryEntityDyn.set(PositionBillConstant.NCKD_POSITION_KEY + lineSuffix, position);
                 } else {
-                    entryEntityDyn.set(PositionBillConstant.NCKD_POSITION + lineSuffix, null);
+                    entryEntityDyn.set(PositionBillConstant.NCKD_POSITION_KEY + lineSuffix, null);
                 }
 
                 getView().updateView(PositionBillConstant.NCKD_ENTRYENTITY + lineSuffix);
@@ -183,50 +209,55 @@ public class PositionBillConfirmCallBackService extends PositionBillBaseService
             }
 
             DataEntityPropertyCollection entryEntityInfo = getModel().getDataEntity(true).getDynamicObjectCollection(String.join("_", PositionBillConstant.NCKD_ENTRYENTITY, suffix)).getDynamicObjectType().getProperties();
-
-            // 获取要转换的键值,转成岗位字段
             Map<String, String> transKeyMap = new HashMap<String, String>();
-            // 单据分录字段要先转分录页面字段
+            // 获取分录要转换的键值,将单据分录字段转换转成分录页面字段
             transKeyMap.putAll(PositionBillServiceHelper.getPosBillEntryTransKeyMap());
+            // 获取岗位要转换的键值
             transKeyMap.putAll(PositionBillServiceHelper.getPositionTransKeyMap());
-            // 倒转,转成岗位字段: 单据分录字段
-            Map<String, String> reverseTransKeyMap = transKeyMap.entrySet().stream().collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey));
-            // 获取岗位要排除的键值
+            // 排除字段
             List<String> positionExcludeKeyList = PositionBillServiceHelper.getPositionExcludeKeyList();
+            positionExcludeKeyList.forEach(transKeyMap::remove);
 
-            QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create().add(PositionBillConstant.ID_KEY);
+            QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create();
             for(IDataEntityProperty iDataEntityProperty : entryEntityInfo) {
-                if (PatternUtil.isExProperty(iDataEntityProperty.getName())) {
-                    String selectName = iDataEntityProperty.getName().substring(suffix.length() + 1);
-                    if (positionExcludeKeyList.contains(selectName)) {
-                        continue;
-                    } else if (transKeyMap.containsKey(selectName)) {
-                        queryFieldBuilder.add(reverseTransKeyMap.get(selectName));
-                    } else {
-                        queryFieldBuilder.add(selectName);
-                    }
+                String propName = iDataEntityProperty.getName();
+                if (PatternUtil.isExProperty(propName) && propName.endsWith(lineSuffix)) {
+                    String selectName = PositionBillServiceHelper.getNoLineSuffixProp(propName, lineSuffix);
+                    queryFieldBuilder.add(transKeyMap.getOrDefault(selectName, selectName));
                 }
             }
 
             DynamicObject entryEntityDyn = PositionBillServiceHelper.getFocusEntry(suffix, getView(), row);
-            long positionId = entryEntityDyn.getLong(PositionBillConstant.NCKD_POSITION + lineSuffix);
+            long positionId = entryEntityDyn.getLong(String.join(".", PositionBillConstant.NCKD_POSITION_KEY+lineSuffix, PositionBillConstant.ID_KEY));
             QFilter filter = new QFilter(PositionBillConstant.ID_KEY, QCP.equals, positionId);
             DynamicObject position = helper.queryOne(queryFieldBuilder.buildSelect(), filter.toArray());
             long entryId = ORM.create().genLongId(PositionBillConstant.NCKD_POSITIONBILLENTRY_ENTITY);
             entryEntityDyn.set(PositionBillConstant.ID_KEY, entryId);
             // 设置单据分录字段值
-            reverseTransKeyMap.forEach((key, value) -> entryEntityDyn.set(key, position.get(value)));
+            for(IDataEntityProperty iDataEntityProperty : entryEntityInfo) {
+                String propName = iDataEntityProperty.getName();
+                if (PatternUtil.isExProperty(propName) && propName.endsWith(lineSuffix)) {
+                    String selectName = PositionBillServiceHelper.getNoLineSuffixProp(propName, lineSuffix);
+                    if (positionExcludeKeyList.contains(selectName) || HRStringUtils.equals(selectName, PositionBillConstant.NCKD_POSDUTY_ENTRY_ENTITY_KEY)) {
+                        continue;
+                    }
+                    // 原上级岗位特殊处理
+                    if (HRStringUtils.equals(selectName, PositionBillConstant.NCKD_PARENT)) {
+                        entryEntityDyn.set(PositionBillConstant.NCKD_ORIPARENT_KEY+lineSuffix, position.get(transKeyMap.getOrDefault(selectName, selectName)));
+                    }
+                    entryEntityDyn.set(propName, position.get(transKeyMap.getOrDefault(selectName, selectName)));
+                }
+            }
 
-            //setChangeSence(lineSuffix, entryEntityDyn, row);
             getView().updateView(PositionBillConstant.NCKD_ENTRYENTITY + lineSuffix);
-        } else if (callBackId.equals(PositionBillConstant.CHANGE_TAG)) {
+        } else if (callBackId.equals(String.join("_", PositionBillConstant.NCKD_ORG_KEY, PositionBillConstant.CHANGE_TAG))) {
             String entryId = String.join("_", PositionBillConstant.NCKD_ENTRYENTITY, callBackId);
             EntryGrid entryGrid = getView().getControl(entryId);
             int row = entryGrid.getEntryState().getFocusRow();
             if (messageBoxClosedEvent.getResult() == MessageBoxResult.Yes) {
-                AdminOrgFastChgHelper.cleanOrgBaseInfoForBillEntry(getView(), row, callBackId, entryId);
+                PosBillEntryFastChgHelper.cleanOrgBaseInfoForBillEntry(getView(), row, callBackId, entryId);
             } else {
-                String oldId = getView().getPageCache().get("entry_position_value");
+                String oldId = getView().getPageCache().get(PositionBillConstant.PC_ENTRY_ORG_VALUE);
                 getModel().beginInit();
                 getModel().setValue(callBackId, Long.parseLong(oldId), row);
                 getModel().endInit();

+ 44 - 24
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/business/hr/PositionBillPropertyChangedService.java → code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/business/hr/service/impl/PositionBillPropertyChangedService.java

@@ -1,4 +1,4 @@
-package nckd.jxccl.hrmp.hbpm.business.hr;
+package nckd.jxccl.hrmp.hbpm.business.hr.service.impl;
 
 import kd.bos.common.enums.EnableEnum;
 import kd.bos.dataentity.entity.DynamicObject;
@@ -15,14 +15,16 @@ import kd.bos.orm.query.QCP;
 import kd.bos.orm.query.QFilter;
 import kd.hr.hbp.business.servicehelper.HRBaseServiceHelper;
 import kd.hr.hbp.common.util.HRStringUtils;
-import kd.hr.homs.business.utils.PatternUtil;
+import nckd.jxccl.hrmp.hbpm.common.hr.PatternUtil;
 import nckd.jxccl.hrmp.hbpm.common.hr.PositionBillConstant;
 
+import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 /**
- *
- * @entity:
+ * 岗位申请单属性变更服务类
+ * @from: kd.hr.homs.business.domain.batchbill.service.impl.AdminOrgBatchBillPropertyChangedService
  * @author: jtd
  * @date: 2025/12/24 22:05
  */
@@ -49,15 +51,24 @@ public class PositionBillPropertyChangedService extends PositionBillBaseService
             int rowIndex = changedArgs.getChangeSet()[0].getRowIndex();
             String fieldKey = property.getName();
             String suffix = getSuffixByFieldKey(fieldKey);
-            String entryName = String.join("_", PositionBillConstant.NCKD_ENTRYENTITY, suffix);
             Object objectNew = changedArgs.getChangeSet()[0].getNewValue();
             Object objectOld = changedArgs.getChangeSet()[0].getOldValue();
-            if (fieldKey.equals(String.join("_", PositionBillConstant.NCKD_POSITION, suffix))) {
+            if (fieldKey.equals(String.join("_", PositionBillConstant.NCKD_POSITION_KEY, suffix))) {
                 if (objectOld == null) {
                     entrySelectF7Change(property, suffix, rowIndex);
                 } else if (objectNew != null) {
                     showConfirmByOldValue(changedArgs, suffix, rowIndex);
                 }
+            } else if (fieldKey.equals(String.join("_", PositionBillConstant.NCKD_ORG_KEY, suffix))) {
+                DynamicObject oldObj = (DynamicObject) objectOld;
+                DynamicObject newObj = (DynamicObject) objectNew;
+                if (newObj != null && oldObj != null && oldObj.getLong(PositionBillConstant.ID_KEY) != newObj.getLong(PositionBillConstant.ID_KEY)) {
+                    Long orgIDOld = oldObj == null ? 0L : oldObj.getLong(PositionBillConstant.ID_KEY);
+                    getView().getPageCache().remove(PositionBillConstant.PC_ENTRY_ORG_VALUE);
+                    getView().getPageCache().put(PositionBillConstant.PC_ENTRY_ORG_VALUE, String.valueOf(orgIDOld));
+                    ConfirmCallBackListener confirmCallBackListener = new ConfirmCallBackListener(fieldKey, closeCallBackPlugin);
+                    getView().showConfirm("切换组织体系管理组织后,将清除该组织不可使用的基础资料信息,是否切换?", MessageBoxOptions.OKCancel, confirmCallBackListener);
+                }
             }
         }
 
@@ -66,31 +77,32 @@ public class PositionBillPropertyChangedService extends PositionBillBaseService
     private void entrySelectF7Change(IDataEntityProperty property, String suffix, int row) {
         String lineSuffix = "_"+suffix;
         DataEntityPropertyCollection entryEntityInfo = getModel().getDataEntity(true).getDynamicObjectCollection(PositionBillConstant.NCKD_ENTRYENTITY+lineSuffix).getDynamicObjectType().getProperties();
+
+        Map<String, String> transKeyMap = new HashMap<String, String>();
         // 获取分录要转换的键值,将单据分录字段转换转成分录页面字段
-        Map<String, String> posBillTransKeyMap = PositionBillServiceHelper.getPosBillEntryTransKeyMap();
+        transKeyMap.putAll(PositionBillServiceHelper.getPosBillEntryTransKeyMap());
         // 获取岗位要转换的键值
-        Map<String, String> positionTransKeyMap = PositionBillServiceHelper.getPositionTransKeyMap();
+        transKeyMap.putAll(PositionBillServiceHelper.getPositionTransKeyMap());
+        // 排除字段
+        List<String> positionExcludeKeyList = PositionBillServiceHelper.getPositionExcludeKeyList();
+        positionExcludeKeyList.forEach(transKeyMap::remove);
 
         StringBuilder selectSqlBuilder = new StringBuilder();
         for(IDataEntityProperty iDataEntityProperty : entryEntityInfo) {
-            if (PatternUtil.isExProperty(iDataEntityProperty.getName())) {
-                String selectName = iDataEntityProperty.getName().replace(lineSuffix, "");
-                if (posBillTransKeyMap.containsKey(selectName)) {
-                    selectSqlBuilder.append(",").append(posBillTransKeyMap.get(selectName));
-                } else if (positionTransKeyMap.containsKey(selectName)) {
-                    selectSqlBuilder.append(",").append(positionTransKeyMap.get(selectName));
-                } else {
-                    selectSqlBuilder.append(",").append(selectName);
-                }
+            String propName = iDataEntityProperty.getName();
+            if (PatternUtil.isExProperty(propName) && propName.endsWith(lineSuffix)) {
+                String selectName = PositionBillServiceHelper.getNoLineSuffixProp(propName, lineSuffix);
+                selectSqlBuilder.append(",").append(transKeyMap.getOrDefault(selectName, selectName));
             }
         }
+        selectSqlBuilder.deleteCharAt(0);
 
         BasedataProp basedataProp = (BasedataProp) property;
         String baseEntityId = basedataProp.getBaseEntityId();
         Map<?, DynamicObject> dyMap = baseDataCacheMap.get(baseEntityId);
         DynamicObject entryEntityDyn = PositionBillServiceHelper.getFocusEntry(suffix, getView(), row);
         DynamicObject position = null;
-        long positionId = entryEntityDyn.getLong(String.join(".", PositionBillConstant.NCKD_POSITION+lineSuffix, PositionBillConstant.ID_KEY));
+        long positionId = entryEntityDyn.getLong(String.join(".", PositionBillConstant.NCKD_POSITION_KEY+lineSuffix, PositionBillConstant.ID_KEY));
         if (dyMap != null) {
             position = dyMap.get(positionId);
         }
@@ -107,12 +119,20 @@ public class PositionBillPropertyChangedService extends PositionBillBaseService
             entryEntityDyn.set(PositionBillConstant.ID_KEY, entryId);
 
             for(IDataEntityProperty iDataEntityProperty : entryEntityInfo) {
-                if (PatternUtil.isExProperty(iDataEntityProperty.getName())) {
-                    entryEntityDyn.set(iDataEntityProperty.getName(), position.get(iDataEntityProperty.getName().replace(lineSuffix, "")));
+                String propName = iDataEntityProperty.getName();
+                if (PatternUtil.isExProperty(propName) && propName.endsWith(lineSuffix)) {
+                    String selectName = PositionBillServiceHelper.getNoLineSuffixProp(propName, lineSuffix);
+                    if (positionExcludeKeyList.contains(selectName) || HRStringUtils.equals(selectName, PositionBillConstant.NCKD_POSDUTY_ENTRY_ENTITY_KEY)) {
+                        continue;
+                    }
+                    // 原上级岗位特殊处理
+                    if (HRStringUtils.equals(selectName, PositionBillConstant.NCKD_PARENT)) {
+                        entryEntityDyn.set(PositionBillConstant.NCKD_ORIPARENT_KEY+lineSuffix, position.get(transKeyMap.getOrDefault(selectName, selectName)));
+                    }
+                    entryEntityDyn.set(propName, position.get(transKeyMap.getOrDefault(selectName, selectName)));
                 }
             }
 
-            //setChangeScene(prefixLine, entryEntityDyn, row);
             getView().updateView(PositionBillConstant.NCKD_ENTRYENTITY+lineSuffix);
         }
 
@@ -121,9 +141,9 @@ public class PositionBillPropertyChangedService extends PositionBillBaseService
     private void showConfirmByOldValue(PropertyChangedArgs e, String suffix, int rowIndex) {
         DynamicObject position = (DynamicObject) e.getChangeSet()[0].getOldValue();
         Long positionOld = position != null ? position.getLong(PositionBillConstant.ID_KEY) : null;
-        getView().getPageCache().put("positionOld", positionOld == null ? "" : String.valueOf(positionOld));
-        getView().getPageCache().put("positionRow", String.valueOf(rowIndex));
-        ConfirmCallBackListener confirmCallBackListener = new ConfirmCallBackListener("select_position_" + suffix, getCloseCallBackPlugin());
+        getView().getPageCache().put(PositionBillConstant.PC_POSITIONOLD, positionOld == null ? "" : String.valueOf(positionOld));
+        getView().getPageCache().put(PositionBillConstant.PC_POSITIONROW, String.valueOf(rowIndex));
+        ConfirmCallBackListener confirmCallBackListener = new ConfirmCallBackListener(PositionBillConstant.CB_SELECT_POSITION + suffix, getCloseCallBackPlugin());
         getView().showConfirm("切换岗位后,当前已修改的内容将会丢失,是否继续?", MessageBoxOptions.OKCancel, confirmCallBackListener);
     }
 

+ 211 - 0
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/business/hr/service/impl/PositionBillSaveHelper.java

@@ -0,0 +1,211 @@
+package nckd.jxccl.hrmp.hbpm.business.hr.service.impl;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.dataentity.metadata.IDataEntityProperty;
+import kd.bos.dataentity.metadata.clr.DataEntityPropertyCollection;
+import kd.bos.logging.Log;
+import kd.bos.logging.LogFactory;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
+import kd.hr.hbp.business.servicehelper.HRBaseServiceHelper;
+import kd.hr.hbp.common.util.HRDynamicObjectUtils;
+import kd.hr.hbp.common.util.HRStringUtils;
+import nckd.jxccl.hrmp.hbpm.common.hr.PatternUtil;
+import nckd.jxccl.hrmp.hbpm.common.hr.PositionBillConstant;
+import nckd.jxccl.hrmp.hbpm.common.hr.PositionChangeTypeEnum;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+;
+
+/**
+ * 岗位申请单保存服务
+ * @from: kd.hr.homs.business.domain.orgbatch.service.impl.OrgBatchBillSaveHelper
+ * @author: jtd
+ * @date: 2025/12/27 15:04
+ */
+public class PositionBillSaveHelper {
+    private static PositionBillSaveHelper INSTANCE = new PositionBillSaveHelper();
+    private static final Log logger = LogFactory.getLog(PositionBillSaveHelper.class);
+    private static final HRBaseServiceHelper positionBillEntryEntityHelper = new HRBaseServiceHelper(PositionBillConstant.NCKD_POSITIONBILLENTRY_ENTITY);
+
+    public static PositionBillSaveHelper getInstance() {
+        return INSTANCE;
+    }
+
+    public void positionBillSave(DynamicObject dataEntity) {
+        long startTime = System.currentTimeMillis();
+        HRBaseServiceHelper positionBillEntryEntityHelper = new HRBaseServiceHelper(PositionBillConstant.NCKD_POSITIONBILLENTRY_ENTITY);
+        Long billId = dataEntity.getLong(PositionBillConstant.ID_KEY);
+        QFilter billIdFilter = new QFilter(PositionBillConstant.NCKD_BILLID, QCP.equals, billId);
+        DynamicObject[] positionBillEntryEntityDyns = positionBillEntryEntityHelper.loadDynamicObjectArray(new QFilter[]{billIdFilter});
+        Set<Long> positionIdSetFromDB = Arrays.stream(positionBillEntryEntityDyns).map((dyn) -> dyn.getLong(String.join(".", PositionBillConstant.NCKD_POSITION_KEY, PositionBillConstant.ID_KEY))).collect(Collectors.toSet());
+        Map<Long, DynamicObject> positionId2DynFromDBMap = Arrays.stream(positionBillEntryEntityDyns).collect(Collectors.toMap((dyn) -> dyn.getLong(String.join(".", PositionBillConstant.NCKD_POSITION_KEY, PositionBillConstant.ID_KEY)), (dyn) -> dyn, (k, v) -> k));
+        DynamicObjectCollection allEntryEntityDyn = getEntryEntityData(dataEntity);
+        if (allEntryEntityDyn.size() != 0) {
+            List<Long> positionIdList = getAllEntryPositionId(allEntryEntityDyn);
+            Map<Long, DynamicObject> positionId2BasicInfoDynMap = PositionBillServiceHelper.getPositionId2BasicInfoDynMapByIds(positionIdList);
+            List<DynamicObject> needSaveEntryDynList = Lists.newArrayListWithExpectedSize(allEntryEntityDyn.size());
+
+            for(DynamicObject entryEntityDyn : allEntryEntityDyn) {
+                String suffix = getSuffixFromEntryEntityDyn(entryEntityDyn);
+                Long positionId = getPositionId(entryEntityDyn, suffix);
+                DynamicObject positionBillEntryDyn;
+                if (positionIdSetFromDB.contains(positionId)) {
+                    positionBillEntryDyn = positionId2DynFromDBMap.get(positionId);
+                } else {
+                    positionBillEntryDyn = positionBillEntryEntityHelper.generateEmptyDynamicObject();
+                    positionBillEntryDyn.set(PositionBillConstant.NCKD_BILLID, dataEntity.getLong(PositionBillConstant.ID_KEY));
+                    DynamicObject basicInfoDyn = positionId2BasicInfoDynMap.get(positionId);
+                    assembleSaveEntryDyn(positionBillEntryDyn, basicInfoDyn);
+                }
+
+                boolean neeSave = coverdEntryValue(positionBillEntryDyn, entryEntityDyn, suffix);
+                if (neeSave || !positionIdSetFromDB.contains(positionId)) {
+                    needSaveEntryDynList.add(positionBillEntryDyn);
+                }
+            }
+
+            if (needSaveEntryDynList.isEmpty()) {
+                logger.info("needSaveEntryDynList is empty");
+            }
+
+            resetSequence(needSaveEntryDynList);
+            setAdminOrgBoId(needSaveEntryDynList, positionId2BasicInfoDynMap);
+            if (needSaveEntryDynList.isEmpty()) {
+                logger.info("needSaveEntryDynList is empty");
+            } else {
+                positionBillEntryEntityHelper.save(needSaveEntryDynList.toArray(new DynamicObject[0]));
+                billIdFilter.and(PositionBillConstant.CREATOR_KEY, QCP.equals, 0);
+                positionBillEntryEntityHelper.deleteByFilter(billIdFilter.toArray());
+                logger.info(String.format(Locale.ROOT, "positionBillSave() time cost is: %s", System.currentTimeMillis() - startTime));
+            }
+        }
+    }
+
+    private void resetSequence(List<DynamicObject> needSaveEntryDynList) {
+        Map<Long, Integer> map = Maps.newHashMapWithExpectedSize(3);
+        needSaveEntryDynList.stream().forEach((dyn) -> {
+            long changeTypeId = dyn.getLong(String.join(".", PositionBillConstant.NCKD_CHANGETYPE, PositionBillConstant.ID_KEY));
+            if (changeTypeId == 0L) {
+                changeTypeId = dyn.getLong(PositionBillConstant.NCKD_CHANGETYPE);
+            }
+
+            if (Objects.isNull(map.get(changeTypeId))) {
+                int sequence = 0;
+                QFilter billIdFilter = new QFilter(PositionBillConstant.NCKD_BILLID, QCP.equals, dyn.get(PositionBillConstant.NCKD_BILLID));
+                QFilter changeTypeFilter = new QFilter(String.join(".", PositionBillConstant.NCKD_CHANGETYPE, PositionBillConstant.ID_KEY), QCP.equals, changeTypeId);
+                DynamicObject[] dys = positionBillEntryEntityHelper.query(PositionBillConstant.NCKD_SEQUENCE, new QFilter[]{billIdFilter, changeTypeFilter}, String.format("%s DESC", PositionBillConstant.NCKD_SEQUENCE), 1);
+                if (dys != null && dys.length > 0) {
+                    sequence = dys[0].getInt(PositionBillConstant.NCKD_SEQUENCE);
+                }
+
+                ++sequence;
+                dyn.set(PositionBillConstant.NCKD_SEQUENCE, sequence);
+                map.put(changeTypeId, sequence);
+            } else {
+                Integer sequence = map.get(changeTypeId);
+                sequence = sequence + 1;
+                dyn.set(PositionBillConstant.NCKD_SEQUENCE, sequence);
+                map.put(changeTypeId, sequence);
+            }
+
+        });
+    }
+
+    public Long getPositionId(DynamicObject entryEntityDynFromPage, String suffix) {
+        String idFieldName = String.join(".", PositionBillConstant.NCKD_POSITION_KEY, PositionBillConstant.ID_KEY);
+        if (HRStringUtils.equals(entryEntityDynFromPage.getString(spliceTwoStringByUnderLine(suffix, String.join(".", PositionBillConstant.NCKD_CHANGETYPE, PositionBillConstant.NUMBER_KEY))), PositionChangeTypeEnum.ADD.getNumber())) {
+            idFieldName = PositionBillConstant.NCKD_POSITION_KEY;
+        }
+
+        String positionFiledName = spliceTwoStringByUnderLine(suffix, idFieldName);
+        return entryEntityDynFromPage.getLong(positionFiledName);
+    }
+
+    public String getSuffixFromEntryEntityDyn(DynamicObject entryEntityDynFromPage) {
+        String entryEntityName = entryEntityDynFromPage.getDynamicObjectType().getName();
+        int lastUnderLineIndex = entryEntityName.lastIndexOf("_");
+        return entryEntityName.substring(lastUnderLineIndex + 1);
+    }
+
+    public void assembleSaveEntryDyn(DynamicObject positionBillEntryDyn, DynamicObject basicInfoDyn) {
+        // 获取岗位要转换的键值
+        Map<String, String> positionReverseTransKeyMap = PositionBillServiceHelper.getPositionTransKeyMap().entrySet().stream().collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey, (oldValue, newValue) -> newValue));
+        HRDynamicObjectUtils.copy(basicInfoDyn, positionBillEntryDyn, positionReverseTransKeyMap);
+
+        // 原上级岗位特殊处理
+        positionBillEntryDyn.set(PositionBillConstant.NCKD_ORIPARENT_KEY, positionBillEntryDyn.get(PositionBillConstant.NCKD_PARENT));
+    }
+
+    public DynamicObjectCollection getEntryEntityData(DynamicObject dataEntity) {
+        List<String> entryExcludeAddName = Arrays.stream(PositionChangeTypeEnum.values()).filter((changeType) -> changeType != PositionChangeTypeEnum.ADD).map((changeType) -> changeType.getTag(PositionBillConstant.NCKD_ENTRYENTITYUNDERLINE_KEY)).collect(Collectors.toList());
+        DynamicObjectCollection dynColl = new DynamicObjectCollection();
+        entryExcludeAddName.forEach((entryName) -> dynColl.addAll(dataEntity.getDynamicObjectCollection(entryName)));
+        return dynColl;
+    }
+
+    public List<Long> getAllEntryPositionId(DynamicObjectCollection allEntryEntityDyns) {
+        List<Long> positionIdList = Lists.newArrayListWithExpectedSize(allEntryEntityDyns.size());
+        allEntryEntityDyns.forEach((dyn) -> {
+            String suffix = getSuffixFromEntryEntityDyn(dyn);
+            Long positionId = getPositionId(dyn, suffix);
+            positionIdList.add(positionId);
+        });
+        return positionIdList;
+    }
+
+    private void setAdminOrgBoId(List<DynamicObject> needSaveEntryDynList, Map<Long, DynamicObject> positionId2BasicInfoDynMap) {
+        needSaveEntryDynList.forEach((entryDyn) -> {
+            long positionId = entryDyn.getLong(String.join(".", PositionBillConstant.NCKD_POSITION_KEY, PositionBillConstant.ID_KEY));
+            DynamicObject basicInfoDyn = positionId2BasicInfoDynMap.get(positionId);
+            entryDyn.set(PositionBillConstant.NCKD_ADMINORGBOID_KEY, basicInfoDyn.getDynamicObject(PositionBillConstant.ADMINORG).getLong(PositionBillConstant.BOID_KEY));
+        });
+    }
+
+    public boolean coverdEntryValue(DynamicObject positionBillEntryDyn, DynamicObject entryEntity, String suffix) {
+        boolean needSave = false;
+        // 获取分录要转换的键值
+        Map<String, String> posBillEntryTransKeyMap = PositionBillServiceHelper.getPosBillEntryTransKeyMap();
+        DataEntityPropertyCollection props = positionBillEntryDyn.getDataEntityType().getProperties();
+
+        for(IDataEntityProperty property : entryEntity.getDataEntityType().getProperties()) {
+            String propName = property.getName();
+            if (PatternUtil.isExProperty(propName) && propName.endsWith("_"+suffix)) {
+                String propNameSub = PositionBillServiceHelper.getNoLineSuffixProp(propName, "_"+suffix);
+                propNameSub = posBillEntryTransKeyMap.getOrDefault(propNameSub, propNameSub);
+                IDataEntityProperty prop = props.get(propNameSub);
+                Object oldVal = positionBillEntryDyn.get(propNameSub);
+                Object newVal = entryEntity.get(propName);
+                if (prop != null && !(oldVal == null && newVal == null)) {
+                    if ((newVal == null && oldVal != null) || (newVal != null && oldVal == null) || !HRDynamicObjectUtils.compareValues(newVal, oldVal)) {
+                        needSave = true;
+                    }
+                }
+
+                // 类型相同的情况下才覆盖值,避免后续获取值的时候类型转换异常
+                if (prop != null && property.getPropertyType() == prop.getPropertyType()) {
+                    positionBillEntryDyn.set(propNameSub, newVal);
+                }
+            }
+        }
+        positionBillEntryDyn.set(PositionBillConstant.ID_KEY, entryEntity.get(PositionBillConstant.ID_KEY));
+
+        return needSave;
+    }
+
+    public String spliceTwoStringByUnderLine(String oneString, String otherString) {
+        String[] str = otherString.split("\\.");
+        return str.length > 1 ? str[0] + "_" + oneString + "." + str[1] : otherString + "_" + oneString;
+    }
+
+}

+ 581 - 0
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/business/hr/service/impl/PositionBillServiceHelper.java

@@ -0,0 +1,581 @@
+package nckd.jxccl.hrmp.hbpm.business.hr.service.impl;
+
+import com.alibaba.fastjson.JSONObject;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.kingdee.util.StringUtils;
+import kd.bos.bill.BillShowParameter;
+import kd.bos.bill.OperationStatus;
+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.entity.ILocaleString;
+import kd.bos.dataentity.serialization.SerializationUtils;
+import kd.bos.entity.constant.StatusEnum;
+import kd.bos.entity.datamodel.IDataModel;
+import kd.bos.entity.operate.OperateOptionConst;
+import kd.bos.entity.operate.result.OperationResult;
+import kd.bos.form.CloseCallBack;
+import kd.bos.form.FormShowParameter;
+import kd.bos.form.IFormView;
+import kd.bos.form.ShowType;
+import kd.bos.form.control.EntryGrid;
+import kd.bos.form.field.events.BeforeF7SelectEvent;
+import kd.bos.list.ListShowParameter;
+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.servicehelper.MetadataServiceHelper;
+import kd.bos.servicehelper.model.PermissionStatus;
+import kd.bos.servicehelper.operation.OperationServiceHelper;
+import kd.hr.hbp.business.servicehelper.HRBaseServiceHelper;
+import kd.hr.hbp.business.servicehelper.HRMServiceHelper;
+import kd.hr.hbp.common.constants.history.HisModelDataStatusEnum;
+import kd.hr.hbp.common.model.AuthorizedOrgResult;
+import kd.hr.hbp.common.util.HRDateTimeUtils;
+import kd.hr.hbp.common.util.HRDynamicObjectUtils;
+import kd.hr.hbp.common.util.HRObjectUtils;
+import kd.hr.hbp.common.util.HRStringUtils;
+import kd.sdk.hr.hdm.common.enums.reg.RegBillStatusEnum;
+import nckd.jxccl.base.common.utils.QueryFieldBuilder;
+import nckd.jxccl.hrmp.hbpm.common.hr.PositionBillConstant;
+import nckd.jxccl.hrmp.hbpm.common.hr.PositionChangeTypeEnum;
+import org.apache.commons.lang3.time.DateUtils;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * 岗位申请单帮组类
+ * @from: kd.hr.homs.business.domain.batchbill.repository.AdminOrgBatchChgHelper
+ * @author: jtd
+ * @date: 2025-10-31 14:33
+ */
+public class PositionBillServiceHelper {
+    private static final Log log = LogFactory.getLog(PositionBillServiceHelper.class);
+
+    public static String getNoLineSuffixProp(String prop, String lineSuffix) {
+        if (prop.endsWith(lineSuffix)) {
+            return prop.substring(0, prop.lastIndexOf(lineSuffix));
+        }
+        return prop;
+    }
+
+    /**
+     * 获取岗位转换键值
+     * @return 目标字段: 源字段
+     */
+    public static Map<String, String> getPositionTransKeyMap() {
+        String selectFields = QueryFieldBuilder.create().add(PositionBillConstant.NUMBER_KEY).add(PositionBillConstant.NAME_KEY).buildSelect();
+        DynamicObject[] transKeyDyos = HRBaseServiceHelper.create(PositionBillConstant.NCKD_POSITION_TRANSKEY_ENTITY).queryOriginalArray(selectFields, null);
+        Map<String, String> transKeyMap = Arrays.stream(transKeyDyos).collect(Collectors.toMap(
+                transKeyDyo -> transKeyDyo.getString(PositionBillConstant.NAME_KEY),
+                transKeyDyo -> transKeyDyo.getString(PositionBillConstant.NUMBER_KEY),
+                (oldValue, newValue) -> newValue)
+        );
+        return transKeyMap;
+    }
+
+    /**
+     * 获取岗位申请分录转换键值
+     * @return 单据分录字段: 分录页面字段
+     */
+    public static Map<String, String> getPosBillEntryTransKeyMap() {
+        String selectFields = QueryFieldBuilder.create().add(PositionBillConstant.NUMBER_KEY).add(PositionBillConstant.NAME_KEY).buildSelect();
+        DynamicObject[] transKeyDyos = HRBaseServiceHelper.create(PositionBillConstant.NCKD_PBENTRY_TRANSKEY_ENTITY).queryOriginalArray(selectFields, null);
+        Map<String, String> transKeyMap = Arrays.stream(transKeyDyos).collect(Collectors.toMap(
+                transKeyDyo -> transKeyDyo.getString(PositionBillConstant.NUMBER_KEY),
+                transKeyDyo -> transKeyDyo.getString(PositionBillConstant.NAME_KEY),
+                (oldValue, newValue) -> newValue));
+        return transKeyMap;
+    }
+
+    public static List<String> getPositionExcludeKeyList() {
+        DynamicObject[] positionExcludeKeyList = HRBaseServiceHelper.create(PositionBillConstant.NCKD_POSITION_EXCLUDEKEY_ENTITY).queryOriginalArray(PositionBillConstant.NUMBER_KEY, null);
+        List<String> excludeKeyList = Arrays.stream(positionExcludeKeyList).map(positionExcludeKeyDyo -> positionExcludeKeyDyo.getString(PositionBillConstant.NUMBER_KEY)).collect(Collectors.toList());
+        return excludeKeyList;
+    }
+
+    /**
+     * 获取分录序号
+     * @param iDataModel
+     * @param changeTypeNumber
+     * @return
+     */
+    public static int getEntrySeq(IDataModel iDataModel, String changeTypeNumber) {
+        Long billId = iDataModel.getDataEntity().getLong(PositionBillConstant.ID_KEY);
+        HRBaseServiceHelper positionBillEntryServiceHelper = new HRBaseServiceHelper(PositionBillConstant.NCKD_POSITIONBILLENTRY_ENTITY);
+        QFilter qFilter = new QFilter(PositionBillConstant.NCKD_BILLID, QCP.equals, billId);
+        qFilter.and(String.join(".", PositionBillConstant.NCKD_CHANGETYPE, PositionBillConstant.NUMBER_KEY), QCP.equals, changeTypeNumber);
+        String selectProps = String.join(",", PositionBillConstant.ID_KEY, PositionBillConstant.NCKD_SEQUENCE);
+        String order = String.format("%s desc", PositionBillConstant.NCKD_SEQUENCE);
+        DynamicObject dynamicObject = positionBillEntryServiceHelper.queryOne(selectProps, qFilter.toArray(), order);
+        return dynamicObject == null ? 1 : dynamicObject.getInt(PositionBillConstant.NCKD_SEQUENCE) + 1;
+    }
+
+    /**
+     * 打开表单界面
+     * @param iFormView
+     * @param operation
+     * @param pluginName
+     */
+    public static void openViewForm(IFormView iFormView, String operation, String pluginName, QFilter filter) {
+        if (iFormView.getModel().getValue(PositionBillConstant.ORG_KEY) == null) {
+            iFormView.showTipNotification("请先填写组织体系管理组织。");
+        } else {
+            HRBaseServiceHelper positionBillHelper = new HRBaseServiceHelper(PositionBillConstant.NCKD_POSITIONBILL_ENTITY);
+            QFilter idFilter = new QFilter(PositionBillConstant.ID_KEY, "=", iFormView.getModel().getDataEntity().getLong(PositionBillConstant.ID_KEY));
+            DynamicObject dynamicObject = positionBillHelper.loadDynamicObject(idFilter);
+            if (dynamicObject != null) {
+                String billStatus = dynamicObject.getString(PositionBillConstant.BILL_STATUS_KEY);
+                if (!billStatus.equals(RegBillStatusEnum.TEMPSTORAGE.getCode()) && !billStatus.equals(RegBillStatusEnum.WAITRESUBMIT.getCode()) && !billStatus.equals(RegBillStatusEnum.APPROVING.getCode()) && (!billStatus.equals(RegBillStatusEnum.ALREADYSUBMIT.getCode()) || !StringUtils.equals(iFormView.getFormShowParameter().getAppId(), PositionBillConstant.WFTASK_APP))) {
+                    String operateLocaleName = PositionChangeTypeEnum.getTipByTag(operation);
+                    String auditstatusName = RegBillStatusEnum.getName(dynamicObject.getString(PositionBillConstant.BILL_STATUS_KEY));
+                    iFormView.showErrorNotification(String.format("“%1$s”的单据不能“%2$s”。", auditstatusName, operateLocaleName));
+                    return;
+                }
+            }
+
+            ListShowParameter listShowParameter = new ListShowParameter();
+            if (filter != null) {
+                listShowParameter.getListFilterParameter().getQFilters().add(filter);
+            }
+
+            switch (operation) {
+                case PositionBillConstant.ADD_TAG:
+                    BillShowParameter formShowParameter = new BillShowParameter();
+                    formShowParameter.setCustomParam(PositionBillConstant.CP_POSITION_BSED, iFormView.getModel().getValue(PositionBillConstant.NCKD_EFFDT) == null ? HRDateTimeUtils.getNowDateTime().getTime() : ((Date)iFormView.getModel().getValue(PositionBillConstant.NCKD_EFFDT)).getTime());
+                    formShowParameter.setFormId(PositionBillConstant.NCKD_POSBILLENTRYADD_ENTITY);
+                    formShowParameter.getOpenStyle().setShowType(ShowType.Modal);
+                    formShowParameter.setCustomParam(PositionBillConstant.CP_BILLID, iFormView.getModel().getDataEntity().getLong(PositionBillConstant.ID_KEY));
+                    formShowParameter.setCustomParam(PositionBillConstant.CP_BILLBSED, iFormView.getModel().getDataEntity().getDate(PositionBillConstant.NCKD_EFFDT));
+                    formShowParameter.setCloseCallBack(new CloseCallBack(pluginName, PositionBillConstant.NCKD_ENTRYENTITY_ADD_KEY));
+
+                    if (HRStringUtils.equals(iFormView.getFormShowParameter().getAppId(), PositionBillConstant.WFTASK_APP)) {
+                        formShowParameter.setHasRight(true);
+                    }
+                    formShowParameter.setCustomParam(PositionBillConstant.ORG_KEY, iFormView.getModel().getDataEntity().getLong(String.join(".", PositionBillConstant.ORG_KEY, PositionBillConstant.ID_KEY)));
+                    int sequence = getEntrySeq(iFormView.getModel(), PositionChangeTypeEnum.ADD.getNumber());
+                    formShowParameter.setCustomParam(PositionBillConstant.CP_SEQUENCE, sequence);
+                    formShowParameter.setCustomParam(PositionBillConstant.OP_VALIDATOR_BILL_POSITION_ALL_CHANGE_POSITION_KEY, getThisBillAllValidateDataStr(dynamicObject));
+                    formShowParameter.setCustomParam(PositionBillConstant.OP_VALIDATOR_BILL_POSITION_NEW_POSITION_NUMBERS_KEY, getThisBillPositionNumbersStr(dynamicObject));
+                    iFormView.showForm(formShowParameter);
+                default:
+            }
+        }
+    }
+
+    public static AuthorizedOrgResult getOrgAuth(IFormView iFormView) {
+        Long userId = RequestContext.get().getCurrUserId();
+        String permItemId = PermissionStatus.View;// 查询权限
+        String appId = iFormView.getFormShowParameter().getCheckRightAppId();
+        AuthorizedOrgResult permResult = HRMServiceHelper.invokeHRMPService("hrcs", "IHRCSBizDataPermissionService", "getUserAdminOrgsF7", new Object[]{userId, appId, PositionBillConstant.NCKD_POSITIONBILL_ENTITY, permItemId, PositionBillConstant.NCKD_ADMINORGBOID_KEY, Maps.newHashMapWithExpectedSize(0)});
+        return permResult;
+    }
+
+    public static Map<Long, DynamicObject> getPositionId2BasicInfoDynMapByIds(List<Long> positionIdList) {
+        HRBaseServiceHelper serviceHelper = new HRBaseServiceHelper(PositionBillConstant.HBPM_POSITIONHR);
+        QFilter qFilter = new QFilter(PositionBillConstant.ID_KEY, QCP.in, positionIdList);
+        DynamicObject[] dynamicObjects = serviceHelper.loadDynamicObjectArray(qFilter.toArray());
+        Map<Long, DynamicObject> positionId2DynMap = Arrays.stream(dynamicObjects).collect(Collectors.toMap((dyn) -> dyn.getLong(PositionBillConstant.ID_KEY), (dyn) -> dyn));
+        return positionId2DynMap;
+    }
+
+    public static void setParentFilter(IFormView view, DynamicObject positionObject, BeforeF7SelectEvent event) {
+        DynamicObject dataEntityParent = view.getModel().getDataEntity(true);
+        QFilter isCurrentVersion = new QFilter(PositionBillConstant.IS_CURRENT_VERSION, QCP.equals, EnableEnum.NO.getCode());
+        DynamicObjectCollection addCollection = dataEntityParent.getDynamicObjectCollection(PositionBillConstant.NCKD_ENTRYENTITY_ADD_KEY);
+        Set<String> positionSet = addCollection.stream().map((s) -> s.getString(String.join("_", PositionBillConstant.NCKD_POSITION_KEY, PositionBillConstant.ADD_TAG))).collect(Collectors.toSet());
+        Set<Long> addPositionIdSet = positionSet.stream().map(Long::valueOf).collect(Collectors.toSet());
+        QFilter currentOrderFilter = new QFilter(PositionBillConstant.ID_KEY, QCP.in, addPositionIdSet);
+
+        AuthorizedOrgResult permResult = getOrgAuth(view);
+        if (permResult != null && !permResult.isHasAllOrgPerm()) {
+            log.info("[非全功能用户过滤条件]");
+            QFilter authFilter = new QFilter(String.join(PositionBillConstant.ADMINORG, PositionBillConstant.BOID_KEY), QCP.in, permResult.getHasPermOrgs());
+            event.getCustomQFilters().add(authFilter.or(currentOrderFilter));
+        }
+
+        DynamicObject buOrg = dataEntityParent.getDynamicObject(PositionBillConstant.ORG_KEY);
+        if (positionObject != null) {
+            event.getCustomQFilters().add(new QFilter(PositionBillConstant.ID_KEY, QCP.not_equals, positionObject.getLong(PositionBillConstant.ID_KEY)));
+            buOrg = positionObject.getDynamicObject(PositionBillConstant.ORG_KEY);
+        }
+
+        Date effDate = HRObjectUtils.isEmpty(view.getModel().getValue(PositionBillConstant.NCKD_EFFDT)) ? DateUtils.truncate(new Date(), 5) : (Date) view.getModel().getValue(PositionBillConstant.NCKD_EFFDT);
+        event.getCustomQFilters().add(new QFilter(PositionBillConstant.BSED_KEY, QCP.less_equals, effDate));
+        event.getCustomQFilters().add(new QFilter(PositionBillConstant.BSLED_KEY, QCP.large_equals, effDate));
+        if (buOrg != null) {
+            event.getCustomQFilters().add(new QFilter(PositionBillConstant.ORG_KEY, QCP.equals, buOrg.getLong(PositionBillConstant.ID_KEY)));
+        }
+
+        QFilter dataStatusFilter = new QFilter(PositionBillConstant.DATA_STATUS, QCP.in, Arrays.asList(HisModelDataStatusEnum.EFFECTING.getStatus(), HisModelDataStatusEnum.TO_BE_EFFECT.getStatus()));
+        event.getCustomQFilters().add(dataStatusFilter.or(currentOrderFilter));
+        QFilter statusFilter = new QFilter(PositionBillConstant.STATUS, QCP.equals, StatusEnum.C);
+        event.getCustomQFilters().add(statusFilter.or(currentOrderFilter));
+        event.getCustomQFilters().add(isCurrentVersion.or(currentOrderFilter));
+        ListShowParameter formShowParameter = (ListShowParameter) event.getFormShowParameter();
+        formShowParameter.setShowApproved(false);
+    }
+
+    public static void filterF7Org(IFormView iFormView, BeforeF7SelectEvent event, QFilter filter) {
+        FormShowParameter formShowParameter = event.getFormShowParameter();
+        formShowParameter.setFormId(PositionBillConstant.NCKD_HBPM_POSORGTREELISTF_ENTITY);
+        log.info("[岗位F7过滤条件]");
+        event.getCustomQFilters().add(filter);
+        Object originalValue = event.getOriginalValue();
+        if (originalValue instanceof DynamicObject) {
+            DynamicObject originalVal = (DynamicObject) originalValue;
+            long currentPositionId = originalVal.getLong(PositionBillConstant.ID_KEY);
+            QFilter positionIdFilter = new QFilter(PositionBillConstant.ID_KEY, QCP.not_equals, currentPositionId);
+            event.getCustomQFilters().add(positionIdFilter);
+        }
+
+        QFilter currentBillPositionFilter = filterCurrentBillOrg(iFormView);
+        event.getCustomQFilters().add(currentBillPositionFilter);
+
+        event.getCustomQFilters().add(new QFilter(PositionBillConstant.ORG_KEY, QCP.equals, ((DynamicObject) iFormView.getModel().getValue(PositionBillConstant.ORG_KEY)).getLong(PositionBillConstant.ID_KEY)));
+        event.getFormShowParameter().setCaption("岗位");
+    }
+
+    public static QFilter filterCurrentBillOrg(IFormView iFormView) {
+        List<Long> list = new ArrayList();
+        DynamicObjectCollection change = new DynamicObjectCollection();
+        if (iFormView.getEntityId().equals(PositionBillConstant.NCKD_POSITIONBILL_ENTITY)) {
+            change = iFormView.getModel().getDataEntity(true).getDynamicObjectCollection(PositionBillConstant.NCKD_ENTRYENTITY_CHANGE_KEY);
+        } else if (iFormView.getEntityId().equals(PositionBillConstant.NCKD_POSBILLENTRYCHANGE_ENTITY)) {
+            change = iFormView.getParentView().getModel().getDataEntity(true).getDynamicObjectCollection(PositionBillConstant.NCKD_ENTRYENTITY_CHANGE_KEY);
+        }
+
+        if (change != null) {
+            list.addAll(change.stream().map((position) -> position.getLong(String.format("%s_%s.%s", PositionBillConstant.NCKD_POSITION_KEY, PositionBillConstant.CHANGE_TAG, PositionBillConstant.BOID_KEY))).collect(Collectors.toList()));
+        }
+
+        return list.isEmpty() ? new QFilter(PositionBillConstant.ID_KEY, QCP.not_equals, 20000L) : new QFilter(PositionBillConstant.BOID_KEY, QCP.not_in, list);
+    }
+
+    public static DynamicObject getPositionDyById(Long orgId) {
+        HRBaseServiceHelper serviceHelper = new HRBaseServiceHelper(PositionBillConstant.HBPM_POSITIONHR);
+        QFilter qFilter = new QFilter(PositionBillConstant.ID_KEY, QCP.equals, orgId);
+        DynamicObject dynamicObject = serviceHelper.loadDynamicObject(qFilter.toArray());
+        return dynamicObject;
+    }
+
+    public static List<Long> getPositionAndChildren(Long positionId, Date positionBsed) {
+        List<Long> positionIds = new ArrayList();
+        HRBaseServiceHelper parentServiceHelper = new HRBaseServiceHelper(PositionBillConstant.HBPM_POSITIONHR);
+        QFilter parentFilter = new QFilter(PositionBillConstant.PARENT_KEY, QCP.equals, positionId)
+                .and(PositionBillConstant.IS_CURRENT_VERSION, QCP.equals, false)
+                .and(PositionBillConstant.BSED_KEY, QCP.less_equals, positionBsed)
+                .and(PositionBillConstant.BSLED_KEY, QCP.large_equals, positionBsed)
+                .and(PositionBillConstant.DATA_STATUS, QCP.in, Arrays.asList(HisModelDataStatusEnum.EFFECTING.getStatus(), HisModelDataStatusEnum.TO_BE_EFFECT.getStatus()))
+                .and(PositionBillConstant.STATUS, QCP.equals, StatusEnum.C);
+
+        DynamicObjectCollection dynamicObjects = parentServiceHelper.queryOriginalCollection(PositionBillConstant.ID_KEY, parentFilter.toArray());
+        dynamicObjects.forEach((dy) -> positionIds.add(dy.getLong(PositionBillConstant.ID_KEY)));
+
+        return positionIds;
+    }
+
+    /**
+     * 删除岗位新设暂存数据
+     * @param positionIdList
+     */
+    public static void delAddMaster(List<Long> positionIdList) {
+//        HisDeleteParam hisDeleteParam = new HisDeleteParam();
+//        hisDeleteParam.setEntityNumber(PositionBillConstant.HBPM_POSITIONHR);
+//        hisDeleteParam.setDataList(Arrays.asList(HRBaseServiceHelper.create(PositionBillConstant.HBPM_POSITIONHR).loadDynamicObjectArray(positionIdList.toArray())));
+//        HisModelServiceHelper.deleteBo(hisDeleteParam);
+        HRBaseServiceHelper positionHrHelper = new HRBaseServiceHelper(PositionBillConstant.HBPM_POSITIONHR);
+        positionHrHelper.deleteByFilter(new QFilter[]{new QFilter(PositionBillConstant.BOID_KEY, QCP.in, positionIdList)});
+    }
+
+    public static DynamicObject getFocusEntry(String suffix, IFormView view, int row) {
+        EntryGrid entryGrid = view.getControl(String.join("_", PositionBillConstant.NCKD_ENTRYENTITY, suffix));
+        if (row == -1) {
+            row = entryGrid.getEntryState().getFocusRow();
+        }
+
+        DynamicObject entryEntityDyn = view.getModel().getDataEntity(true).getDynamicObjectCollection(String.join("_", PositionBillConstant.NCKD_ENTRYENTITY, suffix)).get(row);
+        long entityId = entryEntityDyn.getLong(PositionBillConstant.ID_KEY);
+        if (entityId != 0L) {
+            HRBaseServiceHelper serviceHelper = new HRBaseServiceHelper(PositionBillConstant.NCKD_POSITIONBILLENTRY_ENTITY);
+            serviceHelper.deleteOne(entityId);
+            entryEntityDyn.set(PositionBillConstant.ID_KEY, 0L);
+        }
+
+        return entryEntityDyn;
+    }
+
+    public static Long getHisId(Long boId) {
+        DynamicObject dynamicObject = getHisDynamicObject(boId);
+        return dynamicObject != null ? dynamicObject.getLong(PositionBillConstant.ID_KEY) : boId;
+    }
+
+    public static DynamicObject getHisDynamicObject(Long boId) {
+        if (boId != null && boId != 0L) {
+            HRBaseServiceHelper positionHelper = new HRBaseServiceHelper(PositionBillConstant.HBPM_POSITIONHR);
+            QFilter idFilter = new QFilter(PositionBillConstant.BOID_KEY, QCP.equals, boId);
+            Date effDate = HRDateTimeUtils.truncateDate(new Date());
+            QFilter hisVersionFilter = (new QFilter(PositionBillConstant.IS_CURRENT_VERSION, QCP.equals, false)).and((new QFilter(PositionBillConstant.BSED_KEY, QCP.less_equals, effDate)).and(new QFilter(PositionBillConstant.BSLED_KEY, QCP.large_equals, effDate))).and(new QFilter(PositionBillConstant.DATA_STATUS, QCP.in, Arrays.asList(HisModelDataStatusEnum.EFFECTING.getStatus(), HisModelDataStatusEnum.EFFECTING.getStatus())));
+            hisVersionFilter.and(PositionBillConstant.ISSTANDARDPOS_KEY, QCP.equals, true);
+            return positionHelper.queryOne(PositionBillConstant.ID_KEY, new QFilter[]{idFilter, hisVersionFilter});
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * 构建岗位
+     * 用于校验岗位数据或获取/回收岗位编码
+     * @param addDy
+     * @return
+     */
+    public static DynamicObject getPositionHrDy(DynamicObject addDy) {
+        return getPositionHrDy(addDy, getPositionTransKeyMap());
+    }
+
+    /**
+     * 构建岗位
+     * 用于校验岗位数据或获取/回收岗位编码
+     * @param addDy
+     * @param transKeyMap
+     * @return
+     */
+    public static DynamicObject getPositionHrDy(DynamicObject addDy, Map<String, String> transKeyMap) {
+        DynamicObject positionHrDy = new DynamicObject(MetadataServiceHelper.getDataEntityType(PositionBillConstant.HBPM_POSITIONHR));
+        getPositionHrDy(addDy, positionHrDy, transKeyMap);
+        // 设置 是否标准岗位
+        positionHrDy.set(PositionBillConstant.ISSTANDARDPOS_KEY, EnableEnum.NO.getCode());
+        // 设置 业务状态
+        positionHrDy.set(PositionBillConstant.ENABLE, EnableEnum.YES.getCode());
+        // 设置 数据状态
+        positionHrDy.set(PositionBillConstant.STATUS, StatusEnum.C);
+        // 设置 数据版本状态
+        positionHrDy.set(PositionBillConstant.DATA_STATUS, HisModelDataStatusEnum.EFFECTING);
+        // 设置 行政组织
+        DynamicObject adminOrgVersionDy = addDy.getDynamicObject(PositionBillConstant.NCKD_ADMINORG);
+        if (HRObjectUtils.isEmpty(adminOrgVersionDy)) {
+            positionHrDy.set(PositionBillConstant.ADMINORG, null);
+        } else {
+            positionHrDy.set(PositionBillConstant.ADMINORG, HRBaseServiceHelper.create(PositionBillConstant.ADMINORG_ENTITYID).loadSingle(adminOrgVersionDy.getLong(PositionBillConstant.BOID_KEY)));
+        }
+        // 设置 上级岗位
+        DynamicObject parentPositionVersionDy = addDy.getDynamicObject(PositionBillConstant.NCKD_PARENT);
+        if (HRObjectUtils.isEmpty(parentPositionVersionDy)) {
+            positionHrDy.set(PositionBillConstant.PARENT_KEY, null);
+        } else {
+            positionHrDy.set(PositionBillConstant.PARENT_KEY, HRBaseServiceHelper.create(PositionBillConstant.HBPM_POSITIONHR).loadSingle(parentPositionVersionDy.getLong(PositionBillConstant.BOID_KEY)));
+        }
+        return positionHrDy;
+    }
+
+    /**
+     * 构建岗位
+     * @param addDy
+     * @param positionDyo
+     * @param transKeyMap
+     * @return
+     */
+    public static DynamicObject getPositionHrDy(DynamicObject addDy, DynamicObject positionDyo, Map<String, String> transKeyMap) {
+        // 将表单中的信息赋值到岗位信息中
+        HRDynamicObjectUtils.copy(addDy, positionDyo, transKeyMap);
+        // 设置ID
+        positionDyo.set(PositionBillConstant.ID_KEY, addDy.getLong(PositionBillConstant.ID_KEY));
+        // 设置 业务状态
+        //positionDyo.set(PositionBillConstant.ENABLE, EnableEnum.YES.getCode());
+        // 设置 数据状态
+        //positionDyo.set(PositionBillConstant.STATUS, StatusEnum.A);
+        // 设置 数据版本状态
+        //positionDyo.set(PositionBillConstant.DATA_STATUS, " ");
+        return positionDyo;
+    }
+
+    public static void entryEntityMore(IDataModel iDataModel, IFormView iFormView, String tag, OperationStatus status, String pluginName) {
+        EntryGrid entryEntity = iFormView.getControl(String.join("_", PositionBillConstant.NCKD_ENTRYENTITY, tag));
+        int row = entryEntity.getEntryState().getFocusRow();
+        DynamicObject dynamicObject = iDataModel.getDataEntity(true).getDynamicObjectCollection(String.join("_", PositionBillConstant.NCKD_ENTRYENTITY, tag)).get(row);
+        Map map = HRDynamicObjectUtils.convertDynamicObjectToMap(dynamicObject);
+        long id = dynamicObject.getLong(PositionBillConstant.ID_KEY);
+        BillShowParameter formShowParameter = new BillShowParameter();
+        Object dy = dynamicObject.get(String.join("_", PositionBillConstant.NCKD_POSITION_KEY, tag));
+        if (dy == null) {
+            iFormView.showTipNotification("请先选择岗位。");
+        } else {
+            if (PositionBillConstant.CHANGE_TAG.equals(tag)) {
+                formShowParameter.setFormId(PositionBillConstant.NCKD_POSBILLENTRYCHANGE_ENTITY);
+            }
+
+            // 获取岗位申请单分录服务
+            HRBaseServiceHelper helper = new HRBaseServiceHelper(PositionBillConstant.NCKD_POSITIONBILLENTRY_ENTITY);
+            boolean exists = helper.isExists(id);
+            if (exists) {
+                formShowParameter.setPkId(id);
+            } else {
+                formShowParameter.setCustomParam(PositionBillConstant.ID_KEY, id);
+            }
+
+            if (HRStringUtils.equals(iFormView.getFormShowParameter().getAppId(), PositionBillConstant.WFTASK_APP)) {
+                formShowParameter.setHasRight(true);
+            }
+
+            formShowParameter.setStatus(status);
+            formShowParameter.setCustomParam(PositionBillConstant.ID_KEY, id);
+            formShowParameter.getOpenStyle().setShowType(ShowType.Modal);
+            formShowParameter.setCustomParam(PositionBillConstant.CP_SELECTOBJECT, SerializationUtils.toJsonString(map));
+            formShowParameter.setCustomParam(PositionBillConstant.CP_BILLID, iDataModel.getValue(PositionBillConstant.ID_KEY));
+            formShowParameter.setCustomParam(PositionBillConstant.CP_POSITIONID, String.valueOf(dynamicObject.getLong(String.format("%s_%s.%s", PositionBillConstant.NCKD_POSITION_KEY, tag, PositionBillConstant.ID_KEY))));
+            formShowParameter.setCustomParam(PositionBillConstant.CP_POSITION_BSED, iDataModel.getValue(PositionBillConstant.NCKD_EFFDT) == null ? HRDateTimeUtils.getNowDateTime().getTime() : ((Date) iDataModel.getValue(PositionBillConstant.NCKD_EFFDT)).getTime());
+            formShowParameter.setCustomParam(PositionBillConstant.ORG_KEY, iDataModel.getDataEntity().getLong(String.join(".", PositionBillConstant.ORG_KEY, PositionBillConstant.ID_KEY)));
+            formShowParameter.setCustomParam(PositionBillConstant.BILL_STATUS_KEY, iDataModel.getDataEntity().get(PositionBillConstant.BILL_STATUS_KEY));
+            int sequence = getEntrySeq(iFormView.getModel(), PositionChangeTypeEnum.getNumberByTag(tag));
+            formShowParameter.setCustomParam(PositionBillConstant.CP_SEQUENCE, sequence);
+            formShowParameter.setCloseCallBack(new CloseCallBack(pluginName, String.join("_", PositionBillConstant.NCKD_ENTRYENTITY, tag)));
+            formShowParameter.setCustomParam(PositionBillConstant.OP_VALIDATOR_BILL_POSITION_ALL_CHANGE_POSITION_KEY, getThisBillAllValidateDataStr(iDataModel.getDataEntity(true)));
+            formShowParameter.setCustomParam(PositionBillConstant.OP_VALIDATOR_BILL_POSITION_NEW_POSITION_NUMBERS_KEY, getThisBillPositionNumbersStr(iDataModel.getDataEntity(true)));
+            iFormView.showForm(formShowParameter);
+        }
+    }
+
+    public static String getThisBillAllValidateDataStr(DynamicObject bill) {
+        if (bill == null) {
+            return "";
+        } else {
+            DynamicObjectCollection positionEntryDys = new DynamicObjectCollection();
+            positionEntryDys.addAll(bill.getDynamicObjectCollection(PositionBillConstant.NCKD_ENTRYENTITY_ADD_KEY));
+            positionEntryDys.addAll(bill.getDynamicObjectCollection(PositionBillConstant.NCKD_ENTRYENTITY_CHANGE_KEY));
+            PositionBillSaveHelper helper = PositionBillSaveHelper.getInstance();
+            Map<Long, List<String>> positionBoIdToChangeTypeNumberMap = Maps.newHashMapWithExpectedSize(16);
+
+            for(DynamicObject entryDy : positionEntryDys) {
+                String suffix = helper.getSuffixFromEntryEntityDyn(entryDy);
+                String changeTypeNumber = PositionChangeTypeEnum.getNumberByTag(suffix);
+                Long positionBoId = null;
+                if (PositionChangeTypeEnum.ADD.getNumber().equals(changeTypeNumber)) {
+                    positionBoId = helper.getPositionId(entryDy, suffix);
+                } else {
+                    DynamicObject positionDyRef = entryDy.getDynamicObject(helper.spliceTwoStringByUnderLine(suffix, PositionBillConstant.NCKD_POSITION_KEY));
+                    if (positionDyRef != null) {
+                        positionBoId = positionDyRef.getLong(PositionBillConstant.BOID_KEY);
+                    }
+                }
+
+                if (positionBoId != null && positionBoId != 0L) {
+                    List<String> changeTypeNumbers = positionBoIdToChangeTypeNumberMap.get(positionBoId);
+                    if (changeTypeNumbers == null) {
+                        changeTypeNumbers = Lists.newArrayListWithExpectedSize(10);
+                    }
+
+                    changeTypeNumbers.add(changeTypeNumber);
+                    positionBoIdToChangeTypeNumberMap.put(positionBoId, changeTypeNumbers);
+                }
+            }
+
+            return JSONObject.toJSONString(positionBoIdToChangeTypeNumberMap);
+        }
+    }
+
+    public static String getThisBillPositionNumbersStr(DynamicObject bill) {
+        if (bill == null) {
+            return "";
+        } else {
+            DynamicObjectCollection positionNumberEntryDys = new DynamicObjectCollection();
+            positionNumberEntryDys.addAll(bill.getDynamicObjectCollection(PositionBillConstant.NCKD_ENTRYENTITY_ADD_KEY));
+            positionNumberEntryDys.addAll(bill.getDynamicObjectCollection(PositionBillConstant.NCKD_ENTRYENTITY_CHANGE_KEY));
+            PositionBillSaveHelper helper = PositionBillSaveHelper.getInstance();
+            Map<String, List<Long>> newNumberToPositionIdsMap = Maps.newHashMapWithExpectedSize(positionNumberEntryDys.size());
+
+            for(DynamicObject positionEntryDy : positionNumberEntryDys) {
+                String suffix = helper.getSuffixFromEntryEntityDyn(positionEntryDy);
+                long positionId = 0L;
+                String positionNumber = positionEntryDy.getString(helper.spliceTwoStringByUnderLine(suffix, PositionBillConstant.NCKD_NUMBER_KEY));
+                if (PositionBillConstant.NCKD_ENTRYENTITY_ADD_KEY.equals(positionEntryDy.getDynamicObjectType().getName())) {
+                    positionId = positionEntryDy.getLong(helper.spliceTwoStringByUnderLine(suffix, PositionBillConstant.NCKD_POSITION_KEY));
+                } else {
+                    DynamicObject positionDy = positionEntryDy.getDynamicObject(helper.spliceTwoStringByUnderLine(suffix, PositionBillConstant.NCKD_POSITION_KEY));
+                    if (positionDy != null) {
+                        positionId = positionDy.getLong(PositionBillConstant.BOID_KEY);
+                    }
+                }
+
+                if (HRStringUtils.isNotEmpty(positionNumber)) {
+                    List<Long> positionIds = newNumberToPositionIdsMap.computeIfAbsent(positionNumber, (key) -> Lists.newArrayListWithExpectedSize(positionNumberEntryDys.size()));
+                    positionIds.add(positionId);
+                }
+            }
+
+            return JSONObject.toJSONString(newNumberToPositionIdsMap);
+        }
+    }
+
+    public static String getThisBillPositionNamesStr(DynamicObject bill) {
+        if (bill == null) {
+            return "";
+        } else {
+            DynamicObjectCollection positionNumberEntryDys = new DynamicObjectCollection();
+            positionNumberEntryDys.addAll(bill.getDynamicObjectCollection(PositionBillConstant.NCKD_ENTRYENTITY_ADD_KEY));
+            positionNumberEntryDys.addAll(bill.getDynamicObjectCollection(PositionBillConstant.NCKD_ENTRYENTITY_CHANGE_KEY));
+            PositionBillSaveHelper helper = PositionBillSaveHelper.getInstance();
+            Map<String, Map<String, ILocaleString>> adminOrgBoIdToSiblingNameMap = Maps.newHashMapWithExpectedSize(positionNumberEntryDys.size());
+
+            for(DynamicObject positionEntryDy : positionNumberEntryDys) {
+                String suffix = helper.getSuffixFromEntryEntityDyn(positionEntryDy);
+                long positionId = 0L;
+                DynamicObject adminOrgDy = positionEntryDy.getDynamicObject(helper.spliceTwoStringByUnderLine(suffix, PositionBillConstant.NCKD_ADMINORG));
+                if (HRStringUtils.equals(PositionChangeTypeEnum.ADD.getTag(PositionBillConstant.NCKD_ENTRYENTITYUNDERLINE_KEY) , positionEntryDy.getDynamicObjectType().getName())) {
+                    positionId = positionEntryDy.getLong(helper.spliceTwoStringByUnderLine(suffix, PositionBillConstant.NCKD_POSITION_KEY));
+                } else {
+                    DynamicObject positionDy = positionEntryDy.getDynamicObject(helper.spliceTwoStringByUnderLine(suffix, PositionBillConstant.NCKD_POSITION_KEY));
+                    if (positionDy != null) {
+                        positionId = positionDy.getLong(PositionBillConstant.BOID_KEY);
+                    }
+                }
+
+                if (adminOrgDy != null) {
+                    long boId = adminOrgDy.getLong(PositionBillConstant.BOID_KEY);
+                    Map<String, ILocaleString> siblingNameMap = adminOrgBoIdToSiblingNameMap.get(String.valueOf(boId));
+                    if (siblingNameMap == null) {
+                        siblingNameMap = Maps.newHashMapWithExpectedSize(16);
+                    }
+
+                    siblingNameMap.put(String.valueOf(positionId), positionEntryDy.getLocaleString(helper.spliceTwoStringByUnderLine(suffix, PositionBillConstant.NCKD_NAME_KEY)));
+                    adminOrgBoIdToSiblingNameMap.put(String.valueOf(boId), siblingNameMap);
+                }
+            }
+
+            return JSONObject.toJSONString(adminOrgBoIdToSiblingNameMap);
+        }
+    }
+
+    /**
+     * @param operationKey
+     * @param positionDys
+     * @param option
+     * @return
+     */
+    public static OperationResult executeOperateOnlyValidate(String operationKey, DynamicObject[] positionDys, OperateOption option) {
+        OperateOption operateOption = option;
+        if (option == null) {
+            operateOption = OperateOption.create();
+        }
+
+        operateOption.setVariableValue(OperateOptionConst.ISHASRIGHT, Boolean.TRUE.toString());
+        operateOption.setVariableValue(OperateOptionConst.ONLY_VALIDATE, Boolean.TRUE.toString());
+
+        try {
+            return OperationServiceHelper.executeOperate(operationKey, PositionBillConstant.HBPM_POSITIONHR, positionDys, operateOption);
+        } catch (Exception ex) {
+            log.error("executeOperate  error", ex);
+            throw ex;
+        }
+    }
+
+}

+ 29 - 0
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/business/hr/utils/PositionBillUtil.java

@@ -0,0 +1,29 @@
+package nckd.jxccl.hrmp.hbpm.business.hr.utils;
+
+import kd.bos.exception.KDBizException;
+import kd.bos.form.IFormView;
+import nckd.jxccl.hrmp.hbpm.common.hr.PositionBillConstant;
+
+import java.util.Locale;
+import java.util.stream.Stream;
+
+/**
+ * 岗位申请单工具类
+ * @from: kd.hr.homs.business.utils.OrgChgUtil
+ * @author: jtd
+ * @date: 2025/12/30 15:06
+ */
+public class PositionBillUtil {
+
+    public static synchronized IFormView getView(IFormView view, String name) {
+        String msg = String.format(Locale.ROOT, "需要从 %s 页面进入", name);
+        if (view == null) {
+            throw new KDBizException(msg);
+        } else {
+            String pageName = view.getModel().getDataEntityType().getName();
+            Stream<String> pause = Stream.of(name, PositionBillConstant.BOS_LIST_ENTITY);
+            return pause.anyMatch((s) -> s.equals(pageName)) ? view : getView(view.getParentView(), name);
+        }
+    }
+
+}

+ 1 - 1
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/business/hr/PatternUtil.java → code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/common/hr/PatternUtil.java

@@ -1,4 +1,4 @@
-package nckd.jxccl.hrmp.hbpm.business.hr;
+package nckd.jxccl.hrmp.hbpm.common.hr;
 
 import kd.bos.entity.ISVInfo;
 import kd.bos.logging.Log;

+ 124 - 8
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/common/hr/PositionBillConstant.java

@@ -13,8 +13,6 @@ public class PositionBillConstant extends FormConstant {
     public static final String NCKD_HBPM_POSORGTREELISTF_ENTITY = "nckd_hbpm_posorgtreelistf";
     /** 岗位信息键值转换实体标识 */
     public static final String NCKD_POSITION_TRANSKEY_ENTITY = "nckd_position_transkey";
-    /** 行政组织树实体标识 */
-    public static final String HAOS_ORGTREELISTF7_ENTITY = "haos_orgtreelistf7";
     /** 岗位申请单实体标识 */
     public static final String NCKD_POSITIONBILL_ENTITY = "nckd_positionbill";
     /** 岗位申请单分录实体标识 */
@@ -27,6 +25,8 @@ public class PositionBillConstant extends FormConstant {
     public static final String NCKD_PBENTRY_TRANSKEY_ENTITY = "nckd_pbentry_transkey";
     /** 岗位信息排除键值实体标识 */
     public static final String NCKD_POSITION_EXCLUDEKEY_ENTITY = "nckd_position_excludekey";
+    /** 岗位管理_应用首页实体标识 */
+    public static final String NCKD_POSTMGR_APPHOME_ENTITY = "nckd_postmgr_apphome";
 
     /** 新增标识 */
     public static final String ADD_TAG = "add";
@@ -49,6 +49,18 @@ public class PositionBillConstant extends FormConstant {
     public static final String EDIT_ADD_OP = "edit_add";
     /** 编辑-岗位变更OP */
     public static final String EDIT_CHANGE_OP = "edit_change";
+    /** 确认变更OP */
+    public static final String CONFIRMCHANGE_OP = "confirmchange";
+    /** 保存(不记录操作日志)操作标识 */
+    public static final String SAVE_NO_LOG_OP = "save_no_log";
+
+    /** 岗位职责高级面板工具栏标识 */
+    public static final String NCKD_ADVCONTOOLBARAP11_KEY = "nckd_advcontoolbarap11";
+    /** 分录删除按钮标识 */
+    public static final String NCKD_TB_DEL_KEY = "nckd_tb_del";
+    /** 单据信息容器标识 */
+    public static  final String FS_BASEINFO_KEY = "fs_baseinfo";
+
     /** 岗位申请单内码 */
     public static final String NCKD_BILLID = "nckd_billid";
     /** 生效日期 */
@@ -61,20 +73,18 @@ public class PositionBillConstant extends FormConstant {
     public static final String NCKD_SEQUENCE = "nckd_sequence";
     /** 行政组织 */
     public static final String NCKD_ADMINORG = "nckd_adminorg";
-    /** 岗位 */
-    public static final String NCKD_POSITION = "nckd_position";
+    /** 岗位ID */
+    public static final String NCKD_POSITIONID_KEY = "nckd_positionid";
     /** 上级岗位 */
     public static final String NCKD_PARENT = "nckd_parent";
     /** 上级岗位 */
     public static final String PARENT_KEY = "parent";
     /** 组织体系管理组织 */
-    public static final String NCKD_ORG = "nckd_org";
+    public static final String NCKD_ORG_KEY = "nckd_org";
     /** 生效日期 */
     public static final String NCKD_BSED = "nckd_bsed";
-    /** 行政组织业务ID */
+    /** 行政组织业务ID(仅验权使用) */
     public static final String NCKD_ADMINORGBOID_KEY = "nckd_adminorgboid";
-    /** 岗位业务ID */
-    public static final String NCKD_POSITIONBOID_KEY = "nckd_positionboid";
     /** 单据体-新增岗位 */
     public static final String NCKD_ENTRYENTITY_ADD_KEY = "nckd_entryentity_add";
     /** 单据体-变更信息 */
@@ -87,5 +97,111 @@ public class PositionBillConstant extends FormConstant {
     public static final String NCKD_NAME_KEY = "nckd_name";
     /** 签发组织 */
     public static final String NCKD_DISORG_KEY = "nckd_disorg";
+    /** 原上级岗位 */
+    public static final String NCKD_ORIPARENT_KEY = "nckd_oriparent";
+    /** 岗位申请单分录 */
+    public static final String NCKD_POSBILLENTRY_KEY = "nckd_posbillentry";
+    /** 岗位申请单分录 */
+    public static final String NCKD_ENTRYENTITYUNDERLINE_KEY = "nckd_entryentity_";
+
+    /** 岗位生效时间页面自定义参数 */
+    public static final String CP_POSITION_BSED = "position_bsed";
+    /** 查询日期页面自定义参数 */
+    public static final String CP_SEARCHDATE = "searchdate";
+    /** 单据ID页面自定义参数 */
+    public static final String CP_BILLID = "billid";
+    /** 选中数据页面自定义参数 */
+    public static final String CP_SELECTOBJECT = "selectObject";
+    /** 单据生效时间页面自定义参数 */
+    public static final String CP_BILLBSED = "billBsed";
+    /** 分录顺序号页面自定义参数 */
+    public static final String CP_SEQUENCE = "sequence";
+    /** 岗位ID页面自定义参数 */
+    public static final String CP_POSITIONID = "positionId";
+    /** 来自列表页面自定义参数 */
+    public static final String CP_FROMLIST = "fromList";
+    /** 业务单元页面自定义参数 */
+    public static final String CP_BUSINESSUNIT = "businessUnit";
+    /** 是否来自单据列表点击页面自定义参数 */
+    public static final String CP_ISFROMBILLCLICK = "isFromBillClick";
+    /** 上级岗位ID页面自定义参数 */
+    public static final String CP_PARENTID = "parentId";
+
+    /** 新增岗位上级变更页面缓存参数 */
+    public static final String PC_ADDPOSITIONPARENTCHANGE = "addPositionParentChange";
+    /** 上级ID页面缓存参数 */
+    public static final String PC_PARENTID = "parentId";
+    /** 保存结果页面缓存参数 */
+    public static final String PC_SAVERESULT = "saveResult";
+    /** 是否关闭页面缓存参数 */
+    public static final String PC_ISCLOSE = "isclose";
+    /** 变更前上级岗位ID页面缓存参数 */
+    public static final String PC_BEFOREPARENTPOSITIONID = "beforeParentPositionId";
+    /** 编码规则编码页面缓存参数 */
+    public static final String PC_CODERULENUMBER = "codeRuleNumber";
+    /** 数据变更重置编码页面缓存参数 */
+    public static final String PC_PARAMSCHANGESETNUMBER = "paramsChangeSetNumber";
+    /** 初始化标识页面缓存参数 */
+    public static final String PC_INITFLAG = "initFlag";
+    /** 主业务组织页面缓存参数 */
+    public static final String PC_MASTERORG = "masterOrg";
+    /** 不可修改页面缓存参数 */
+    public static final String PC_NOTMODIFIABLE = "notModifiable";
+    /** 是否初始化页面缓存参数 */
+    public static final String PC_ISINIT = "isInit";
+    /** 变更前岗位ID页面缓存参数 */
+    public static final String PC_POSITIONOLD = "positionOld";
+    /** 岗位变更行页面缓存参数 */
+    public static final String PC_POSITIONROW = "positionRow";
+    /** 分录岗位信息页面缓存参数 */
+    public static final String PC_ENTRY_ORG_VALUE = "entry_position_value";
+    /** 是否变更岗位页面缓存参数 */
+    public static final String PC_ISCHANGEPOSITION = "isChangePosition";
+    /** 是否关闭完成页面缓存参数 */
+    public static final String PC_ISCANCELOVER = "isCancelOver";
+    /** 是否列表页面缓存参数 */
+    public static final String PC_ISLIST = "isList";
+    /** 是否来自导入页面缓存参数 */
+    public static final String PC_ISFROMIMPORT = "isFromImport";
+    /** 是否来自应用首页页面缓存参数 */
+    public static final String PC_ISFROMHOMEPAGE = "isFromHomePage";
+    /** 导入开始/结束页面缓存参数 */
+    public static final String PC_CACHE_KEY_IMPORT_START_CLOSE = "CACHE_KEY_IMPORT_START_CLOSE";
+    /** 导入数据标识页面缓存参数 */
+    public static final String PC_CACHE_KEY_IMPORT_DATA_FLAG = "CACHE_KEY_IMPORT_DATA_FLAG";
+    /** 组织体系管理组织页面缓存参数 */
+    public static final String PC_ORGCACHE = "orgCache";
+    /** 是否来自单据点击页面缓存参数 */
+    public static final String PC_ISFROMBILLCLICK = "isFromBillClick";
+    /** 业务单元页面缓存参数 */
+    public static final String PC_BUSINESSUNIT = "businessUnit";
+    /** 最近一次新增岗位的数据ID */
+    public static final String PC_LASTTIMEADDENTRYID = "lastTimeAddEntryId";
+
+    /** 变更组织体系管理组织回调标识 */
+    public static final String CB_CHG_ORG = "chg_org";
+    /** 选中岗位数据回调标识 */
+    public static final String CB_SELECT_POSITION = "select_position_";
+    /** 关闭页面回调标识 */
+    public static final String CB_CLOSE_BILL = "close_bill";
+    /** 删除分录回调标识 */
+    public static final String CB_DEL_ROW = "del_row";
+
+    /** 岗位申请单同级岗位名称OP参数 */
+    public static final String OP_BILL_SIBLING_NAMES_MAP = "OP_BILL_SIBLING_NAMES_MAP";
+    /** 岗位申请单岗位编码OP参数 */
+    public static final String OP_BILL_NUMBER_MAP = "OP_BILL_NUMBER_MAP";
+    /** 所有岗位信息OP参数 */
+    public static final String OP_VALIDATOR_BILL_POSITION_ALL_CHANGE_POSITION_KEY = "OP_VALIDATOR_BILL_POSITION_ALL_CHANGE_POSITION_KEY";
+    /** 岗位申请单所有岗位编码OP参数 */
+    public static final String OP_VALIDATOR_BILL_POSITION_NEW_POSITION_NUMBERS_KEY = "OP_VALIDATOR_BILL_POSITION_NEW_POSITION_NUMBERS_KEY";
+    /** 操作标识OP参数 */
+    public static final String OP_OPERATE_KEY = "OP_OPERATE_KEY";
+    /** 删除行数据OP参数 */
+    public static final String OP_ROW_INDEX = "OP_ROW_INDEX";
+    /** 校验数据(忽略后缀) */
+    public static final String OP_VALIDATOR_SUFFIX_IGNORE = "OP_VALIDATOR_SUFFIX_IGNORE";
+    /** 跳过必录校验OP参数 */
+    public static final String OP_SKIPMUSTINPUT = "SkipMustInput";
 
 }

+ 42 - 10
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/common/hr/PositionChangeTypeEnum.java

@@ -25,26 +25,54 @@ public enum PositionChangeTypeEnum {
 
     public static String getNumberByTag(String tag) {
         if (tag == null) {
-            return null;
+            return "";
         }
-        for (PositionChangeTypeEnum value : values()) {
-            if (HRStringUtils.equals(value.getTag(), tag)) {
-                return value.getNumber();
+        for (PositionChangeTypeEnum changeTypeEnum : values()) {
+            if (HRStringUtils.equals(changeTypeEnum.getTag(), tag)) {
+                return changeTypeEnum.getNumber();
             }
         }
-        return null;
+        return "";
+    }
+
+    public static String getTagByNumber(String number) {
+        return getTagByNumber("", number);
+    }
+
+    public static String getTagByNumber(String prefix, String number) {
+        if (number == null) {
+            return "";
+        }
+        for (PositionChangeTypeEnum changeTypeEnum : values()) {
+            if (HRStringUtils.equals(changeTypeEnum.getNumber(), number)) {
+                return prefix + changeTypeEnum.getTag();
+            }
+        }
+        return "";
+    }
+
+    public static String getTipByNumber(String number) {
+        if (number == null) {
+            return "";
+        }
+        for (PositionChangeTypeEnum changeTypeEnum : values()) {
+            if (HRStringUtils.equals(changeTypeEnum.getNumber(), number)) {
+                return changeTypeEnum.getTip();
+            }
+        }
+        return "";
     }
 
     public static String getTipByTag(String tag) {
         if (tag == null) {
-            return null;
+            return "";
         }
-        for (PositionChangeTypeEnum value : values()) {
-            if (HRStringUtils.equals(value.getTag(), tag)) {
-                return value.getTip();
+        for (PositionChangeTypeEnum changeTypeEnum : values()) {
+            if (HRStringUtils.equals(changeTypeEnum.getTag(), tag)) {
+                return changeTypeEnum.getTip();
             }
         }
-        return null;
+        return "";
     }
 
     public String getNumber() {
@@ -59,6 +87,10 @@ public enum PositionChangeTypeEnum {
         return tag;
     }
 
+    public String getTag(String prefix) {
+        return prefix+tag;
+    }
+
     public String getTip() {
         return tip;
     }

+ 0 - 38
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/form/hr/ParentPositionListPlugin.java

@@ -1,38 +0,0 @@
-package nckd.jxccl.hrmp.hbpm.plugin.form.hr;
-
-import kd.bos.form.control.SplitContainer;
-import kd.bos.form.control.SplitDirection;
-import kd.bos.form.events.PreOpenFormEventArgs;
-import kd.bos.list.plugin.AbstractListPlugin;
-
-import java.util.EventObject;
-import java.util.Map;
-
-
-/**
- * 上级岗位列表插件
- * @author: jtd
- * @date: 2025-10-24 10:24
- */
-public class ParentPositionListPlugin extends AbstractListPlugin {
-
-    @Override
-    public void preOpenForm(PreOpenFormEventArgs e) {
-        super.preOpenForm(e);
-
-        // 指定显示岗位数据
-        Map<String, Object> customParams = e.getFormShowParameter().getCustomParams();
-        customParams.put("showBasedata", "0");
-    }
-
-    @Override
-    public void beforeBindData(EventObject e) {
-        super.beforeBindData(e);
-
-        // 默认隐藏左树
-        SplitContainer splitContainer = (SplitContainer)this.getView().getControl("splitcontainerap");
-        if (splitContainer != null) {
-            splitContainer.hidePanel(SplitDirection.left, true);
-        }
-    }
-}

+ 153 - 76
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/form/hr/PosBillEntryAddFormPlugin.java

@@ -28,8 +28,9 @@ import kd.bos.servicehelper.coderule.CodeRuleServiceHelper;
 import kd.hr.hbp.business.servicehelper.HRBaseServiceHelper;
 import kd.hr.hbp.common.util.HRObjectUtils;
 import kd.hr.hbp.common.util.HRStringUtils;
-import kd.hr.homs.business.utils.PatternUtil;
-import nckd.jxccl.hrmp.hbpm.business.hr.PositionBillServiceHelper;
+import nckd.jxccl.hrmp.hbpm.common.hr.PatternUtil;
+import nckd.jxccl.hrmp.hbpm.business.hr.service.impl.PosBillEntryFastChgHelper;
+import nckd.jxccl.hrmp.hbpm.business.hr.service.impl.PositionBillServiceHelper;
 import nckd.jxccl.hrmp.hbpm.common.hr.PositionBillConstant;
 
 import java.util.ArrayList;
@@ -41,37 +42,32 @@ import java.util.Map;
 import java.util.stream.Stream;
 
 /**
- * 岗位申请-新增岗位表单插件
+ * 岗位申请-岗位新设表单插件
+ * @from: kd.hr.homs.formplugin.web.orgbatch.AdminOrgBatchDetailAddPlugin
  * @author: jtd
  * @date: 2025-11-05 15:32
  */
 public class PosBillEntryAddFormPlugin extends AbstractFormPlugin {
 
-    /**
-     * 编码规则的编码
-     */
-    private static final String CODERULE_NUMBER = "codeRuleNumber";
-
-    /**
-     * 保存结果标识
-     */
-    private static final String SAVE_RESULT = "saveResult";
-
     @Override
     public void beforeBindData(EventObject e) {
         super.beforeBindData(e);
 
-        getPageCache().put("paramsChangeSetNumber", "false");
+        getPageCache().put(PositionBillConstant.PC_PARAMSCHANGESETNUMBER, Boolean.FALSE.toString());
         DynamicObject positionDy = getModel().getDataEntity();
         long entityId = positionDy.getLong(PositionBillConstant.ID_KEY);
         if (entityId == 0L) {
-            Long billId = getView().getFormShowParameter().getCustomParam("billid");
+            Long billId = getView().getFormShowParameter().getCustomParam(PositionBillConstant.CP_BILLID);
             getModel().setValue(PositionBillConstant.NCKD_BILLID, billId);
-            getPageCache().put("initFlag", Boolean.TRUE.toString());
+            getPageCache().put(PositionBillConstant.PC_INITFLAG, Boolean.TRUE.toString());
+        }
+
+        if (!HRStringUtils.isEmpty(getView().getFormShowParameter().getCustomParam(PositionBillConstant.CP_PARENTID))) {
+            getModel().setValue(PositionBillConstant.NCKD_PARENT, Long.valueOf(getView().getFormShowParameter().getCustomParam(PositionBillConstant.CP_PARENTID)));
         }
 
         // 设置生效时间
-        Object positionBsedStr = getView().getFormShowParameter().getCustomParam("position_bsed");
+        Object positionBsedStr = getView().getFormShowParameter().getCustomParam(PositionBillConstant.CP_POSITION_BSED);
         if (positionBsedStr != null) {
             long positionBsedTime = Long.parseLong(positionBsedStr.toString());
             getModel().setValue(PositionBillConstant.NCKD_BSED, new Date(positionBsedTime));
@@ -80,6 +76,7 @@ public class PosBillEntryAddFormPlugin extends AbstractFormPlugin {
         }
 
         getModel().setValue(PositionBillConstant.ENABLE, EnableEnum.YES.getCode());
+        setLastTimeAddPositionInfo();
         // 设置岗位编码
         if (HRStringUtils.isEmpty(getModel().getDataEntity().getString(PositionBillConstant.NUMBER_KEY))) {
             setPositionNumber(PositionBillServiceHelper.getPositionHrDy(getModel().getDataEntity()), true);
@@ -87,20 +84,20 @@ public class PosBillEntryAddFormPlugin extends AbstractFormPlugin {
             setPositionNumberEnable();
         }
 
-        getPageCache().put("paramsChangeSetNumber", "true");
+        getPageCache().put(PositionBillConstant.PC_PARAMSCHANGESETNUMBER, Boolean.TRUE.toString());
         // 新增的时候生成岗位ID
-        String positionIdKey = String.join("_", PositionBillConstant.NCKD_POSITION, PositionBillConstant.ID_KEY);
+        String positionIdKey = String.join("_", PositionBillConstant.NCKD_POSITION_KEY, PositionBillConstant.ID_KEY);
         long positionId = getModel().getDataEntity().getLong(positionIdKey);
         if (positionId == 0L) {
             positionId = ORM.create().genLongId(PositionBillConstant.HBPM_POSITIONHR);
             getModel().setValue(positionIdKey, positionId);
         }
 
-        getPageCache().put("masterOrg", String.valueOf(positionDy.getLong(String.join(".", PositionBillConstant.NCKD_ORG, PositionBillConstant.ID_KEY))));
+        getPageCache().put(PositionBillConstant.PC_MASTERORG, String.valueOf(positionDy.getLong(String.join(".", PositionBillConstant.NCKD_ORG_KEY, PositionBillConstant.ID_KEY))));
     }
 
     private void setPositionNumberEnable() {
-        DynamicObject org = getModel().getDataEntity().getDynamicObject(PositionBillConstant.NCKD_ORG);
+        DynamicObject org = getModel().getDataEntity().getDynamicObject(PositionBillConstant.NCKD_ORG_KEY);
         if (org == null) {
             getView().setEnable(Boolean.valueOf(false), PositionBillConstant.NUMBER_KEY);
             return;
@@ -112,23 +109,23 @@ public class PosBillEntryAddFormPlugin extends AbstractFormPlugin {
             getView().setEnable(false, PositionBillConstant.NUMBER_KEY);
             String orgNumber = getModel().getDataEntity().getString(PositionBillConstant.NUMBER_KEY);
             if (HRStringUtils.isNotEmpty(orgNumber)) {
-                getView().getPageCache().put("codeRuleNumber", orgNumber);
-                getView().getPageCache().put("notModifiable", Boolean.TRUE.toString());
+                getView().getPageCache().put(PositionBillConstant.PC_CODERULENUMBER, orgNumber);
+                getView().getPageCache().put(PositionBillConstant.PC_NOTMODIFIABLE, Boolean.TRUE.toString());
             }
         }
     }
 
     private void setPositionNumber(DynamicObject positionHrDy, Boolean init) {
-        DynamicObject dataEntity = getModel().getDataEntity();// 157
+        DynamicObject dataEntity = getModel().getDataEntity();
         // 组织体系管理组织
-        DynamicObject org = dataEntity.getDynamicObject(PositionBillConstant.NCKD_ORG);
+        DynamicObject org = dataEntity.getDynamicObject(PositionBillConstant.NCKD_ORG_KEY);
         if (org == null) {
             getView().setEnable(Boolean.FALSE, PositionBillConstant.NUMBER_KEY);
             return;
         }
 
         String number = dataEntity.getString(PositionBillConstant.NUMBER_KEY);
-        if (HRStringUtils.isNotEmpty(number) && !HRStringUtils.equals(number, getView().getPageCache().get("codeRuleNumber"))) {
+        if (HRStringUtils.isNotEmpty(number) && !HRStringUtils.equals(number, getView().getPageCache().get(PositionBillConstant.PC_CODERULENUMBER))) {
             return;
         }
 
@@ -143,7 +140,7 @@ public class PosBillEntryAddFormPlugin extends AbstractFormPlugin {
                 QFilter qFilter = new QFilter(PositionBillConstant.NUMBER_KEY, QCP.equals, positionNumber);
                 if (!hrBaseServiceHelper.isExists(qFilter)) {
                     getModel().setValue(PositionBillConstant.NUMBER_KEY, positionNumber);
-                    getView().getPageCache().put("codeRuleNumber", positionNumber);
+                    getView().getPageCache().put(PositionBillConstant.PC_CODERULENUMBER, positionNumber);
                 } else {
                     setPositionNumber(positionHrDy, init);
                 }
@@ -152,7 +149,7 @@ public class PosBillEntryAddFormPlugin extends AbstractFormPlugin {
             }
         } else {
             getModel().setValue(PositionBillConstant.NUMBER_KEY, null);
-            getView().getPageCache().put("codeRuleNumber", "");
+            getView().getPageCache().put(PositionBillConstant.PC_CODERULENUMBER, "");
             getView().setEnable(Boolean.TRUE, PositionBillConstant.NUMBER_KEY);
         }
     }
@@ -161,10 +158,10 @@ public class PosBillEntryAddFormPlugin extends AbstractFormPlugin {
     public void beforeClosed(BeforeClosedEvent event) {
         super.beforeClosed(event);
 
-        String isCancelOverFlag = getView().getPageCache().get("isclose");
+        String isCancelOverFlag = getView().getPageCache().get(PositionBillConstant.PC_ISCLOSE);
         if (HRStringUtils.isNotEmpty(isCancelOverFlag) && Boolean.TRUE.toString().equals(isCancelOverFlag)) {
             getModel().setDataChanged(false);
-            getView().getPageCache().put("isclose", Boolean.FALSE.toString());
+            getView().getPageCache().put(PositionBillConstant.PC_ISCLOSE, Boolean.FALSE.toString());
         } else {
             boolean dataChanged = getModel().getDataChanged();
             if (dataChanged) {
@@ -177,15 +174,15 @@ public class PosBillEntryAddFormPlugin extends AbstractFormPlugin {
                 String msg = "检测到您有更改内容,是否不保存直接退出?若不保存,将丢失这些更改。";
                 getView().showConfirm(msg, getModel().getChangeDesc(), options, ConfirmTypes.Save, confirmCallBacks, btnNameMaps);
             } else {
-                String codeRuleNumber = getView().getPageCache().get("codeRuleNumber");
-                String notModifiable = getView().getPageCache().get("notModifiable");
+                String codeRuleNumber = getView().getPageCache().get(PositionBillConstant.PC_CODERULENUMBER);
+                String notModifiable = getView().getPageCache().get(PositionBillConstant.PC_NOTMODIFIABLE);
                 if (!StringUtils.isEmpty(codeRuleNumber) && !Boolean.TRUE.toString().equals(notModifiable)) {
-                    DynamicObject org = getModel().getDataEntity().getDynamicObject(PositionBillConstant.NCKD_ORG);
+                    DynamicObject org = getModel().getDataEntity().getDynamicObject(PositionBillConstant.NCKD_ORG_KEY);
                     if (org == null) {
                         return;
                     }
 
-                    String saveResult = getView().getPageCache().get("saveResult");
+                    String saveResult = getView().getPageCache().get(PositionBillConstant.PC_SAVERESULT);
                     if (!Boolean.TRUE.toString().equals(saveResult)) {
                         long orgId = org.getLong(PositionBillConstant.ID_KEY);
                         DynamicObject positionHrDy = PositionBillServiceHelper.getPositionHrDy(getModel().getDataEntity());
@@ -210,31 +207,33 @@ public class PosBillEntryAddFormPlugin extends AbstractFormPlugin {
         // 设置上级岗位变更前的数据到页面缓存中
         DynamicObject parentPosition = getModel().getDataEntity().getDynamicObject(PositionBillConstant.NCKD_PARENT);
         if (parentPosition != null) {
-            getView().getPageCache().put("beforeParentPositionId", parentPosition.getString(PositionBillConstant.ID_KEY));
+            getView().getPageCache().put(PositionBillConstant.PC_BEFOREPARENTPOSITIONID, parentPosition.getString(PositionBillConstant.ID_KEY));
         }
 
-        Object selectObject = getView().getFormShowParameter().getCustomParam("selectObject");
+        Object selectObject = getView().getFormShowParameter().getCustomParam(PositionBillConstant.CP_SELECTOBJECT);
         if (selectObject != null) {
+            String lineSuffix = "_"+PositionBillConstant.ADD_TAG;
             Map<String, Object> map = SerializationUtils.fromJsonString(selectObject.toString(), Map.class);
-            Map<String, Object> noPrefixMap = map.entrySet().stream().collect(HashMap::new, (m, v) -> m.put((v.getKey()).replace("_"+PositionBillConstant.ADD_TAG, ""), v.getValue()), HashMap::putAll);
+            Map<String, Object> noSuffixMap = map.entrySet().stream().collect(HashMap::new, (m, v) -> m.put(PositionBillServiceHelper.getNoLineSuffixProp(v.getKey(), lineSuffix), v.getValue()), HashMap::putAll);
             List<String> props = new ArrayList();
 
-            for(String prop : noPrefixMap.keySet()) {
+            for(String prop : noSuffixMap.keySet()) {
                 if (PatternUtil.isExProperty(prop)) {
                     props.add(prop);
                 }
             }
 
-            // 获取分录要转换的键值,将单据分录字段转换转成分录页面字段
+            // 获取分录要转换的键值,将单据分录字段转换转成分录页面字段
             Map<String, String> transKeyMap = PositionBillServiceHelper.getPosBillEntryTransKeyMap();
             transKeyMap.forEach((key, value) -> {
-                noPrefixMap.put(value, noPrefixMap.get(key));
-                noPrefixMap.remove(key);
+                noSuffixMap.put(value, noSuffixMap.get(key));
+                noSuffixMap.remove(key);
+                props.add(value);
                 props.remove(key);
             });
 
             Stream<String> fields = Stream.of(props.toArray(new String[0]));
-            fields.forEach((s) -> setValue(s, noPrefixMap.get(s)));
+            fields.forEach((s) -> setValue(s, noSuffixMap.get(s)));
         }
 
         // 取消数据标哥标识
@@ -248,20 +247,20 @@ public class PosBillEntryAddFormPlugin extends AbstractFormPlugin {
             if (value != null) {
                 if (propertyType.equals(DynamicObject.class) && dynamicProperty instanceof BasedataProp) {
                     // 岗位特殊处理
-                    Object id = PositionBillConstant.NCKD_POSITION.equals(key) ? value : ((Map)value).get(PositionBillConstant.ID_KEY);
+                    Object id = PositionBillConstant.NCKD_POSITION_KEY.equals(key) ? value : ((Map) value).get(PositionBillConstant.ID_KEY);
                     if (id != null && !HRStringUtils.equals(value.toString(), "0")) {
                         getModel().setValue(key, id);
                     }
                 } else if (propertyType.equals(DynamicObject.class) && dynamicProperty instanceof MulBasedataProp && value instanceof List) {
                     MulBasedataProp property = (MulBasedataProp) getModel().getDataEntityType().getProperty(key);
                     DynamicObjectCollection dynamicObjectCollection = new DynamicObjectCollection();
-                        HRBaseServiceHelper serviceHelper = new HRBaseServiceHelper(property.getBaseEntityId());
-                    ((List)value).forEach((map) -> {
+                    HRBaseServiceHelper serviceHelper = new HRBaseServiceHelper(property.getBaseEntityId());
+                    ((List) value).forEach((map) -> {
                         DynamicObject dy = new DynamicObject(property.getDynamicCollectionItemPropertyType());
-                        dy.set("fbasedataid_id", ((Map)map).get("fbasedataid_id"));
+                        dy.set(PositionBillConstant.FBASEDATAID_ID_KEY, ((Map) map).get(PositionBillConstant.FBASEDATAID_ID_KEY));
                         DynamicObject emptyDynamicObject = serviceHelper.generateEmptyDynamicObject();
-                        emptyDynamicObject.set(PositionBillConstant.ID_KEY, ((Map)map).get("fbasedataid_id"));
-                        dy.set("fbasedataid", emptyDynamicObject);
+                        emptyDynamicObject.set(PositionBillConstant.ID_KEY, ((Map) map).get(PositionBillConstant.FBASEDATAID_ID_KEY));
+                        dy.set(PositionBillConstant.FBASEDATAID_KEY, emptyDynamicObject);
                         dynamicObjectCollection.add(dy);
                     });
                     getModel().setValue(key, !dynamicObjectCollection.isEmpty() ? dynamicObjectCollection : null);
@@ -276,9 +275,21 @@ public class PosBillEntryAddFormPlugin extends AbstractFormPlugin {
     @Override
     public void propertyChanged(PropertyChangedArgs changedArgs) {
         String fieldKey = changedArgs.getProperty().getName();
-        if (PositionBillConstant.NCKD_ESTDATE.equals(fieldKey)) {
-            setEstablishmentDateToBsed((Date)changedArgs.getChangeSet()[0].getNewValue());
+        boolean isGetNumber = true;
+        switch (fieldKey) {
+            case PositionBillConstant.NCKD_ESTDATE:
+                setEstablishmentDateToBsed((Date)changedArgs.getChangeSet()[0].getNewValue());
+                break;
+            case PositionBillConstant.NCKD_POSITION_KEY:
+                break;
+            case PositionBillConstant.NCKD_ORG_KEY:
+                PosBillEntryFastChgHelper.orgPropertyChanged(changedArgs, getView(), this);
+        }
+
+        if (HRStringUtils.equals(Boolean.TRUE.toString(), getPageCache().get(PositionBillConstant.PC_PARAMSCHANGESETNUMBER)) && isGetNumber) {
+            propertyChangedGetNumber(fieldKey, changedArgs.getChangeSet()[0].getOldValue());
         }
+
     }
 
     /**
@@ -288,8 +299,8 @@ public class PosBillEntryAddFormPlugin extends AbstractFormPlugin {
     private void setEstablishmentDateToBsed(Date date) {
         if (date != null) {
             getModel().setValue(PositionBillConstant.NCKD_BSED, date);
-            DynamicProperty property = this.getModel().getDataEntityType().getProperty(PositionBillConstant.NCKD_BSED);
-            DataEntityState dataEntityState = this.getModel().getDataEntity().getDataEntityState();
+            DynamicProperty property = getModel().getDataEntityType().getProperty(PositionBillConstant.NCKD_BSED);
+            DataEntityState dataEntityState = getModel().getDataEntity().getDataEntityState();
             dataEntityState.setBizChanged(property.getOrdinal(), false);
         }
     }
@@ -299,9 +310,35 @@ public class PosBillEntryAddFormPlugin extends AbstractFormPlugin {
         super.confirmCallBack(event);
 
         if (String.join("_", PositionBillConstant.CLOSE_OP, PositionBillConstant.ADD_TAG).equals(event.getCallBackId()) && event.getResult() != MessageBoxResult.Cancel) {
-            recycleNumber();
-            getView().getPageCache().put("isclose", Boolean.TRUE.toString());
+            String codeRuleNumber = getView().getPageCache().get(PositionBillConstant.PC_CODERULENUMBER);
+            if (!StringUtils.isEmpty(codeRuleNumber)) {
+                DynamicObject org = getModel().getDataEntity().getDynamicObject(PositionBillConstant.NCKD_ORG_KEY);
+                if (HRObjectUtils.isEmpty(org)) {
+                    return;
+                }
+                String saveResult = getView().getPageCache().get(PositionBillConstant.PC_SAVERESULT);
+                if (!Boolean.TRUE.toString().equals(saveResult)) {
+                    long orgId = org.getLong(PositionBillConstant.ID_KEY);
+                    DynamicObject positionHrDy = PositionBillServiceHelper.getPositionHrDy(getModel().getDataEntity());
+                    CodeRuleServiceHelper.recycleNumber(PositionBillConstant.HBPM_POSITIONHR, positionHrDy, String.valueOf(orgId), codeRuleNumber);
+                }
+            }
+
+            getView().getPageCache().put(PositionBillConstant.PC_ISCLOSE, Boolean.TRUE.toString());
             getView().invokeOperation(PositionBillConstant.CLOSE_OP);
+        } else if (PositionBillConstant.CB_CHG_ORG.equals(event.getCallBackId())) {
+            if (event.getResult().getValue() == MessageBoxResult.Yes.getValue()) {
+                getView().getPageCache().put(PositionBillConstant.PC_MASTERORG, String.valueOf(getModel().getDataEntity().getLong(String.join(".", PositionBillConstant.NCKD_ORG_KEY, PositionBillConstant.ID_KEY))));
+                getModel().beginInit();
+                PosBillEntryFastChgHelper.cleanOrgBaseInfo(getModel().getDataEntity().getLong(String.join(".", PositionBillConstant.NCKD_ORG_KEY, PositionBillConstant.ID_KEY)), getView());
+                getModel().endInit();
+            } else {
+                Long masterOrgId = Long.valueOf(getPageCache().get(PositionBillConstant.PC_MASTERORG));
+                getModel().beginInit();
+                getModel().setValue(PositionBillConstant.NCKD_ORG_KEY, masterOrgId.equals(0L) ? null : masterOrgId);
+                getView().updateView(PositionBillConstant.NCKD_ORG_KEY);
+                getModel().endInit();
+            }
         }
     }
 
@@ -314,8 +351,8 @@ public class PosBillEntryAddFormPlugin extends AbstractFormPlugin {
         }
         IPageCache parentPageCache = getView().getParentView().getPageCache();
         String operateKey = eventArgs.getOperateKey();
-        if (HRStringUtils.equals(operateKey, PositionBillConstant.SAVE_AND_NEW_OP) || HRStringUtils.equals(operateKey, PositionBillConstant.SAVE_OP)) {
-            String beforeParentPositionId = getView().getPageCache().get("beforeParentPositionId");
+        if (HRStringUtils.equalsAny(operateKey, PositionBillConstant.SAVE_AND_NEW_OP, PositionBillConstant.SAVE_OP)) {
+            String beforeParentPositionId = getView().getPageCache().get(PositionBillConstant.PC_BEFOREPARENTPOSITIONID);
             String addPositionParentChange = Boolean.FALSE.toString();
             DynamicObject parentPosition = getModel().getDataEntity().getDynamicObject(PositionBillConstant.NCKD_PARENT);
             if (parentPosition != null) {
@@ -323,35 +360,75 @@ public class PosBillEntryAddFormPlugin extends AbstractFormPlugin {
                 if (!HRStringUtils.equals(beforeParentPositionId, afterParentPositionId)) {
                     addPositionParentChange = Boolean.TRUE.toString();
                 }
-                parentPageCache.put("addPositionParentChange", addPositionParentChange);
-                parentPageCache.put("parentId", afterParentPositionId);
+                parentPageCache.put(PositionBillConstant.PC_ADDPOSITIONPARENTCHANGE, addPositionParentChange);
+                parentPageCache.put(PositionBillConstant.PC_PARENTID, afterParentPositionId);
             }
             Map<String, String> map = new HashMap<>();
             DynamicObject dataEntity = getModel().getDataEntity();
-            map.put("positionId", dataEntity.getString(String.join("_", PositionBillConstant.NCKD_POSITION, PositionBillConstant.ID_KEY)));
-            map.put("name", dataEntity.getString(PositionBillConstant.NAME_KEY));
-            map.put("id", dataEntity.getString(PositionBillConstant.ID_KEY));
-            getView().getPageCache().put("saveResult", Boolean.TRUE.toString());
+            map.put(PositionBillConstant.CP_POSITIONID, dataEntity.getString(String.join("_", PositionBillConstant.NCKD_POSITION_KEY, PositionBillConstant.ID_KEY)));
+            map.put(PositionBillConstant.NAME_KEY, dataEntity.getString(PositionBillConstant.NAME_KEY));
+            map.put(PositionBillConstant.ID_KEY, dataEntity.getString(PositionBillConstant.ID_KEY));
+            getView().getPageCache().put(PositionBillConstant.PC_SAVERESULT, Boolean.TRUE.toString());
             getView().returnDataToParent(map);
         }
+
+        if (HRStringUtils.equals(operateKey, PositionBillConstant.SAVE_AND_NEW_OP)) {
+            parentPageCache.put(PositionBillConstant.PC_LASTTIMEADDENTRYID, String.valueOf(getModel().getDataEntity().getLong(PositionBillConstant.ID_KEY)));
+        }
     }
 
-    private void recycleNumber() {
-        String codeRuleNumber = getView().getPageCache().get(CODERULE_NUMBER);
-        if (!StringUtils.isEmpty(codeRuleNumber)) {
-            DynamicObject org = getModel().getDataEntity().getDynamicObject(PositionBillConstant.NCKD_ORG);
-            if (HRObjectUtils.isEmpty(org)) {
-                return;
-            }
-            String saveResult = getView().getPageCache().get(SAVE_RESULT);
-            if (!Boolean.TRUE.toString().equals(saveResult)) {
-                long orgId = org.getLong(PositionBillConstant.ID_KEY);
-                DynamicObject positionHrDy = PositionBillServiceHelper.getPositionHrDy(getModel().getDataEntity());
-                CodeRuleServiceHelper.recycleNumber(PositionBillConstant.HBPM_POSITIONHR, positionHrDy, String.valueOf(orgId), codeRuleNumber);
+    private void setLastTimeAddPositionInfo() {
+        String positionIdStr = getView().getParentView().getPageCache().get(PositionBillConstant.PC_LASTTIMEADDENTRYID);
+        if (!HRStringUtils.isEmpty(positionIdStr)) {
+            Long lastTimeAddEntryId = Long.valueOf(positionIdStr);
+            /*HRBaseServiceHelper billHelper = new HRBaseServiceHelper(PositionBillConstant.NCKD_POSITIONBILLENTRY_ENTITY);
+            DynamicObject addPositionDy = billHelper.queryOne("", lastTimeAddEntryId);
+            if (addPositionDy != null) {
+                getModel().setValue();
+            }*/
+
+            getView().getParentView().getPageCache().remove(PositionBillConstant.PC_LASTTIMEADDENTRYID);
+        }
+    }
+
+    private void propertyChangedGetNumber(String fieldKey, Object oldValue) {
+        switch (fieldKey) {
+            case PositionBillConstant.NCKD_POSITION_KEY:
+                String codeRuleNumber = getView().getPageCache().get(PositionBillConstant.PC_CODERULENUMBER);
+                if (!StringUtils.isEmpty(codeRuleNumber)) {
+                    DynamicObject org = getModel().getDataEntity().getDynamicObject(PositionBillConstant.NCKD_ORG_KEY);
+                    if (org == null) {
+                        return;
+                    }
+
+                    long orgId = org.getLong(PositionBillConstant.ID_KEY);
+                    recycleNumber(orgId, codeRuleNumber, Boolean.TRUE, fieldKey, oldValue);
+                }
+
+                setPositionNumber(PositionBillServiceHelper.getPositionHrDy(getModel().getDataEntity()), false);
+            default:
+        }
+    }
+
+
+    private void recycleNumber(Long orgId, String codeRuleNumber, Boolean paramsChg, String numberParams, Object numberParamsOb) {
+        DynamicObject positionHrDy = PositionBillServiceHelper.getPositionHrDy(getModel().getDataEntity());
+        if (paramsChg) {
+            if (positionHrDy.get(numberParams) instanceof DynamicObject && numberParamsOb instanceof Long) {
+                String baseName = positionHrDy.getDynamicObject(numberParams).getDataEntityType().getName();
+                HRBaseServiceHelper hrBaseServiceHelper = new HRBaseServiceHelper(baseName);
+                DynamicObject paramDy = hrBaseServiceHelper.loadSingle(numberParamsOb);
+                positionHrDy.set(numberParams, paramDy);
+            } else {
+                positionHrDy.set(numberParams, numberParamsOb);
             }
         }
-        getView().getPageCache().put("isclose", Boolean.TRUE.toString());
-        getView().invokeOperation(PositionBillConstant.CLOSE_OP);
+
+        String number = getModel().getDataEntity().getString(PositionBillConstant.NUMBER_KEY);
+        if (HRStringUtils.equals(number, codeRuleNumber)) {
+            CodeRuleServiceHelper.recycleNumber(PositionBillConstant.HBPM_POSITIONHR, positionHrDy, String.valueOf(orgId), codeRuleNumber);
+        }
+
     }
 
 }

+ 38 - 0
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/form/hr/PosBillEntryChangeFormPlugin.java

@@ -0,0 +1,38 @@
+package nckd.jxccl.hrmp.hbpm.plugin.form.hr;
+
+import kd.bos.form.events.AfterDoOperationEventArgs;
+import kd.bos.form.field.BasedataEdit;
+import nckd.jxccl.hrmp.hbpm.common.hr.PositionBillConstant;
+
+import java.util.EventObject;
+
+/**
+ * 岗位申请-岗位变更表单插件
+ * @from: kd.hr.homs.formplugin.web.orgbatch.AdminOrgBatchDetailParentPlugin
+ * @author: jtd
+ * @date: 2025/12/28 15:47
+ */
+public class PosBillEntryChangeFormPlugin extends PosBillEntryUpdatePlugin {
+
+    @Override
+    public void initialize() {
+        super.initialize();
+        suffix = PositionBillConstant.CHANGE_TAG;
+        lineSuffix = "_" + suffix;
+    }
+
+    @Override
+    public void afterDoOperation(AfterDoOperationEventArgs afterDoOperationEventArgs) {
+        suffix = PositionBillConstant.CHANGE_TAG;
+        lineSuffix = "_" + suffix;
+        super.afterDoOperation(afterDoOperationEventArgs);
+    }
+
+    @Override
+    public void registerListener(EventObject e) {
+        super.registerListener(e);
+
+        BasedataEdit control = getView().getControl(PositionBillConstant.NCKD_PARENT);
+        control.addBeforeF7SelectListener(this);
+    }
+}

+ 425 - 0
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/form/hr/PosBillEntryUpdatePlugin.java

@@ -0,0 +1,425 @@
+package nckd.jxccl.hrmp.hbpm.plugin.form.hr;
+
+import kd.bos.common.enums.EnableEnum;
+import kd.bos.context.RequestContext;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.dataentity.metadata.IDataEntityProperty;
+import kd.bos.dataentity.metadata.IDataEntityType;
+import kd.bos.dataentity.metadata.clr.DataEntityPropertyCollection;
+import kd.bos.dataentity.metadata.dynamicobject.DynamicProperty;
+import kd.bos.dataentity.serialization.SerializationUtils;
+import kd.bos.entity.MainEntityType;
+import kd.bos.entity.datamodel.events.PropertyChangedArgs;
+import kd.bos.entity.operate.result.OperationResult;
+import kd.bos.entity.property.BasedataProp;
+import kd.bos.entity.property.EntryProp;
+import kd.bos.entity.property.LongProp;
+import kd.bos.entity.property.MulBasedataProp;
+import kd.bos.form.ConfirmCallBackListener;
+import kd.bos.form.ConfirmTypes;
+import kd.bos.form.MessageBoxOptions;
+import kd.bos.form.MessageBoxResult;
+import kd.bos.form.events.AfterDoOperationEventArgs;
+import kd.bos.form.events.MessageBoxClosedEvent;
+import kd.bos.form.field.BasedataEdit;
+import kd.bos.form.field.events.BeforeF7SelectEvent;
+import kd.bos.form.field.events.BeforeF7SelectListener;
+import kd.bos.form.plugin.AbstractFormPlugin;
+import kd.bos.list.ListShowParameter;
+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.orm.util.CollectionUtils;
+import kd.bos.permission.api.HasPermOrgResult;
+import kd.bos.servicehelper.permission.PermissionServiceHelper;
+import kd.hr.hbp.business.servicehelper.HRBaseServiceHelper;
+import kd.hr.hbp.common.model.AuthorizedOrgResult;
+import kd.hr.hbp.common.util.HRDateTimeUtils;
+import kd.hr.hbp.common.util.HRDynamicObjectUtils;
+import kd.hr.hbp.common.util.HRStringUtils;
+import nckd.jxccl.hrmp.hbpm.business.hr.service.impl.PosBillEntryFastChgHelper;
+import nckd.jxccl.hrmp.hbpm.business.hr.service.impl.PositionBillServiceHelper;
+import nckd.jxccl.hrmp.hbpm.common.hr.PatternUtil;
+import nckd.jxccl.hrmp.hbpm.common.hr.PositionBillConstant;
+import org.apache.commons.lang3.time.DateUtils;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.EventObject;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * 岗位申请单分录修改插件
+ * @from: kd.hr.homs.formplugin.web.orgbatch.AdminOrgBatchDetailUpdatePlugin
+ * @author: jtd
+ * @date: 2025/12/28 15:48
+ */
+public class PosBillEntryUpdatePlugin extends AbstractFormPlugin implements BeforeF7SelectListener {
+    private static final Log LOG = LogFactory.getLog(PosBillEntryUpdatePlugin.class);
+    public static String suffix;
+    public static String lineSuffix;
+
+    @Override
+    public void afterBindData(EventObject e) {
+        super.afterBindData(e);
+        getModel().setDataChanged(false);
+    }
+
+    @Override
+    public void beforeBindData(EventObject e) {
+        super.beforeBindData(e);
+        Long billId = getView().getFormShowParameter().getCustomParam(PositionBillConstant.CP_BILLID);
+        Object positionBsed = getView().getFormShowParameter().getCustomParam(PositionBillConstant.CP_POSITION_BSED);
+        long positionBsedTime = positionBsed != null ? Long.parseLong(String.valueOf(positionBsed)) : HRDateTimeUtils.getNowDate().getTime();
+        long id = getModel().getDataEntity().getLong(PositionBillConstant.ID_KEY);
+        if (id == 0L) {
+            Object idStr = getView().getFormShowParameter().getCustomParam(PositionBillConstant.ID_KEY);
+            if (idStr != null) {
+                getModel().setValue(PositionBillConstant.ID_KEY, Long.valueOf(String.valueOf(idStr)));
+            }
+        }
+
+        getModel().setValue(PositionBillConstant.NCKD_BILLID, billId);
+        getModel().setValue(PositionBillConstant.ENABLE, EnableEnum.YES.getCode());
+
+        DynamicObject orgDy = getModel().getDataEntity().getDynamicObject(PositionBillConstant.NCKD_ORG_KEY);
+        getPageCache().put(PositionBillConstant.PC_MASTERORG, orgDy != null ? String.valueOf(orgDy.getLong(PositionBillConstant.ID_KEY)) : EnableEnum.NO.getCode());
+        getModel().setValue(PositionBillConstant.NCKD_BSED, new Date(positionBsedTime));
+        Object positionIdStr = getView().getFormShowParameter().getCustomParam(PositionBillConstant.CP_POSITIONID);
+        if (positionIdStr != null) {
+            Long positionId = Long.valueOf(String.valueOf(positionIdStr));
+            setInfoFromDb(positionId, false);
+        }
+
+        getModel().beginInit();
+        setInfoFromEntry();
+        getModel().endInit();
+        getModel().setDataChanged(false);
+    }
+
+    public void registerListener(EventObject e) {
+        super.registerListener(e);
+        BasedataEdit position = getView().getControl(PositionBillConstant.NCKD_POSITION_KEY);
+        position.addBeforeF7SelectListener(this);
+
+        for(String registerBeforeF7Listener : getRegisterBeforeF7ListenerControlList()) {
+            BasedataEdit basedataEdit = getControl(registerBeforeF7Listener);
+            if (basedataEdit != null) {
+                basedataEdit.setF7BatchFill(false);
+                basedataEdit.addBeforeF7SelectListener(this);
+            }
+        }
+
+    }
+
+    private List<String> getRegisterBeforeF7ListenerControlList() {
+        //return Arrays.asList(PositionBillConstant.NCKD_PARENT, PositionBillConstant.NCKD_ORG_KEY);
+        return Collections.singletonList(PositionBillConstant.NCKD_ORG_KEY);
+    }
+
+    @Override
+    public void beforeF7Select(BeforeF7SelectEvent beforeF7SelectEvent) {
+        String fieldKey = beforeF7SelectEvent.getProperty().getName();
+        if (PositionBillConstant.NCKD_POSITION_KEY.equals(fieldKey)) {
+            AuthorizedOrgResult authorizedOrgResult = PositionBillServiceHelper.getOrgAuth(getView());
+            if (!authorizedOrgResult.isHasAllOrgPerm()) {
+                List<Long> hasPermOrgList = authorizedOrgResult.getHasPermOrgs();
+                beforeF7SelectEvent.getCustomQFilters().add(new QFilter(String.join(".", PositionBillConstant.ADMINORG, PositionBillConstant.BOID_KEY), QCP.in, hasPermOrgList));
+            }
+            PositionBillServiceHelper.filterF7Org(getView().getParentView(), beforeF7SelectEvent, null);
+
+            if (getModel().getValue(PositionBillConstant.NCKD_ORG_KEY) != null) {
+                List<Long> orgIdList = Collections.singletonList(((DynamicObject) getModel().getValue(PositionBillConstant.NCKD_ORG_KEY)).getLong(PositionBillConstant.ID_KEY));
+                if (CollectionUtils.isEmpty(orgIdList)) {
+                    beforeF7SelectEvent.getCustomQFilters().add(new QFilter("1", QCP.not_equals, 1));
+                } else {
+                    beforeF7SelectEvent.getCustomQFilters().add(new QFilter(PositionBillConstant.ORG_KEY, QCP.in, orgIdList));
+                }
+            }
+
+            beforeF7SelectEvent.getFormShowParameter().setCustomParam(PositionBillConstant.CP_SEARCHDATE, new Date());
+            getPageCache().put(PositionBillConstant.PC_ISCHANGEPOSITION, Boolean.TRUE.toString());
+        } else if (PositionBillConstant.NCKD_PARENT.equals(fieldKey)) {
+            Long positionId = getModel().getDataEntity().getLong(PositionBillConstant.NCKD_POSITIONID_KEY);
+            // 使用岗位BOID查下级岗位,岗位的上级岗位存储的是BOID
+            Long positionBoId = getModel().getDataEntity().getDynamicObject(PositionBillConstant.NCKD_POSITION_KEY).getLong(PositionBillConstant.BOID_KEY);
+            Date positionBsed = getModel().getDataEntity().getDate(PositionBillConstant.NCKD_BSED);
+            List<Long> positionIds = PositionBillServiceHelper.getPositionAndChildren(positionBoId, positionBsed);
+            // 固定过滤岗位
+            positionIds.add(positionId);
+            beforeF7SelectEvent.getCustomQFilters().add(new QFilter(PositionBillConstant.ID_KEY, QCP.not_in, positionIds));
+
+            ListShowParameter showParameter = (ListShowParameter) beforeF7SelectEvent.getFormShowParameter();
+            Date date = DateUtils.truncate(new Date(), 5);
+            showParameter.getCustomParams().put(PositionBillConstant.CP_SEARCHDATE, date);
+        } else if (PositionBillConstant.NCKD_ORG_KEY.equals(fieldKey)) {
+            HasPermOrgResult permOrgResult = PermissionServiceHelper.getUserHasPermOrgs(RequestContext.get().getCurrUserId(), false);
+            if (!permOrgResult.hasAllOrgPerm()) {
+                List<Long> hasPermOrgs = permOrgResult.getHasPermOrgs();
+                beforeF7SelectEvent.getCustomQFilters().add(new QFilter(PositionBillConstant.ID_KEY, QCP.in, hasPermOrgs));
+            }
+        }
+    }
+
+    @Override
+    public void propertyChanged(PropertyChangedArgs changedArgs) {
+        String fieldKey = changedArgs.getProperty().getName();
+        switch (fieldKey) {
+            case PositionBillConstant.NCKD_POSITION_KEY:
+                positionChanged(changedArgs);
+                break;
+            case PositionBillConstant.NCKD_ORG_KEY:
+                PosBillEntryFastChgHelper.orgPropertyChanged(changedArgs, getView(), this);
+        }
+
+    }
+
+    private void positionChanged(PropertyChangedArgs changedArgs) {
+        if (Boolean.TRUE.toString().equals(getPageCache().get(PositionBillConstant.PC_ISCHANGEPOSITION))) {
+            getPageCache().put(PositionBillConstant.PC_ISCHANGEPOSITION, Boolean.FALSE.toString());
+            if (changedArgs.getChangeSet()[0].getNewValue() == null) {
+                getModel().setValue(PositionBillConstant.NCKD_POSITION_KEY, changedArgs.getChangeSet()[0].getOldValue());
+                return;
+            }
+
+            DynamicObject position = (DynamicObject) changedArgs.getChangeSet()[0].getOldValue();
+            DynamicObject newPosition = (DynamicObject) changedArgs.getChangeSet()[0].getNewValue();
+            Long positionIdOld = position != null ? position.getLong(PositionBillConstant.ID_KEY) : null;
+            Long positionIdNew = newPosition != null ? newPosition.getLong(PositionBillConstant.ID_KEY) : null;
+            if (newPosition != null) {
+                ConfirmCallBackListener confirmCallBackListener = new ConfirmCallBackListener(PositionBillConstant.NCKD_POSITION_KEY, this);
+                getView().showConfirm("切换岗位后,当前已修改的内容将会丢失,是否继续?", "", MessageBoxOptions.OKCancel, ConfirmTypes.Default, confirmCallBackListener, null, positionIdOld + "#" + positionIdNew);
+            }
+        }
+
+    }
+
+    @Override
+    public void confirmCallBack(MessageBoxClosedEvent event) {
+        super.confirmCallBack(event);
+        int result = event.getResult().getValue();
+        getView().getFormShowParameter();
+        switch (event.getCallBackId()) {
+            case PositionBillConstant.NCKD_POSITION_KEY:
+                if (result == MessageBoxResult.Yes.getValue()) {
+                    String positionIdNew = event.getCustomVaule().split("#")[1];
+                    setInfoFromDb(Long.parseLong(positionIdNew), true);
+                } else {
+                    String positionIdOld = event.getCustomVaule().split("#")[0];
+                    getModel().setValue(PositionBillConstant.NCKD_POSITION_KEY, "null".equals(positionIdOld) ? null : positionIdOld);
+                }
+            case PositionBillConstant.CB_CHG_ORG:
+                if (event.getResult().getValue() == MessageBoxResult.Yes.getValue()) {
+                    getView().getPageCache().put(PositionBillConstant.PC_MASTERORG, String.valueOf(getModel().getDataEntity().getLong(String.join(".", PositionBillConstant.NCKD_ORG_KEY, PositionBillConstant.ID_KEY))));
+                    getModel().beginInit();
+                    PosBillEntryFastChgHelper.cleanOrgBaseInfo(getModel().getDataEntity().getLong(String.join(".", PositionBillConstant.NCKD_ORG_KEY, PositionBillConstant.ID_KEY)), getView());
+                    getModel().endInit();
+                } else {
+                    Long masterOrgId = Long.valueOf(getPageCache().get(PositionBillConstant.PC_MASTERORG));
+                    getModel().beginInit();
+                    getModel().setValue(PositionBillConstant.NCKD_ORG_KEY, masterOrgId.equals(0L) ? null : masterOrgId);
+                    getView().updateView(PositionBillConstant.NCKD_ORG_KEY);
+                    getModel().endInit();
+                }
+            default:
+        }
+    }
+
+    protected void setInfoFromEntry() {
+        Object selectObject = getView().getFormShowParameter().getCustomParam(PositionBillConstant.CP_SELECTOBJECT);
+        if (selectObject != null) {
+            Map<String, Object> map = SerializationUtils.fromJsonString(selectObject.toString(), Map.class);
+            Map<String, Object> noSuffixMap = map.entrySet().stream().collect(HashMap::new, (m, v) -> m.put(PositionBillServiceHelper.getNoLineSuffixProp(v.getKey(), lineSuffix), v.getValue()), HashMap::putAll);
+            List<String> props = new ArrayList();
+
+            for(String prop : noSuffixMap.keySet()) {
+                if (PatternUtil.isExProperty(prop)) {
+                    props.add(prop);
+                }
+            }
+
+            // 获取分录要转换的键值,将单据分录字段转换转成分录页面字段
+            Map<String, String> transKeyMap = PositionBillServiceHelper.getPosBillEntryTransKeyMap();
+            transKeyMap.forEach((key, value) -> {
+                noSuffixMap.put(value, noSuffixMap.get(key));
+                noSuffixMap.remove(key);
+                props.add(value);
+                props.remove(key);
+            });
+
+            Stream<String> fields = Stream.of(props.toArray(new String[0]));
+            fields.forEach((s) -> setValue(s, noSuffixMap.get(s)));
+
+            setValue(PositionBillConstant.NCKD_BILLID, getView().getFormShowParameter().getCustomParam(PositionBillConstant.CP_BILLID));
+        }
+
+    }
+
+    protected void setInfoFromDb(Long positionId, boolean positionChange) {
+        Object positionBsed = getView().getFormShowParameter().getCustomParam(PositionBillConstant.CP_POSITION_BSED);
+        long positionBsedTime = positionBsed != null ? Long.parseLong(String.valueOf(positionBsed)) : HRDateTimeUtils.getNowDate().getTime();
+        if (positionId != 0L) {
+            Object entryId = getView().getFormShowParameter().getCustomParam(PositionBillConstant.ID_KEY);
+            HRBaseServiceHelper positionBillEntryDAO = new HRBaseServiceHelper(PositionBillConstant.NCKD_POSITIONBILLENTRY_ENTITY);
+            boolean entryIdExists = positionBillEntryDAO.isExists(entryId);
+            DynamicObject positionMasterInfo = PositionBillServiceHelper.getPositionDyById(positionId);
+            if (!positionChange && entryIdExists) {
+            } else {
+                long orgBoId = positionMasterInfo.getDynamicObject(PositionBillConstant.ADMINORG).getLong(PositionBillConstant.BOID_KEY);
+                getModel().setValue(PositionBillConstant.NCKD_ADMINORGBOID_KEY, orgBoId);
+                getModel().setValue(PositionBillConstant.NCKD_POSITION_KEY, positionId);
+                getModel().setValue(PositionBillConstant.NCKD_POSITIONID_KEY, positionId);
+                if (lineSuffix.endsWith("_"+PositionBillConstant.CHANGE_TAG)) {
+                    getModel().setValue(PositionBillConstant.NCKD_PARENT, null);
+                } else {
+                    getModel().setValue(PositionBillConstant.NCKD_PARENT, PositionBillServiceHelper.getHisId(positionMasterInfo.getLong(String.join(".", PositionBillConstant.NCKD_PARENT, PositionBillConstant.ID_KEY))));
+                }
+
+                Object orgParam = getView().getFormShowParameter().getCustomParam(PositionBillConstant.ORG_KEY);
+                if (orgParam != null) {
+                    getModel().beginInit();
+                    getModel().setValue(PositionBillConstant.NCKD_ORG_KEY, orgParam);
+                    getModel().endInit();
+                    getView().updateView(PositionBillConstant.NCKD_ORG_KEY);
+                }
+
+                MainEntityType dataEntityType = getModel().getDataEntityType();
+                DataEntityPropertyCollection properties = dataEntityType.getProperties();
+                Map<String, IDataEntityProperty> allFields = ((MainEntityType) positionMasterInfo.getDataEntityType()).getAllFields();
+
+                // 获取分录要转换的键值
+                Map<String, String> posBillEntryTransKeyMap = PositionBillServiceHelper.getPosBillEntryTransKeyMap();
+                // 获取岗位要转换的键值
+                Map<String, String> positionTransKeyMap = PositionBillServiceHelper.getPositionTransKeyMap();
+                // 获取分录属性
+                Map<String, IDataEntityProperty> entryPropMap = new HashMap<String, IDataEntityProperty>();
+                for(IDataEntityProperty property : properties) {
+                    String propName = property.getName();
+                    if (property instanceof EntryProp) {
+                        getModel().deleteEntryData(propName);
+                        entryPropMap.put(positionTransKeyMap.getOrDefault(propName, propName), property);
+                        continue;
+                    }
+
+                    if (positionTransKeyMap.containsKey(propName) && allFields.containsKey(positionTransKeyMap.getOrDefault(propName, ""))) {
+                        getModel().setValue(propName, positionMasterInfo.get(positionTransKeyMap.getOrDefault(propName, "")));
+                    } else if ((PatternUtil.isExProperty(propName) || posBillEntryTransKeyMap.containsValue(propName)) && allFields.containsKey(propName)) {
+                        getModel().setValue(propName, positionMasterInfo.get(propName));
+                    }
+                }
+
+                // 处理分录数据
+                DataEntityPropertyCollection positionProperties = positionMasterInfo.getDataEntityType().getProperties();
+                Map<String, IDataEntityProperty> dataEntryPropMap = positionProperties.stream().filter(property -> entryPropMap.containsKey(property.getName())).collect(Collectors.toMap(property -> entryPropMap.get(property.getName()).getName(), Function.identity()));
+
+                for (Map.Entry<String, IDataEntityProperty> dataEntryProp : dataEntryPropMap.entrySet()) {
+                    DynamicObjectCollection fromCollection = positionMasterInfo.getDynamicObjectCollection(dataEntryProp.getValue());
+                    DynamicObjectCollection toCollection = getModel().getDataEntity().getDynamicObjectCollection(dataEntryProp.getKey());
+                    if (fromCollection == null || fromCollection.isEmpty()) {
+                        continue;
+                    }
+
+                    for (DynamicObject fromObj : fromCollection) {
+                        HRDynamicObjectUtils.copy(fromObj, toCollection.addNew());
+                    }
+                }
+
+                getModel().setDataChanged(false);
+                // 生效日期特殊处理
+                getModel().setValue(PositionBillConstant.NCKD_BSED, new Date(positionBsedTime));
+                // 原上级岗位特殊处理
+                getModel().setValue(PositionBillConstant.NCKD_ORIPARENT_KEY, getModel().getValue(PositionBillConstant.NCKD_PARENT));
+            }
+        }
+    }
+
+    private void setValue(String key, Object value) {
+        if (getModel().getProperty(key) != null) {
+            Class<?> propertyType = getModel().getDataEntityType().getProperty(key).getPropertyType();
+            DynamicProperty dynamicProperty = getModel().getDataEntityType().getProperty(key);
+            if (value != null) {
+                if (propertyType.equals(DynamicObject.class) && dynamicProperty instanceof BasedataProp) {
+                    Object id = ((Map) value).get(PositionBillConstant.ID_KEY);
+                    if (id != null && !HRStringUtils.equals(value.toString(), "0")) {
+                        getModel().setValue(key, id);
+                    }
+                } else if (propertyType.equals(DynamicObject.class) && dynamicProperty instanceof MulBasedataProp && value instanceof List) {
+                    MulBasedataProp property = (MulBasedataProp) getModel().getDataEntityType().getProperty(key);
+                    DynamicObjectCollection dynamicObjectCollection = new DynamicObjectCollection();
+                    HRBaseServiceHelper serviceHelper = new HRBaseServiceHelper(property.getBaseEntityId());
+                    LOG.info("set MulBasedataProp value [{}]", value);
+                    ((List) value).forEach((map) -> {
+                        DynamicObject dy = new DynamicObject(property.getDynamicCollectionItemPropertyType());
+                        if (((Map) map).get(PositionBillConstant.FBASEDATAID_ID_KEY) != null) {
+                            dy.set(PositionBillConstant.FBASEDATAID_ID_KEY, ((Map) map).get(PositionBillConstant.FBASEDATAID_ID_KEY));
+                            DynamicObject emptyDynamicObject = serviceHelper.generateEmptyDynamicObject();
+                            emptyDynamicObject.set(PositionBillConstant.ID_KEY, ((Map) map).get(PositionBillConstant.FBASEDATAID_ID_KEY));
+                            dy.set(PositionBillConstant.FBASEDATAID_KEY, emptyDynamicObject);
+                            dynamicObjectCollection.add(dy);
+                        } else {
+                            Object fbasedataid = ((Map) map).get(PositionBillConstant.FBASEDATAID_KEY);
+                            if (fbasedataid instanceof Map && ((Map) fbasedataid).get(PositionBillConstant.ID_KEY) instanceof Long) {
+                                Long id = (Long) ((Map) fbasedataid).get(PositionBillConstant.ID_KEY);
+                                dy.set(PositionBillConstant.FBASEDATAID_ID_KEY, id);
+                                DynamicObject emptyDynamicObject = serviceHelper.generateEmptyDynamicObject();
+                                emptyDynamicObject.set(PositionBillConstant.ID_KEY, id);
+                                dy.set(PositionBillConstant.FBASEDATAID_KEY, emptyDynamicObject);
+                                dynamicObjectCollection.add(dy);
+                            }
+                        }
+
+                    });
+                    getModel().setValue(key, dynamicObjectCollection.size() != 0 ? dynamicObjectCollection : null);
+                } else {
+                    getModel().setValue(key, value);
+                }
+
+            }
+        }
+    }
+
+    public void afterDoOperation(AfterDoOperationEventArgs afterDoOperationEventArgs) {
+        super.afterDoOperation(afterDoOperationEventArgs);
+        String key = afterDoOperationEventArgs.getOperateKey();
+        OperationResult result = afterDoOperationEventArgs.getOperationResult();
+        if (result != null && HRStringUtils.equals(key, PositionBillConstant.SAVE_OP) && result.isSuccess()) {
+            DynamicObject data = getModel().getDataEntity();
+            Map<String, Object> map = new HashMap(1);
+            DynamicObject dataEntity = getModel().getDataEntity(true);
+            IDataEntityType dataEntityType = dataEntity.getDataEntityType();
+
+            for(IDataEntityProperty property : dataEntityType.getProperties()) {
+                String propName = property.getName();
+                if (PatternUtil.isExProperty(propName) && !(property instanceof LongProp)) {
+                    map.put(propName, data.get(propName));
+                }
+            }
+
+            // 获取分录要转换的键值
+            Map<String, String> posBillEntryTransKeyMap = PositionBillServiceHelper.getPosBillEntryTransKeyMap();
+            posBillEntryTransKeyMap.forEach((k, v) -> {
+                if (map.containsKey(v)) {
+                    map.put(k, map.get(v));
+                    map.remove(k);
+                } else {
+                    map.put(k, data.get(v));
+                }
+            });
+
+            Map<String, Object> suffixMap = map.entrySet().stream().collect(HashMap::new, (m, v) -> m.put(v.getKey()+lineSuffix, v.getValue()), HashMap::putAll);
+            suffixMap.put(PositionBillConstant.ID_KEY, data.getLong(PositionBillConstant.ID_KEY));
+            getView().returnDataToParent(suffixMap);
+            getView().close();
+        }
+
+    }
+
+}

+ 96 - 52
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/form/hr/PositionBillEntryFormPlugin.java

@@ -6,19 +6,32 @@ import kd.bos.bill.OperationStatus;
 import kd.bos.common.enums.EnableEnum;
 import kd.bos.dataentity.entity.DynamicObject;
 import kd.bos.dataentity.entity.ILocaleString;
+import kd.bos.dataentity.metadata.IDataEntityProperty;
 import kd.bos.dataentity.utils.ObjectUtils;
+import kd.bos.entity.EntityMetadataCache;
+import kd.bos.entity.MainEntityType;
 import kd.bos.entity.operate.result.OperationResult;
+import kd.bos.entity.property.BasedataProp;
+import kd.bos.form.ConfirmCallBackListener;
 import kd.bos.form.FormShowParameter;
 import kd.bos.form.IFormView;
+import kd.bos.form.MessageBoxOptions;
+import kd.bos.form.MessageBoxResult;
+import kd.bos.form.control.EntryGrid;
+import kd.bos.form.control.events.ClickListener;
+import kd.bos.form.control.events.ItemClickEvent;
 import kd.bos.form.events.AfterDoOperationEventArgs;
 import kd.bos.form.events.BeforeDoOperationEventArgs;
+import kd.bos.form.events.MessageBoxClosedEvent;
 import kd.bos.form.field.BasedataEdit;
 import kd.bos.form.field.events.BeforeF7SelectEvent;
 import kd.bos.form.field.events.BeforeF7SelectListener;
 import kd.bos.form.operate.AbstractOperate;
 import kd.bos.form.plugin.AbstractFormPlugin;
-import kd.bos.list.ListShowParameter;
+import kd.bos.servicehelper.basedata.BaseDataServiceHelper;
 import kd.hr.hbp.common.util.HRStringUtils;
+import nckd.jxccl.hrmp.hbpm.business.hr.service.impl.PositionBillServiceHelper;
+import nckd.jxccl.hrmp.hbpm.business.hr.utils.PositionBillUtil;
 import nckd.jxccl.hrmp.hbpm.common.hr.PositionBillConstant;
 
 import java.util.EventObject;
@@ -26,10 +39,11 @@ import java.util.Map;
 
 /**
  * 岗位申请单分录表单插件
+ * @from: kd.hr.homs.formplugin.web.orgbatch.AdminOrgBatchDetailPlugin
  * @author: jtd
  * @date: 2025-11-04 9:35
  */
-public class PositionBillEntryFormPlugin extends AbstractFormPlugin implements BeforeF7SelectListener {
+public class PositionBillEntryFormPlugin extends AbstractFormPlugin implements ClickListener, BeforeF7SelectListener {
 
     @Override
     public void beforeBindData(EventObject e) {
@@ -38,8 +52,8 @@ public class PositionBillEntryFormPlugin extends AbstractFormPlugin implements B
         FormShowParameter formShowParameter = getView().getFormShowParameter();
         setOrg();
         setDefaultValue();
-        if (formShowParameter.getCustomParam("sequence") != null && getModel().getDataEntity(true).getInt(PositionBillConstant.NCKD_SEQUENCE) == 0) {
-            getModel().setValue(PositionBillConstant.NCKD_SEQUENCE, formShowParameter.getCustomParam("sequence"));
+        if (formShowParameter.getCustomParam(PositionBillConstant.CP_SEQUENCE) != null && getModel().getDataEntity(true).getInt(PositionBillConstant.NCKD_SEQUENCE) == 0) {
+            getModel().setValue(PositionBillConstant.NCKD_SEQUENCE, formShowParameter.getCustomParam(PositionBillConstant.CP_SEQUENCE));
         }
     }
 
@@ -49,7 +63,7 @@ public class PositionBillEntryFormPlugin extends AbstractFormPlugin implements B
         getModel().setDataChanged(false);
         OperationStatus status = getView().getFormShowParameter().getStatus();
         if (OperationStatus.ADDNEW.equals(status) || OperationStatus.EDIT.equals(status)) {
-            getView().setEnable(Boolean.TRUE, PositionBillConstant.ORG_KEY);
+            getView().setEnable(Boolean.TRUE, PositionBillConstant.NCKD_ORG_KEY);
         }
     }
 
@@ -57,8 +71,8 @@ public class PositionBillEntryFormPlugin extends AbstractFormPlugin implements B
      * 设置单头ID
      */
     private void setDefaultValue() {
-        Object billId = getView().getFormShowParameter().getCustomParam("billid");
-        if (billId != null) {// 135
+        Object billId = getView().getFormShowParameter().getCustomParam(PositionBillConstant.CP_BILLID);
+        if (billId != null) {
             getModel().setValue(PositionBillConstant.NCKD_BILLID, Long.parseLong(String.valueOf(billId)));
         }
     }
@@ -69,36 +83,42 @@ public class PositionBillEntryFormPlugin extends AbstractFormPlugin implements B
 
         BasedataEdit adminorg = getView().getControl(PositionBillConstant.NCKD_ADMINORG);
         adminorg.addBeforeF7SelectListener(this);
-
-        BasedataEdit position = getView().getControl(PositionBillConstant.NCKD_POSITION);
+        BasedataEdit position = getView().getControl(PositionBillConstant.NCKD_POSITION_KEY);
         position.addBeforeF7SelectListener(this);
-
         BasedataEdit parent = getView().getControl(PositionBillConstant.NCKD_PARENT);
         parent.addBeforeF7SelectListener(this);
+        addItemClickListeners(PositionBillConstant.NCKD_ADVCONTOOLBARAP11_KEY);
     }
 
     @Override
     public void beforeF7Select(BeforeF7SelectEvent beforeF7SelectEvent) {
         String fieldKey = beforeF7SelectEvent.getProperty().getName();
-        // 替换组织F7模板
-        if (PositionBillConstant.NCKD_ADMINORG.equals(fieldKey)) {
-            ListShowParameter showParameter = (ListShowParameter) beforeF7SelectEvent.getFormShowParameter();
-            showParameter.setFormId(PositionBillConstant.HAOS_ORGTREELISTF7_ENTITY);
-            //showParameter.setCaption("行政组织");
-        }
-
-        // 替换岗位F7模板
-        if (PositionBillConstant.NCKD_POSITION.equals(fieldKey)) {
-            ListShowParameter showParameter = (ListShowParameter) beforeF7SelectEvent.getFormShowParameter();
-            showParameter.setFormId(PositionBillConstant.NCKD_HBPM_POSORGTREELISTF_ENTITY);
-            showParameter.setCaption("岗位");
-        }
+        DynamicObject orgDy = getModel().getDataEntity().getDynamicObject(PositionBillConstant.NCKD_ORG);
+        MainEntityType entityType = EntityMetadataCache.getDataEntityType(getView().getEntityId());
+        IDataEntityProperty property = entityType.getAllFields().get(fieldKey);
+        Boolean baseDataCtrl = BaseDataServiceHelper.checkBaseDataCtrl(((BasedataProp) property).getBaseEntityId());
+        if (baseDataCtrl && orgDy == null && !HRStringUtils.equals(PositionBillConstant.NCKD_PARENT, fieldKey) && !HRStringUtils.equals(PositionBillConstant.NCKD_ORG, fieldKey)) {
+            getView().showTipNotification("请先选择组织体系管理组织。");
+            beforeF7SelectEvent.setCancel(true);
+        } else {
+            switch (fieldKey) {
+                case PositionBillConstant.NCKD_ADMINORG:
+                    // 替换组织F7模板
+                    beforeF7SelectEvent.getFormShowParameter().setFormId(PositionBillConstant.HAOS_ORGBATCHTREELISTF7_ENTITY);
+                    beforeF7SelectEvent.getFormShowParameter().setCaption("行政组织");
+                    break;
+                case PositionBillConstant.NCKD_POSITION_KEY:
+                    // 替换岗位F7模板
+                    beforeF7SelectEvent.getFormShowParameter().setFormId(PositionBillConstant.NCKD_HBPM_POSORGTREELISTF_ENTITY);
+                    beforeF7SelectEvent.getFormShowParameter().setCaption("岗位");
+                    break;
+                case PositionBillConstant.NCKD_PARENT:
+                    DynamicObject positionObject = (DynamicObject) getModel().getValue(PositionBillConstant.NCKD_POSITION_KEY);
+                    PositionBillServiceHelper.setParentFilter(PositionBillUtil.getView(getView(), PositionBillConstant.NCKD_POSITIONBILL_ENTITY), positionObject, beforeF7SelectEvent);
+                    beforeF7SelectEvent.getFormShowParameter().setCaption("上级岗位");
+                    beforeF7SelectEvent.getFormShowParameter().setFormId(PositionBillConstant.NCKD_HBPM_POSORGTREELISTF_ENTITY);
+            }
 
-        // 替换上级岗位F7模板
-        if (PositionBillConstant.NCKD_PARENT.equals(fieldKey)) {
-            ListShowParameter showParameter = (ListShowParameter) beforeF7SelectEvent.getFormShowParameter();
-            showParameter.setFormId(PositionBillConstant.NCKD_HBPM_POSORGTREELISTF_ENTITY);
-            showParameter.setCaption("上级岗位");
         }
     }
 
@@ -115,6 +135,31 @@ public class PositionBillEntryFormPlugin extends AbstractFormPlugin implements B
         }
     }
 
+    public void itemClick(ItemClickEvent evt) {
+        super.itemClick(evt);
+        if (PositionBillConstant.NCKD_TB_DEL_KEY.equals(evt.getItemKey())) {
+            EntryGrid posDutyEntryGrid = getView().getControl(PositionBillConstant.NCKD_POSDUTY_ENTRY_ENTITY_KEY);
+            int length = posDutyEntryGrid.getSelectRows().length;
+            if (length > 0) {
+                ConfirmCallBackListener deleteEntryCallBackListener = new ConfirmCallBackListener(PositionBillConstant.CB_DEL_ROW, this);
+                getView().showConfirm(String.format("你已选中%s条记录,删除后将不可恢复,是否继续?", length), MessageBoxOptions.OKCancel, deleteEntryCallBackListener);
+            } else {
+                getView().showTipNotification("请选中需要操作的行。");
+            }
+        }
+
+    }
+
+    public void confirmCallBack(MessageBoxClosedEvent event) {
+        super.confirmCallBack(event);
+        if (PositionBillConstant.CB_DEL_ROW.equals(event.getCallBackId()) && event.getResult().getValue() == MessageBoxResult.Yes.getValue()) {
+            EntryGrid strategyEntryGrid = getView().getControl(PositionBillConstant.NCKD_POSDUTY_ENTRY_ENTITY_KEY);
+            int[] rows = strategyEntryGrid.getSelectRows();
+            getModel().deleteEntryRows(PositionBillConstant.NCKD_POSDUTY_ENTRY_ENTITY_KEY, rows);
+        }
+
+    }
+
     /**
      * 设置组织体系管理组织
      */
@@ -122,12 +167,12 @@ public class PositionBillEntryFormPlugin extends AbstractFormPlugin implements B
         String entityId = getView().getEntityId();
         if (PositionBillConstant.NCKD_POSBILLENTRYADD_ENTITY.equals(entityId) || PositionBillConstant.NCKD_POSBILLENTRYCHANGE_ENTITY.equals(entityId)) {
             Object orgParam = getView().getFormShowParameter().getCustomParam(PositionBillConstant.ORG_KEY);
-            String isInit = getPageCache().get("isInit");
+            String isInit = getPageCache().get(PositionBillConstant.PC_ISINIT);
             if (orgParam != null && HRStringUtils.isEmpty(isInit)) {
                 getModel().beginInit();
-                getModel().setValue(PositionBillConstant.NCKD_ORG, orgParam);
+                getModel().setValue(PositionBillConstant.NCKD_ORG_KEY, orgParam);
                 getModel().endInit();
-                getPageCache().put("isInit", EnableEnum.YES.getCode());
+                getPageCache().put(PositionBillConstant.PC_ISINIT, EnableEnum.YES.getCode());
             }
         }
     }
@@ -135,12 +180,9 @@ public class PositionBillEntryFormPlugin extends AbstractFormPlugin implements B
     @Override
     public void beforeDoOperation(BeforeDoOperationEventArgs args) {
         super.beforeDoOperation(args);
-
-
         AbstractOperate operate = (AbstractOperate) args.getSource();
         String operateKey = operate.getOperateKey();
         if (HRStringUtils.equals(operateKey, PositionBillConstant.SAVE_OP) || HRStringUtils.equals(operateKey, PositionBillConstant.SAVE_AND_NEW_OP)) {
-
             IFormView parentView = getBillFormView(getView());
             // 组织下同级岗位名称数据 {orgBoid:{positionId:positionName}}
             Map<String, Map<String, ILocaleString>> orgBoIdToSiblingNameMap = Maps.newHashMapWithExpectedSize(16);
@@ -151,9 +193,9 @@ public class PositionBillEntryFormPlugin extends AbstractFormPlugin implements B
                 setValidateData(parentView, PositionBillConstant.CHANGE_TAG, orgBoIdToSiblingNameMap, numberMap);
             }
 
-            operate.getOption().setVariableValue("OP_BILL_SIBLING_NAMES_MAP", JSONObject.toJSONString(orgBoIdToSiblingNameMap));
-            operate.getOption().setVariableValue("OP_BILL_NUMBER_MAP", JSONObject.toJSONString(numberMap));
-            operate.getOption().setVariableValue("OP_VALIDATOR_BILL_POSITION_ALL_CHANGE_POSITION_KEY", getView().getFormShowParameter().getCustomParam("OP_VALIDATOR_BILL_POSITION_ALL_CHANGE_POSITION_KEY"));
+            operate.getOption().setVariableValue(PositionBillConstant.OP_BILL_SIBLING_NAMES_MAP, JSONObject.toJSONString(orgBoIdToSiblingNameMap));
+            operate.getOption().setVariableValue(PositionBillConstant.OP_BILL_NUMBER_MAP, JSONObject.toJSONString(numberMap));
+            operate.getOption().setVariableValue(PositionBillConstant.OP_VALIDATOR_BILL_POSITION_ALL_CHANGE_POSITION_KEY, getView().getFormShowParameter().getCustomParam(PositionBillConstant.OP_VALIDATOR_BILL_POSITION_ALL_CHANGE_POSITION_KEY));
         }
     }
 
@@ -170,23 +212,25 @@ public class PositionBillEntryFormPlugin extends AbstractFormPlugin implements B
     private void setValidateData(IFormView parentView, String suffix, Map<String, Map<String, ILocaleString>> orgBoIdToSiblingNameMap, Map<String, String> numberMap) {
         for(DynamicObject addEntryDy : parentView.getModel().getDataEntity(true).getDynamicObjectCollection(String.join("_", PositionBillConstant.NCKD_ENTRYENTITY, suffix))) {
             DynamicObject adminOrgDy = addEntryDy.getDynamicObject(String.join("_", PositionBillConstant.NCKD_ADMINORG, suffix));
-            String positionKey = String.join("_", PositionBillConstant.NCKD_POSITION_KEY, suffix);
-            String positionIdKey = String.join(".", positionKey, PositionBillConstant.ID_KEY);
-            if (PositionBillConstant.ADD_TAG.equals(suffix)) {
-                positionIdKey = positionKey;
+            if (adminOrgDy != null) {
+                String positionKey = String.join("_", PositionBillConstant.NCKD_POSITION_KEY, suffix);
+                String positionIdKey = String.join(".", positionKey, PositionBillConstant.ID_KEY);
+                if (PositionBillConstant.ADD_TAG.equals(suffix)) {
+                    positionIdKey = positionKey;
+                }
+
+                long positionId = addEntryDy.getLong(positionIdKey);
+                long boId = adminOrgDy.getLong(PositionBillConstant.BOID_KEY);
+                Map<String, ILocaleString> siblingNameMap = orgBoIdToSiblingNameMap.get(String.valueOf(boId));
+                if (siblingNameMap == null) {
+                    siblingNameMap = Maps.newHashMapWithExpectedSize(16);
+                }
+
+                siblingNameMap.put(String.valueOf(positionId), addEntryDy.getLocaleString(String.join("_", PositionBillConstant.NCKD_NAME_KEY, suffix)));
+                orgBoIdToSiblingNameMap.put(String.valueOf(boId), siblingNameMap);
+                numberMap.put(String.valueOf(positionId), addEntryDy.getString(String.join("_", PositionBillConstant.NCKD_NUMBER_KEY, suffix)));
             }
 
-            long positionId = addEntryDy.getLong(positionIdKey);
-            long boId = adminOrgDy.getLong(PositionBillConstant.BOID_KEY);
-            Map<String, ILocaleString> siblingNameMap = orgBoIdToSiblingNameMap.get(String.valueOf(boId));
-            if (siblingNameMap == null) {
-                siblingNameMap = Maps.newHashMapWithExpectedSize(16);
-            }
-
-            siblingNameMap.put(String.valueOf(positionId), addEntryDy.getLocaleString(String.join("_", PositionBillConstant.NCKD_NAME_KEY, suffix)));
-            orgBoIdToSiblingNameMap.put(String.valueOf(boId), siblingNameMap);
-
-            numberMap.put(String.valueOf(positionId), addEntryDy.getString(String.join("_", PositionBillConstant.NCKD_NUMBER_KEY, suffix)));
         }
 
     }

+ 338 - 94
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/form/hr/PositionBillFormPlugin.java

@@ -1,12 +1,16 @@
 package nckd.jxccl.hrmp.hbpm.plugin.form.hr;
 
+import com.alibaba.fastjson.JSONObject;
 import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
 import kd.bos.bill.BillOperationStatus;
 import kd.bos.bill.BillShowParameter;
 import kd.bos.bill.OperationStatus;
 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.entity.LocaleString;
 import kd.bos.dataentity.metadata.IDataEntityProperty;
 import kd.bos.dataentity.metadata.IDataEntityType;
 import kd.bos.dataentity.serialization.SerializationUtils;
@@ -17,6 +21,8 @@ import kd.bos.entity.datamodel.IDataModel;
 import kd.bos.entity.datamodel.ListSelectedRow;
 import kd.bos.entity.datamodel.ListSelectedRowCollection;
 import kd.bos.entity.datamodel.events.PropertyChangedArgs;
+import kd.bos.entity.operate.OperateOptionConst;
+import kd.bos.entity.operate.result.IOperateInfo;
 import kd.bos.entity.operate.result.OperationResult;
 import kd.bos.entity.property.BasedataProp;
 import kd.bos.ext.hr.entity.property.PositionFieldProp;
@@ -25,55 +31,68 @@ import kd.bos.form.ConfirmCallBackListener;
 import kd.bos.form.ConfirmTypes;
 import kd.bos.form.IFormView;
 import kd.bos.form.MessageBoxOptions;
+import kd.bos.form.MessageBoxResult;
 import kd.bos.form.ShowType;
 import kd.bos.form.control.EntryGrid;
 import kd.bos.form.control.events.EntryGridBindDataListener;
 import kd.bos.form.events.AfterDoOperationEventArgs;
+import kd.bos.form.events.BeforeClosedEvent;
+import kd.bos.form.events.BeforeDoOperationEventArgs;
 import kd.bos.form.events.ClosedCallBackEvent;
+import kd.bos.form.events.LoadCustomControlMetasArgs;
 import kd.bos.form.events.MessageBoxClosedEvent;
 import kd.bos.form.field.BasedataEdit;
 import kd.bos.form.field.events.BeforeBasedataSetValueEvent;
 import kd.bos.form.field.events.BeforeBasedataSetValueListener;
 import kd.bos.form.field.events.BeforeF7SelectEvent;
 import kd.bos.form.field.events.BeforeF7SelectListener;
+import kd.bos.form.operate.AbstractOperate;
 import kd.bos.form.plugin.AbstractFormPlugin;
+import kd.bos.lang.Lang;
 import kd.bos.list.ListShowParameter;
 import kd.bos.logging.Log;
 import kd.bos.logging.LogFactory;
 import kd.bos.mvc.bill.BillView;
-import kd.bos.orm.ORM;
 import kd.bos.orm.query.QCP;
 import kd.bos.orm.query.QFilter;
 import kd.bos.orm.util.CollectionUtils;
 import kd.bos.permission.api.HasPermOrgResult;
 import kd.bos.servicehelper.basedata.BaseDataServiceHelper;
+import kd.bos.servicehelper.coderule.CodeRuleServiceHelper;
+import kd.bos.servicehelper.model.PermissionStatus;
 import kd.bos.servicehelper.permission.PermissionServiceHelper;
-import kd.hr.haos.business.domain.common.service.impl.BaseDataHelper;
 import kd.hr.hbp.business.servicehelper.HRBaseServiceHelper;
 import kd.hr.hbp.common.model.AuthorizedOrgResult;
 import kd.hr.hbp.common.util.HRDateTimeUtils;
 import kd.hr.hbp.common.util.HRDynamicObjectUtils;
+import kd.hr.hbp.common.util.HRObjectUtils;
 import kd.hr.hbp.common.util.HRStringUtils;
 import kd.hr.hbp.common.util.concurrent.NullableConcurrentHashMap;
-import kd.hr.homs.business.domain.batchbill.repository.AdminOrgBatchChgHelper;
 import kd.sdk.hr.hdm.common.enums.reg.RegBillStatusEnum;
-import nckd.jxccl.hrmp.hbpm.business.hr.PositionBillClosedCallBackService;
-import nckd.jxccl.hrmp.hbpm.business.hr.PositionBillConfirmCallBackService;
-import nckd.jxccl.hrmp.hbpm.business.hr.PositionBillPropertyChangedService;
-import nckd.jxccl.hrmp.hbpm.business.hr.PositionBillServiceHelper;
+import nckd.jxccl.hrmp.hbpm.business.hr.service.impl.PositionBillAfterBindDataService;
+import nckd.jxccl.hrmp.hbpm.business.hr.service.impl.PositionBillBeforeBindDataService;
+import nckd.jxccl.hrmp.hbpm.business.hr.service.impl.PositionBillClosedCallBackService;
+import nckd.jxccl.hrmp.hbpm.business.hr.service.impl.PositionBillConfirmCallBackService;
+import nckd.jxccl.hrmp.hbpm.business.hr.service.impl.PositionBillPropertyChangedService;
+import nckd.jxccl.hrmp.hbpm.business.hr.service.impl.PositionBillServiceHelper;
 import nckd.jxccl.hrmp.hbpm.common.hr.PositionBillConstant;
+import nckd.jxccl.hrmp.hbpm.common.hr.PositionChangeTypeEnum;
 import org.apache.commons.lang3.time.DateUtils;
 
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Date;
 import java.util.EventObject;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Objects;
 
 /**
  * 岗位申请单表单插件
+ * @entity: nckd_positionbill
+ * @from: kd.hr.homs.formplugin.web.orgbatch.AdminOrgBatchBillPlugin
  * @author: jtd
  * @date: 2025-10-25 13:38
  */
@@ -82,23 +101,85 @@ public class PositionBillFormPlugin extends AbstractFormPlugin implements Before
     private final Map<String, Map<?, DynamicObject>> baseDataCacheMap = new NullableConcurrentHashMap(3);
 
     @Override
-    public void afterBindData(EventObject e) {
-        super.afterBindData(e);
+    public void afterCreateNewData(EventObject e) {
+        DynamicObject org = getModel().getDataEntity().getDynamicObject(PositionBillConstant.ORG_KEY);
+        if (org == null) {
+            // 获取是否有查询权限
+            HasPermOrgResult hrPermOrg = PermissionServiceHelper.getAllPermOrgs(RequestContext.get().getCurrUserId(), "21", PositionBillConstant.HOMS_APP, PositionBillConstant.HAOS_ADMINORGDETAIL_ENTITY, PermissionStatus.View, true);
+            List<Long> hasPermOrgs = hrPermOrg.getHasPermOrgs();
+            if (!Objects.isNull(hasPermOrgs) && hasPermOrgs.size() != 0) {
+                if (hasPermOrgs.contains(RequestContext.get().getOrgId())) {
+                    getModel().setValue(PositionBillConstant.ORG_KEY, RequestContext.get().getOrgId());
+                } else {
+                    getModel().setValue(PositionBillConstant.ORG_KEY, hasPermOrgs.get(0));
+                }
+            } else {
+                LOG.error("PositionBillFormPlugin can not get any org");
+            }
+        }
+
+        org = getModel().getDataEntity().getDynamicObject(PositionBillConstant.ORG_KEY);
+        if (org == null) {
+            setBillNo(e);
+        } else {
+            long orgid = org.getLong(PositionBillConstant.ID_KEY);
+            boolean cudeRule = CodeRuleServiceHelper.isExist(PositionBillConstant.NCKD_POSITIONBILL_ENTITY, getModel().getDataEntity(), String.valueOf(orgid));
+            if (!cudeRule) {
+                setBillNo(e);
+            }
+        }
 
-        // 生成临时单据ID
-        genBillIdIfNotExist();
-        getModel().setDataChanged(false);
     }
 
-    /**
-     * 生成临时单据ID
-     */
-    private void genBillIdIfNotExist() {
-        long billId = getModel().getDataEntity().getLong(PositionBillConstant.ID_KEY);
-        if (billId == 0L) {
-            billId = ORM.create().genLongId(getView().getEntityId());
-            getModel().setValue(PositionBillConstant.ID_KEY, billId);
+    private void setBillNo(EventObject e) {
+        Map map = new HashMap();
+        Map item = new HashMap();
+        Map emptyTip = new HashMap();
+        map.put("item", item);
+        item.put("emptytip", emptyTip);
+        Lang lang = Lang.get();
+        emptyTip.put(lang.getLocale(), "");
+        getView().updateControlMetadata(PositionBillConstant.BILL_NO_KEY, map);
+        getModel().setValue(PositionBillConstant.BILL_NO_KEY, "");
+        getView().setEnable(Boolean.TRUE, PositionBillConstant.BILL_NO_KEY);
+        super.afterCreateNewData(e);
+    }
+
+    @Override
+    public void loadCustomControlMetas(LoadCustomControlMetasArgs e) {
+        super.loadCustomControlMetas(e);
+        BillShowParameter billShowParameter = (BillShowParameter) e.getSource();
+        LocaleString caption = billShowParameter.getFormConfig().getCaption();
+        if (billShowParameter.getPkId() == null) {
+            caption.setLocaleValue("岗位调整申请");
+        } else {
+            HRBaseServiceHelper hrBaseServiceHelper = new HRBaseServiceHelper(PositionBillConstant.NCKD_POSITIONBILL_ENTITY);
+            DynamicObject billObject = hrBaseServiceHelper.queryOne(String.join(",", PositionBillConstant.ID_KEY, PositionBillConstant.BILL_NO_KEY), billShowParameter.getPkId());
+            if (billObject != null) {
+                caption.setLocaleValue(String.format(Locale.ROOT, "岗位调整申请-%s", billObject.getString(PositionBillConstant.BILL_NO_KEY)));
+            }
         }
+
+    }
+
+    @Override
+    public void beforeBindData(EventObject e) {
+        super.beforeBindData(e);
+
+        long startTime = System.currentTimeMillis();
+        PositionBillBeforeBindDataService beforeBindDataService = new PositionBillBeforeBindDataService(getView());
+        beforeBindDataService.beforeBindData(e);
+        LOG.info(String.format(Locale.ROOT, "PositionBillFormPlugin beforeBindData() time cost is: %s", System.currentTimeMillis() - startTime));
+    }
+
+    @Override
+    public void afterBindData(EventObject e) {
+        super.afterBindData(e);
+
+        long startTime = System.currentTimeMillis();
+        PositionBillAfterBindDataService afterBindDataService = new PositionBillAfterBindDataService(getView());
+        afterBindDataService.afterBindData();
+        LOG.info(String.format(Locale.ROOT, "PositionBillFormPlugin afterBindData() time cost is: %s", System.currentTimeMillis() - startTime));
     }
 
     public void beforeBasedataSetValue(BeforeBasedataSetValueEvent beforeBasedataSetValueEvent) {
@@ -109,24 +190,20 @@ public class PositionBillFormPlugin extends AbstractFormPlugin implements Before
             BasedataEdit basedataEdit = (BasedataEdit) source;
             IDataEntityProperty property = basedataEdit.getProperty();
             if (property instanceof PositionFieldProp && basedataEdit.isF7MultipleSelect()) {
-                DynamicObject billDy = getModel().getDataEntity();
-                String fieldKey = basedataEdit.getFieldKey();
                 String baseEntityId = ((BasedataProp) property).getBaseEntityId();
                 HRBaseServiceHelper helper = new HRBaseServiceHelper(baseEntityId);
                 DynamicObject[] baseDataDys = helper.loadDynamicObjectArray(rows.stream().map(ListSelectedRow::getPrimaryKeyValue).distinct().toArray());
-                //Set<Long> parentBoIds = Sets.newHashSetWithExpectedSize(baseDataDys.length);
                 Map<Object, DynamicObject> baseDataDyMap = Maps.newHashMapWithExpectedSize(baseDataDys.length);
 
-                for(DynamicObject orgDy : baseDataDys) {
-                    //parentBoIds.add(orgDy.getLong(String.join(".", PositionBillConstant.PARENT_KEY, PositionBillConstant.BOID_KEY)));
-                    baseDataDyMap.put(orgDy.getPkValue(), orgDy);
+                for(DynamicObject positionDy : baseDataDys) {
+                    baseDataDyMap.put(positionDy.getPkValue(), positionDy);
                 }
 
                 baseDataCacheMap.put(baseEntityId, baseDataDyMap);
             }
         }
 
-    }// 280
+    }
 
     @Override
     public void propertyChanged(PropertyChangedArgs e) {
@@ -137,9 +214,132 @@ public class PositionBillFormPlugin extends AbstractFormPlugin implements Before
         propertyChangedService.propertyChanged(e);
     }
 
+    public void confirmCallBack(MessageBoxClosedEvent event) {
+        super.confirmCallBack(event);
+
+        PositionBillConfirmCallBackService confirmCallBackService = new PositionBillConfirmCallBackService(getView());
+        confirmCallBackService.confirmCallBack(event);
+    }
+
+    @Override
+    public void closedCallBack(ClosedCallBackEvent closedCallBackEvent) {
+        super.closedCallBack(closedCallBackEvent);
+
+        PositionBillClosedCallBackService closedCallBackService = new PositionBillClosedCallBackService(getView());
+        closedCallBackService.closedCallBack(closedCallBackEvent);
+    }
+
     @Override
-    public void afterDoOperation(AfterDoOperationEventArgs afterDoOperationEventArgs) {
-        super.afterDoOperation(afterDoOperationEventArgs);
+    public void beforeClosed(BeforeClosedEvent e) {
+        super.beforeClosed(e);
+
+        String isCancelOverFlag = getView().getPageCache().get(PositionBillConstant.PC_ISCANCELOVER);
+        if (HRStringUtils.isNotEmpty(isCancelOverFlag) && Boolean.TRUE.toString().equals(isCancelOverFlag)) {
+            getModel().setDataChanged(false);
+            getView().getPageCache().put(PositionBillConstant.PC_ISCANCELOVER, Boolean.FALSE.toString());
+        } else {
+            boolean hasEntryData = false;
+            DynamicObject dataEntity = getModel().getDataEntity(Boolean.TRUE);
+
+            for (PositionChangeTypeEnum changeTypeEnum : PositionChangeTypeEnum.values()) {
+                DynamicObjectCollection entryDynColl = dataEntity.getDynamicObjectCollection(changeTypeEnum.getTag(PositionBillConstant.NCKD_ENTRYENTITYUNDERLINE_KEY));
+                hasEntryData = entryDynColl != null && entryDynColl.size() > 0;
+                if (hasEntryData) {
+                    break;
+                }
+            }
+
+            HRBaseServiceHelper orgBatchChgBillHelper = new HRBaseServiceHelper(PositionBillConstant.NCKD_POSITIONBILL_ENTITY);
+            long billId = getModel().getDataEntity().getLong(PositionBillConstant.ID_KEY);
+            QFilter idFilter = new QFilter(PositionBillConstant.ID_KEY, QCP.equals, billId);
+            boolean isExistFromDb = orgBatchChgBillHelper.isExists(idFilter);
+            if (hasEntryData && !isExistFromDb) {
+                e.setCancel(true);
+                ConfirmCallBackListener confirmCallBacks = new ConfirmCallBackListener(PositionBillConstant.CB_CLOSE_BILL, this);
+                Map<Integer, String> btnNameMaps = new HashMap();
+                btnNameMaps.put(MessageBoxResult.Cancel.getValue(), "返回编辑");
+                btnNameMaps.put(MessageBoxResult.Yes.getValue(), "直接退出");
+                MessageBoxOptions options = MessageBoxOptions.OKCancel;
+                String msg = "检测到您有更改内容,是否不保存直接退出?若直接退出,将丢失这些更改。";
+                getView().showConfirm(msg, getModel().getChangeDesc(), options, ConfirmTypes.Save, confirmCallBacks, btnNameMaps);
+            }
+
+        }
+    }
+
+    private boolean executeSaveOperation(String operateKey, OperateOption operateOption) {
+        OperateOption option = OperateOption.create();
+        if (operateOption != null) {
+            option.mergeValue(operateOption);
+        }
+
+        option.setVariableValue(OperateOptionConst.MUTEX_IGNORE_VALIDATION, Boolean.TRUE.toString());
+        option.setVariableValue(PositionBillConstant.OP_OPERATE_KEY, operateKey);
+        option.setVariableValue(OperateOptionConst.ISSHOWMESSAGE, Boolean.FALSE.toString());
+        OperationResult saveOperationResult = getView().invokeOperation(PositionBillConstant.SAVE_NO_LOG_OP, option);
+        if (!saveOperationResult.isSuccess()) {
+            getView().showOperationResult(saveOperationResult);
+            return false;
+        } else {
+            return true;
+        }
+    }
+
+    @Override
+    public void beforeDoOperation(BeforeDoOperationEventArgs args) {
+        super.beforeDoOperation(args);
+        AbstractOperate operate = (AbstractOperate) args.getSource();
+        String operateKey = operate.getOperateKey();
+        OperateOption option = operate.getOption();
+        if (getAllEntrySize() == 0) {
+            option.setVariableValue(OperateOptionConst.ISHASRIGHT, Boolean.TRUE.toString());
+            option.setVariableValue(OperateOptionConst.SKIPCHECKPERMISSION, Boolean.TRUE.toString());
+        }
+
+        if (HRStringUtils.equals("import_multientry_hr", operate.getOperateKey())) {
+            if (getModel().getValue(PositionBillConstant.ORG_KEY) == null) {
+                getView().showTipNotification("请先填写组织体系管理组织。");
+                args.setCancel(Boolean.TRUE);
+                return;
+            }
+
+            DynamicObject dataEntity = getModel().getDataEntity(Boolean.TRUE);
+            long billId = dataEntity.getLong(PositionBillConstant.ID_KEY);
+            HRBaseServiceHelper serviceHelper = new HRBaseServiceHelper(PositionBillConstant.NCKD_POSITIONBILL_ENTITY);
+            DynamicObject[] dynamicObjects = serviceHelper.query(PositionBillConstant.BILL_STATUS_KEY, new QFilter[]{new QFilter(PositionBillConstant.ID_KEY, QCP.equals, billId)});
+            if (dynamicObjects.length > 0 && !Sets.newHashSet(new String[]{RegBillStatusEnum.TEMPSTORAGE.getCode(), RegBillStatusEnum.WAITRESUBMIT.getCode()}).contains(dynamicObjects[0].getString(PositionBillConstant.BILL_STATUS_KEY))) {
+                String auditStatus = dynamicObjects[0].getString(PositionBillConstant.BILL_STATUS_KEY);
+                getView().showTipNotification(String.format(Locale.ROOT, "%s的单据不能导入。", RegBillStatusEnum.getName(auditStatus)));
+                args.setCancel(Boolean.TRUE);
+            }
+        }
+
+        if (HRStringUtils.equalsAny(operateKey, PositionBillConstant.SAVE_OP, PositionBillConstant.SUBMIT_OP, PositionBillConstant.SUBMITEFFECT_OP)) {
+            if (HRStringUtils.equals(operateKey, PositionBillConstant.SUBMIT_OP) || HRStringUtils.equals(operateKey, PositionBillConstant.SUBMITEFFECT_OP)) {
+                if (!executeSaveOperation(operateKey, operate.getOption())) {
+                    args.setCancel(true);
+                } else {
+                    option.setVariableValue(OperateOptionConst.MUTEX_IGNORE_VALIDATION, Boolean.TRUE.toString());
+                }
+            }
+        }
+
+        if (PositionBillConstant.DELETE_ROWS_ADD_OP.equals(operateKey)) {
+            EntryGrid entryGrid = getView().getControl(PositionBillConstant.NCKD_ENTRYENTITY_ADD_KEY);
+            int[] selectRows = entryGrid.getSelectRows();
+            operate.getOption().setVariableValue(PositionBillConstant.OP_ROW_INDEX, JSONObject.toJSONString(selectRows));
+        }
+
+        if (HRStringUtils.equals(getView().getFormShowParameter().getAppId(), PositionBillConstant.WFTASK_APP)) {
+            option.setVariableValue(OperateOptionConst.ISHASRIGHT, Boolean.TRUE.toString());
+            option.setVariableValue(OperateOptionConst.SKIPCHECKPERMISSION, Boolean.TRUE.toString());
+        }
+
+    }
+
+    @Override
+    public void afterDoOperation(AfterDoOperationEventArgs eventArgs) {
+        super.afterDoOperation(eventArgs);
 
         OperationStatus status = getView().getFormShowParameter().getStatus();
         if (HRStringUtils.equals(getView().getFormShowParameter().getAppId(), PositionBillConstant.WFTASK_APP)) {
@@ -147,57 +347,81 @@ public class PositionBillFormPlugin extends AbstractFormPlugin implements Before
             getView().getFormShowParameter().setStatus(OperationStatus.EDIT);
             ((BillShowParameter) getView().getFormShowParameter()).setBillStatus(BillOperationStatus.EDIT);
             String billStatus = ((BillEntityType) getModel().getDataEntityType()).getBillStatus();
-            getModel().setValue(billStatus, "A");
+            getModel().setValue(billStatus, RegBillStatusEnum.TEMPSTORAGE.getCode());
             getModel().setDataChanged(Boolean.FALSE);
         }
 
-        OperationResult afterOperationResult = afterDoOperationEventArgs.getOperationResult();
-        if (!(afterOperationResult == null || afterOperationResult.isSuccess())) {
-            return;
-        }
+        String opKey = eventArgs.getOperateKey();
+        if (!PositionBillConstant.VIEWFLOWCHART_OP.equals(opKey)) {
+            OperationResult afterOperationResult = eventArgs.getOperationResult();
+            if (afterOperationResult != null && !afterOperationResult.isSuccess()) {
+                if (PositionBillConstant.SUBMIT_OP.equals(opKey)) {
+                    afterSubmitError(afterOperationResult);
+                }
 
-        String opKey = afterDoOperationEventArgs.getOperateKey();
-        switch (opKey) {
-            case PositionBillConstant.NEWENTRY_ADD_OP:
-                PositionBillServiceHelper.openViewForm(getView(), PositionBillConstant.ADD_TAG, getPluginName(), null);
-                break;
-            case PositionBillConstant.EDIT_ADD_OP:
-                openEditAddPage(status, getModel(), getView());
-                break;
-            case PositionBillConstant.EDIT_CHANGE_OP:
-                PositionBillServiceHelper.entryEntityMore(getModel(), getView(), PositionBillConstant.CHANGE_TAG, status);
-                break;
-            case PositionBillConstant.DELETE_ROWS_ADD_OP:
-            case PositionBillConstant.DELETE_ROWS_CHANGE_OP:
-                deleteRowsConfirm(opKey);
-                break;
+            } else {
+                switch (opKey) {
+                    case PositionBillConstant.NEWENTRY_ADD_OP:
+                        PositionBillServiceHelper.openViewForm(getView(), PositionBillConstant.ADD_TAG, getPluginName(), null);
+                        break;
+                    case PositionBillConstant.EDIT_ADD_OP:
+                        openEditAddPage(status, getModel(), getView());
+                        break;
+                    case PositionBillConstant.EDIT_CHANGE_OP:
+                        PositionBillServiceHelper.entryEntityMore(getModel(), getView(), PositionBillConstant.CHANGE_TAG, status, getPluginName());
+                        break;
+                    case PositionBillConstant.DELETE_ROWS_ADD_OP:
+                    case PositionBillConstant.DELETE_ROWS_CHANGE_OP:
+                        deleteRowsConfirm(opKey);
+                        break;
+                    case PositionBillConstant.SUBMIT_OP:
+                        afterSubmit();
+                }
+            }
 
         }
     }
 
-    public void confirmCallBack(MessageBoxClosedEvent event) {
-        super.confirmCallBack(event);
+    private void afterSubmitError(OperationResult operationResult) {
+        boolean needWfAssignPersons = operationResult.isNeedWfAssignPersons();
+        List<IOperateInfo> allErrorOrValidateInfo = operationResult.getAllErrorOrValidateInfo();
+        String errorMsg;
+        if (allErrorOrValidateInfo.isEmpty()) {
+            errorMsg = operationResult.getMessage();
+        } else {
+            errorMsg = operationResult.getAllErrorOrValidateInfo().get(0).getMessage();
+        }
 
-        PositionBillConfirmCallBackService confirmCallBackService = new PositionBillConfirmCallBackService(getView());
-        confirmCallBackService.confirmCallBack(event);
+        if (errorMsg != null && !errorMsg.isEmpty() || !needWfAssignPersons) {
+            String exist = "已存在";
+            if (errorMsg != null && !errorMsg.contains(exist)) {
+                getView().showErrorNotification(errorMsg);
+            }
+
+        }
     }
 
-    @Override
-    public void closedCallBack(ClosedCallBackEvent closedCallBackEvent) {
-        super.closedCallBack(closedCallBackEvent);
+    private void afterSubmit() {
+        LOG.info("afterDoSubmit:" + getModel().getDataEntity().get(PositionBillConstant.BILL_NO_KEY));
+        LOG.info("afterDoSubmit getEntityId refresh:" + getView().getFormShowParameter().getAppId());
+        if (HRStringUtils.equals(getView().getFormShowParameter().getAppId(), PositionBillConstant.WFTASK_APP)) {
+            LOG.info("afterDoSubmit refresh:" + getModel().getDataEntity().get(PositionBillConstant.BILL_NO_KEY));
+            getView().getParentView().invokeOperation(PositionBillConstant.REFRESH_OP);
+            getView().invokeOperation(PositionBillConstant.CLOSE_OP);
+        } else {
+            getView().updateView();
+        }
 
-        PositionBillClosedCallBackService closedCallBackService = new PositionBillClosedCallBackService(getView());
-        closedCallBackService.closedCallBack(closedCallBackEvent);
     }
 
     private void deleteRowsConfirm(String callBackId) {
         long id = getModel().getDataEntity().getLong(PositionBillConstant.ID_KEY);
-        HRBaseServiceHelper helper = new HRBaseServiceHelper(PositionBillConstant.HBPM_POSITIONHR);
+        HRBaseServiceHelper helper = new HRBaseServiceHelper(PositionBillConstant.NCKD_POSITIONBILL_ENTITY);
         QFilter idFilter = new QFilter(PositionBillConstant.ID_KEY, QCP.equals, id);
         DynamicObject dyn = helper.queryOne(String.join(",", PositionBillConstant.ID_KEY, PositionBillConstant.BILL_STATUS_KEY), new QFilter[]{idFilter});
         String billstatus;
         if (Objects.isNull(dyn)) {
-            billstatus = "A";
+            billstatus = RegBillStatusEnum.TEMPSTORAGE.getCode();
         } else {
             billstatus = dyn.getString(PositionBillConstant.BILL_STATUS_KEY);
         }
@@ -205,14 +429,14 @@ public class PositionBillFormPlugin extends AbstractFormPlugin implements Before
         boolean enableDeleteForUserPage = billstatus.equals(RegBillStatusEnum.TEMPSTORAGE.getCode()) || billstatus.equals(RegBillStatusEnum.WAITRESUBMIT.getCode());
         boolean enableDeleteForAuditPage = HRStringUtils.equals(getView().getFormShowParameter().getAppId(), PositionBillConstant.WFTASK_APP) && billstatus.equals(RegBillStatusEnum.ALREADYSUBMIT.getCode());
         if (!enableDeleteForUserPage && !enableDeleteForAuditPage) {
-            String auditStatusName = AdminOrgBatchChgHelper.getAuditstatusName(billstatus);
+            String auditStatusName = RegBillStatusEnum.getName(billstatus);
             getView().showErrorNotification(String.format("%s的单据不能删除调整明细。", auditStatusName));
         } else {
-            EntryGrid coopRelEntryGrid = getView().getControl(PositionBillConstant.NCKD_ENTRYENTITY_ADD_KEY);
-            if (null == coopRelEntryGrid) {
+            EntryGrid strategyEntryGrid = getView().getControl(String.join("_", PositionBillConstant.NCKD_ENTRYENTITY, callBackId.substring(callBackId.lastIndexOf("_")+1)));
+            if (null == strategyEntryGrid) {
                 getView().showTipNotification("请选中需要删除的行。");
             } else {
-                int[] selectRows = coopRelEntryGrid.getSelectRows();
+                int[] selectRows = strategyEntryGrid.getSelectRows();
                 int length = selectRows.length;
                 if (selectRows.length > 0) {
                     ConfirmCallBackListener deleteEntryCallBackListener = new ConfirmCallBackListener(callBackId, this);
@@ -230,25 +454,27 @@ public class PositionBillFormPlugin extends AbstractFormPlugin implements Before
         int row = strategyEntryGrid.getEntryState().getFocusRow();
         DynamicObject addDy = iDataModel.getDataEntity(true).getDynamicObjectCollection(PositionBillConstant.NCKD_ENTRYENTITY_ADD_KEY).get(row);
         Long adddyId = addDy.getLong(PositionBillConstant.ID_KEY);
-        Map map = HRDynamicObjectUtils.convertDynamicObjectToMap(addDy);
+        DynamicObject dataEntity = iDataModel.getDataEntity(true);
+        DynamicObject dynamicObject = dataEntity.getDynamicObjectCollection(PositionBillConstant.NCKD_ENTRYENTITY_ADD_KEY).get(row);
+        Map map = HRDynamicObjectUtils.convertDynamicObjectToMap(dynamicObject);
         BillShowParameter formShowParameter = new BillShowParameter();
         formShowParameter.setFormId(PositionBillConstant.NCKD_POSBILLENTRYADD_ENTITY);
-        formShowParameter.setCustomParam("position_bsed", iDataModel.getValue(PositionBillConstant.NCKD_EFFDT) == null ? HRDateTimeUtils.getNowDateTime().getTime() : ((Date) iDataModel.getValue(PositionBillConstant.NCKD_EFFDT)).getTime());
+        formShowParameter.setCustomParam(PositionBillConstant.CP_POSITION_BSED, iDataModel.getValue(PositionBillConstant.NCKD_EFFDT) == null ? HRDateTimeUtils.getNowDateTime().getTime() : ((Date) iDataModel.getValue(PositionBillConstant.NCKD_EFFDT)).getTime());
         formShowParameter.setPkId(adddyId);
         formShowParameter.setStatus(status);
-        formShowParameter.setCustomParam("billid", iDataModel.getDataEntity().getLong(PositionBillConstant.ID_KEY));
+        formShowParameter.setCustomParam(PositionBillConstant.CP_BILLID, iDataModel.getDataEntity().getLong(PositionBillConstant.ID_KEY));
         if (HRStringUtils.equals(iFormView.getFormShowParameter().getAppId(), PositionBillConstant.WFTASK_APP)) {
             formShowParameter.setHasRight(true);
         }
 
         if (!status.equals(OperationStatus.VIEW)) {
-            formShowParameter.setCloseCallBack(new CloseCallBack(getPluginName(), PositionBillConstant.ADD_TAG));
+            formShowParameter.setCloseCallBack(new CloseCallBack(getPluginName(), PositionBillConstant.NCKD_ENTRYENTITY_ADD_KEY));
         }
 
-        formShowParameter.setCustomParam("selectObject", SerializationUtils.toJsonString(map));
+        formShowParameter.setCustomParam(PositionBillConstant.CP_SELECTOBJECT, SerializationUtils.toJsonString(map));
         formShowParameter.getOpenStyle().setShowType(ShowType.Modal);
-        //formShowParameter.setCustomParam("OP_VALIDATOR_BILL_ORG_ALL_CHANGE_ORG_KEY", getThisBillAllValidateDataStr(dynamicObject));
-        //formShowParameter.setCustomParam("OP_VALIDATOR_BILL_ORG_NEW_ORG_NUMBERS_KEY", getThisBillOrgNumbersStr(dynamicObject));
+        formShowParameter.setCustomParam(PositionBillConstant.OP_VALIDATOR_BILL_POSITION_ALL_CHANGE_POSITION_KEY, PositionBillServiceHelper.getThisBillAllValidateDataStr(dataEntity));
+        formShowParameter.setCustomParam(PositionBillConstant.OP_VALIDATOR_BILL_POSITION_NEW_POSITION_NUMBERS_KEY, PositionBillServiceHelper.getThisBillPositionNumbersStr(dataEntity));
         iFormView.showForm(formShowParameter);
     }
 
@@ -256,8 +482,8 @@ public class PositionBillFormPlugin extends AbstractFormPlugin implements Before
     public void registerListener(EventObject e) {
         super.registerListener(e);
 
-        EntryGrid entryGrid = getControl(String.join("_", PositionBillConstant.NCKD_ENTRYENTITY, PositionBillConstant.CHANGE_TAG));
-        //entryGrid.addDataBindListener(this);
+        EntryGrid entryGrid = getControl(PositionBillConstant.NCKD_ENTRYENTITY_CHANGE_KEY);
+        entryGrid.addDataBindListener(this);
 
         for(String registerBeforeF7Listener : getRegisterBeforeF7ListenerControlList()) {
             BasedataEdit basedataEdit = getControl(registerBeforeF7Listener);
@@ -270,7 +496,7 @@ public class PositionBillFormPlugin extends AbstractFormPlugin implements Before
     }
 
     private List<String> getRegisterBeforeF7ListenerControlList() {
-        return Arrays.asList(PositionBillConstant.NCKD_DISORG_KEY, String.join("_", PositionBillConstant.NCKD_ORG, PositionBillConstant.CHANGE_TAG), String.join("_", PositionBillConstant.NCKD_POSITION, PositionBillConstant.CHANGE_TAG), String.join("_", PositionBillConstant.NCKD_POSITION, PositionBillConstant.CHANGE_TAG));
+        return Arrays.asList(PositionBillConstant.NCKD_DISORG_KEY, String.join("_", PositionBillConstant.ORG_KEY, PositionBillConstant.CHANGE_TAG), String.join("_", PositionBillConstant.NCKD_POSITION_KEY, PositionBillConstant.CHANGE_TAG), String.join("_", PositionBillConstant.NCKD_PARENT, PositionBillConstant.CHANGE_TAG));
     }
 
     @Override
@@ -278,9 +504,9 @@ public class PositionBillFormPlugin extends AbstractFormPlugin implements Before
         String fieldKey = beforeF7SelectEvent.getProperty().getName();
         setFuzzySearchAuthFilter(beforeF7SelectEvent);
         replaceFormIdByFieldKey(beforeF7SelectEvent);
-        if (PositionBillConstant.NCKD_DISORG_KEY.equals(fieldKey)) {// 780
+        if (PositionBillConstant.NCKD_DISORG_KEY.equals(fieldKey)) {
             beforeF7SelectEvent.getFormShowParameter().setCaption("签发组织");
-            beforeF7SelectEvent.getCustomQFilters().add(BaseDataHelper.getAdminOrgBaseDataFilter(PositionBillConstant.NCKD_POSITIONBILL_ENTITY, Collections.singletonList(((DynamicObject) getView().getModel().getValue(PositionBillConstant.ORG_KEY)).getLong(PositionBillConstant.ID_KEY))));
+            beforeF7SelectEvent.getCustomQFilters().add(new QFilter(PositionBillConstant.ORG_KEY, QCP.equals, ((DynamicObject) getView().getModel().getValue(PositionBillConstant.ORG_KEY)).getLong(PositionBillConstant.ID_KEY)));
         } else {
             int rowIndex = beforeF7SelectEvent.getRow();
             String suffix = getSuffixByFieldKey(fieldKey);
@@ -291,16 +517,25 @@ public class PositionBillFormPlugin extends AbstractFormPlugin implements Before
             MainEntityType entityType = EntityMetadataCache.getDataEntityType(getView().getEntityId());
             IDataEntityProperty property = entityType.getAllFields().get(fieldKey);
             IDataEntityType parent = property.getParent();
-            Date effectDate = (Date) getModel().getValue(PositionBillConstant.NCKD_EFFDT);
-            if (checkOrgValue(beforeF7SelectEvent, property, parent)) {
+            if (!checkOrgValue(beforeF7SelectEvent, property, parent)) {
                 ListShowParameter showParameter = (ListShowParameter) beforeF7SelectEvent.getFormShowParameter();
-                if (fieldKey.equals(String.join("_", PositionBillConstant.NCKD_POSITION, PositionBillConstant.CHANGE_TAG))) {
-                    showParameter.getCustomParams().put("searchdate", date);
-                    AdminOrgBatchChgHelper.filterF7Org(getView(), beforeF7SelectEvent, null);
+                if (fieldKey.equals(String.join("_", PositionBillConstant.NCKD_POSITION_KEY, PositionBillConstant.CHANGE_TAG))) {
+                    showParameter.getCustomParams().put(PositionBillConstant.CP_SEARCHDATE, date);
+                    PositionBillServiceHelper.filterF7Org(getView(), beforeF7SelectEvent, null);
                     setFilterByOrg(beforeF7SelectEvent);
                 } else if (fieldKey.equals(String.join("_", PositionBillConstant.NCKD_PARENT, PositionBillConstant.CHANGE_TAG))) {
-                    // 岗位变更-上级岗位业务逻辑
-                } else if (fieldKey.equals(String.join("_", PositionBillConstant.NCKD_ORG, PositionBillConstant.CHANGE_TAG))) {
+                    DynamicObject position = focusEntryDyn.getDynamicObject(String.join("_", PositionBillConstant.NCKD_POSITION_KEY, PositionBillConstant.CHANGE_TAG));
+                    PositionBillServiceHelper.setParentFilter(getView(), position, beforeF7SelectEvent);
+                    beforeF7SelectEvent.getFormShowParameter().setCaption("上级岗位");
+                    if (!HRObjectUtils.isEmpty(position)) {
+                        // 过滤下级岗位
+                        Date effDate = HRObjectUtils.isEmpty(getModel().getValue(PositionBillConstant.NCKD_EFFDT)) ? DateUtils.truncate(new Date(), 5) : (Date) getModel().getValue(PositionBillConstant.NCKD_EFFDT);
+                        List<Long> positionIds = PositionBillServiceHelper.getPositionAndChildren(position.getLong(PositionBillConstant.BOID_KEY), effDate);
+                        if (!positionIds.isEmpty()) {
+                            beforeF7SelectEvent.getCustomQFilters().add(new QFilter(PositionBillConstant.ID_KEY, QCP.not_in, positionIds));
+                        }
+                    }
+                } else if (fieldKey.equals(String.join("_", PositionBillConstant.NCKD_ORG_KEY, PositionBillConstant.CHANGE_TAG))) {
                     HasPermOrgResult permOrgResult = PermissionServiceHelper.getUserHasPermOrgs(RequestContext.get().getCurrUserId(), false);
                     if (!permOrgResult.hasAllOrgPerm()) {
                         List<Long> hasPermOrgs = permOrgResult.getHasPermOrgs();
@@ -322,15 +557,15 @@ public class PositionBillFormPlugin extends AbstractFormPlugin implements Before
             DynamicObjectCollection dynamicObjectCollection = getModel().getDataEntity(true).getDynamicObjectCollection(parent.getName());
             DynamicObject dynamicObject = dynamicObjectCollection.get(beforeF7SelectEvent.getRow());
             String name = property.getName();
-            String suffix = name.substring(name.lastIndexOf("_") + 1);
-            String fieldKey = name.replace("_"+suffix, "");
-            if (PositionBillConstant.NCKD_ORG.equals(fieldKey)) {
+            String lineSuffix = name.substring(name.lastIndexOf("_"));
+            String fieldKey = PositionBillServiceHelper.getNoLineSuffixProp(name, lineSuffix);
+            if (PositionBillConstant.ORG_KEY.equals(fieldKey)) {
                 return false;
-            } else if (!dynamicObject.getDataEntityType().getProperties().containsKey(String.join("_", PositionBillConstant.NCKD_ORG, suffix))) {
+            } else if (!dynamicObject.getDataEntityType().getProperties().containsKey(String.join(PositionBillConstant.ORG_KEY +lineSuffix))) {
                 return false;
             } else {
-                Boolean baseDataCtrl = BaseDataServiceHelper.checkBaseDataCtrl(((BasedataProp)property).getBaseEntityId());
-                DynamicObject orgDy = dynamicObject.getDynamicObject(String.join("_", PositionBillConstant.NCKD_ORG, suffix));
+                Boolean baseDataCtrl = BaseDataServiceHelper.checkBaseDataCtrl(((BasedataProp) property).getBaseEntityId());
+                DynamicObject orgDy = dynamicObject.getDynamicObject(String.join(PositionBillConstant.ORG_KEY +lineSuffix));
                 if (orgDy == null && baseDataCtrl) {
                     getView().showTipNotification("请先选择组织体系管理组织。");
                     beforeF7SelectEvent.setCancel(true);
@@ -347,7 +582,7 @@ public class PositionBillFormPlugin extends AbstractFormPlugin implements Before
         if (CollectionUtils.isEmpty(orgIdList)) {
             beforeF7SelectEvent.getCustomQFilters().add(new QFilter("1", QCP.not_equals, 1));
         } else {
-            beforeF7SelectEvent.getCustomQFilters().add(new QFilter(String.join(".", PositionBillConstant.ADMINORG, PositionBillConstant.ORG_KEY), QCP.in, orgIdList));
+            beforeF7SelectEvent.getCustomQFilters().add(new QFilter(PositionBillConstant.ORG_KEY, QCP.in, orgIdList));
         }
     }
 
@@ -359,17 +594,22 @@ public class PositionBillFormPlugin extends AbstractFormPlugin implements Before
             }
 
             String fieldName = beforeF7SelectEvent.getProperty().getName();
-            if (PositionBillConstant.NCKD_DISORG_KEY.equals(fieldName) || HRStringUtils.equals(String.join("_", PositionBillConstant.NCKD_POSITION, PositionBillConstant.CHANGE_TAG), fieldName)) {
+            if (PositionBillConstant.NCKD_DISORG_KEY.equals(fieldName) || HRStringUtils.equals(String.join("_", PositionBillConstant.NCKD_POSITION_KEY, PositionBillConstant.CHANGE_TAG), fieldName)) {
                 List<Long> hasPermOrgList = authorizedOrgResult.getHasPermOrgs();
-                beforeF7SelectEvent.getCustomQFilters().add(new QFilter(String.join(".", PositionBillConstant.ADMINORG, PositionBillConstant.BOID_KEY), "in", hasPermOrgList));
+                beforeF7SelectEvent.getCustomQFilters().add(new QFilter(String.join(".", PositionBillConstant.ADMINORG, PositionBillConstant.BOID_KEY), QCP.in, hasPermOrgList));
             }
         }
 
-    }// 1018
+    }
 
     private void replaceFormIdByFieldKey(BeforeF7SelectEvent beforeF7SelectEvent) {
         String fieldKey = beforeF7SelectEvent.getProperty().getName();
-        if (PositionBillConstant.NCKD_DISORG_KEY.equals(fieldKey) || HRStringUtils.equals(String.join("_", PositionBillConstant.NCKD_POSITION, PositionBillConstant.CHANGE_TAG), fieldKey)) {
+        if (HRStringUtils.equals(fieldKey, String.join(PositionBillConstant.NCKD_DISORG_KEY))) {
+            ListShowParameter showParameter = (ListShowParameter) beforeF7SelectEvent.getFormShowParameter();
+            showParameter.setFormId(PositionBillConstant.HAOS_ORGBATCHTREELISTF7_ENTITY);
+        }
+
+        if (HRStringUtils.equalsAny(fieldKey, String.join("_", PositionBillConstant.NCKD_POSITION_KEY, PositionBillConstant.CHANGE_TAG), String.join("_", PositionBillConstant.NCKD_PARENT, PositionBillConstant.CHANGE_TAG))) {
             ListShowParameter showParameter = (ListShowParameter) beforeF7SelectEvent.getFormShowParameter();
             showParameter.setFormId(PositionBillConstant.NCKD_HBPM_POSORGTREELISTF_ENTITY);
         }
@@ -379,4 +619,8 @@ public class PositionBillFormPlugin extends AbstractFormPlugin implements Before
     private static String getSuffixByFieldKey(String fieldKey) {
         return fieldKey.substring(fieldKey.lastIndexOf("_") + 1);
     }
+
+    private int getAllEntrySize() {
+        return Arrays.stream(PositionChangeTypeEnum.values()).mapToInt(changeTypeEnum -> getModel().getEntryEntity(changeTypeEnum.getTag(PositionBillConstant.NCKD_ENTRYENTITYUNDERLINE_KEY)).size()).sum();
+    }
 }

+ 70 - 0
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/form/hr/PositionBillListPlugin.java

@@ -0,0 +1,70 @@
+package nckd.jxccl.hrmp.hbpm.plugin.form.hr;
+
+import kd.bos.context.RequestContext;
+import kd.bos.form.events.FilterContainerSearchClickArgs;
+import kd.bos.form.events.SetFilterEvent;
+import kd.bos.list.events.BeforeShowBillFormEvent;
+import kd.bos.list.plugin.AbstractListPlugin;
+import kd.bos.permission.api.HasPermOrgResult;
+import kd.bos.servicehelper.model.PermissionStatus;
+import kd.bos.servicehelper.org.OrgViewType;
+import kd.bos.servicehelper.permission.PermissionServiceHelper;
+import nckd.jxccl.hrmp.hbpm.common.hr.PositionBillConstant;
+
+import java.util.List;
+import java.util.Objects;
+
+/**
+ *  * 岗位申请单列表插件
+ * @entity: nckd_positionbill
+ * @from: kd.hr.homs.formplugin.web.orgbatch.AdminOrgBatchBillListPlugin
+ * @author: jtd
+ * @date: 2025/12/31 20:48
+ */
+public class PositionBillListPlugin extends AbstractListPlugin {
+
+    @Override
+    public void setFilter(SetFilterEvent setFilterEvent) {
+        super.setFilter(setFilterEvent);
+        setFilterEvent.setOrderBy(String.format("%s desc, %s desc", PositionBillConstant.CREATE_TIME_KEY, PositionBillConstant.BILL_NO_KEY));
+    }
+
+    @Override
+    public void beforeShowBill(BeforeShowBillFormEvent e) {
+        super.beforeShowBill(e);
+        String orgId = getView().getPageCache().get(PositionBillConstant.PC_BUSINESSUNIT);
+        if (Objects.isNull(orgId)) {
+            if (getView().getPageCache().get(PositionBillConstant.PC_ISFROMBILLCLICK) != null) {
+                getView().getPageCache().remove(PositionBillConstant.PC_ISFROMBILLCLICK);
+                e.getParameter().setCustomParam(PositionBillConstant.CP_ISFROMBILLCLICK, Boolean.TRUE.toString());
+            } else {
+                HasPermOrgResult hrPermOrg = PermissionServiceHelper.getAllPermOrgs(RequestContext.get().getCurrUserId(), "21", PositionBillConstant.HOMS_APP, PositionBillConstant.HAOS_ADMINORGDETAIL_ENTITY, PermissionStatus.View, false);
+                List<Long> hasPermOrgs = hrPermOrg.getHasPermOrgs();
+                if (!Objects.isNull(hasPermOrgs) && hasPermOrgs.size() != 0) {
+                    if (hasPermOrgs.contains(RequestContext.get().getOrgId())) {
+                        e.getParameter().setCustomParam(PositionBillConstant.CP_BUSINESSUNIT, String.valueOf(RequestContext.get().getOrgId()));
+                    } else {
+                        e.getParameter().setCustomParam(PositionBillConstant.CP_BUSINESSUNIT, String.valueOf(hasPermOrgs.get(0)));
+                    }
+                }
+            }
+        } else {
+            e.getParameter().setCustomParam(PositionBillConstant.CP_BUSINESSUNIT, orgId);
+        }
+
+        e.getParameter().setCustomParam(PositionBillConstant.CP_FROMLIST, Boolean.TRUE.toString());
+    }
+
+    @Override
+    public void filterContainerAfterSearchClick(FilterContainerSearchClickArgs args) {
+        Object filterValue = args.getFilterValue(String.join(".", PositionBillConstant.ORG_KEY, PositionBillConstant.ID_KEY));
+        if (!Objects.isNull(filterValue) && filterValue instanceof Long) {
+            getView().getPageCache().put(PositionBillConstant.PC_BUSINESSUNIT, filterValue.toString());
+        } else {
+            getView().getPageCache().remove(PositionBillConstant.PC_BUSINESSUNIT);
+        }
+
+        super.filterContainerAfterSearchClick(args);
+    }
+
+}

+ 2 - 1
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/operate/hr/PosBillEntryAddSaveOpPlugin.java

@@ -9,6 +9,7 @@ import nckd.jxccl.hrmp.hbpm.plugin.operate.hr.validator.PositionAddSaveValidator
 /**
  * 岗位申请-岗位新设保存操作插件
  * @entity: nckd_posbillentryadd
+ * @from: kd.hr.homs.opplugin.web.orgbatch.AdminOrgBatchDetailAddSaveOp
  * @author: jtd
  * @date: 2025/12/18 09:57
  */
@@ -19,7 +20,7 @@ public class PosBillEntryAddSaveOpPlugin extends PositionBillEntrySaveOpPlugin {
         super.onAddValidators(e);
 
         OperateOption option = getOption();
-        String onlyValidate = option.getVariableValue(OperateOptionConst.ONLY_VALIDATE, Boolean.FALSE.toString());// 22
+        String onlyValidate = option.getVariableValue(OperateOptionConst.ONLY_VALIDATE, Boolean.FALSE.toString());
         if (Boolean.TRUE.toString().equals(onlyValidate)) {
             e.addValidator(new PositionAddSaveValidator());
         }

+ 26 - 0
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/operate/hr/PosBillEntryChangeSaveOpPlugin.java

@@ -0,0 +1,26 @@
+package nckd.jxccl.hrmp.hbpm.plugin.operate.hr;
+
+import kd.bos.entity.plugin.AddValidatorsEventArgs;
+import nckd.jxccl.hrmp.hbpm.common.hr.PositionBillConstant;
+import nckd.jxccl.hrmp.hbpm.plugin.operate.hr.validator.PositionChangeSaveValidator;
+
+/**
+ * 岗位申请-岗位变更保存操作插件
+ * @entity: nckd_posbillentrychange
+ * @from: kd.hr.homs.opplugin.web.orgbatch.AdminOrgBatchDetailParentSaveOp
+ * @author: jtd
+ * @date: 2025/12/31 21:58
+ */
+public class PosBillEntryChangeSaveOpPlugin extends PositionBillEntrySaveOpPlugin {
+
+    @Override
+    public void onAddValidators(AddValidatorsEventArgs e) {
+        super.onAddValidators(e);
+        e.addValidator(new PositionChangeSaveValidator());
+    }
+
+    @Override
+    protected String getOperationKey() {
+        return PositionBillConstant.CONFIRMCHANGE_OP;
+    }
+}

+ 6 - 5
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/operate/hr/PosBillEntryNewPositionTempSaveOpPlugin.java

@@ -19,7 +19,7 @@ import kd.bos.servicehelper.operation.SaveServiceHelper;
 import kd.hr.hbp.business.servicehelper.HRBaseServiceHelper;
 import kd.hr.hbp.common.constants.history.HisModelDataStatusEnum;
 import kd.hr.hbp.common.util.HRStringUtils;
-import nckd.jxccl.hrmp.hbpm.business.hr.PositionBillServiceHelper;
+import nckd.jxccl.hrmp.hbpm.business.hr.service.impl.PositionBillServiceHelper;
 import nckd.jxccl.hrmp.hbpm.common.hr.PositionBillConstant;
 
 import java.util.List;
@@ -28,6 +28,7 @@ import java.util.Map;
 /**
  * 岗位申请-新增岗位保存操作插件
  * @entity: nckd_posbillentryadd
+ * @from: kd.hr.homs.opplugin.web.orgbatch.OrgBatchChgBillNewOrgTempSaveOp
  * @author: jtd
  * @date: 2025-11-08 15:30
  */
@@ -47,7 +48,7 @@ public class PosBillEntryNewPositionTempSaveOpPlugin extends AbstractOperationSe
         // 获取 行政组织业务ID
         List<Long> adminorgBoIds = Lists.newArrayListWithExpectedSize(positionEntities.length);
         // 岗位ID标识
-        String positionIdKey = String.join("_", PositionBillConstant.NCKD_POSITION, PositionBillConstant.ID_KEY);
+        String positionIdKey = String.join("_", PositionBillConstant.NCKD_POSITION_KEY, PositionBillConstant.ID_KEY);
         for (DynamicObject positionEntity : positionEntities) {
             positionBoIds.add(positionEntity.getLong(positionIdKey));
             adminorgBoIds.add(positionEntity.getLong(PositionBillConstant.NCKD_ADMINORGBOID_KEY));
@@ -75,8 +76,8 @@ public class PosBillEntryNewPositionTempSaveOpPlugin extends AbstractOperationSe
         // 构建岗位对象
         OperateOption operateOption = OperateOption.create();
         List<DynamicObject> positionList = Lists.newArrayListWithExpectedSize(positionEntities.length);
-        // 获取岗位要转换的键值
-        Map<String, String> transKeyMap = PositionBillServiceHelper.getPositionTransKeyMap();
+        // 获取岗位要转换的键值
+        Map<String, String> positionTransKeyMap = PositionBillServiceHelper.getPositionTransKeyMap();
 
         for (DynamicObject positionEntity : positionEntities) {
             long positionId = positionEntity.getLong(positionIdKey);
@@ -87,7 +88,7 @@ public class PosBillEntryNewPositionTempSaveOpPlugin extends AbstractOperationSe
                 positionDyo = positionServiceHelper.generateEmptyDynamicObject();
             }
             // 将表单中的信息赋值到岗位信息中
-            PositionBillServiceHelper.getPositionHrDy(positionEntity, positionDyo, transKeyMap);// 调用保存会自动设置status、enable、datastatus
+            PositionBillServiceHelper.getPositionHrDy(positionEntity, positionDyo, positionTransKeyMap);// 调用保存会自动设置status、enable、datastatus
             // 设置ID为岗位ID
             positionDyo.set(PositionBillConstant.ID_KEY, positionId);
             // 设置 是否标准岗位

+ 55 - 0
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/operate/hr/PositionBillDeleteOpPlugin.java

@@ -0,0 +1,55 @@
+package nckd.jxccl.hrmp.hbpm.plugin.operate.hr;
+
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.entity.plugin.AbstractOperationServicePlugIn;
+import kd.bos.entity.plugin.AddValidatorsEventArgs;
+import kd.bos.entity.plugin.args.BeginOperationTransactionArgs;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
+import kd.hr.hbp.business.servicehelper.HRBaseServiceHelper;
+import kd.hr.hbp.common.util.HRStringUtils;
+import nckd.jxccl.base.common.utils.QueryFieldBuilder;
+import nckd.jxccl.hrmp.hbpm.business.hr.service.impl.PositionBillServiceHelper;
+import nckd.jxccl.hrmp.hbpm.common.hr.PositionBillConstant;
+import nckd.jxccl.hrmp.hbpm.plugin.operate.hr.validator.PositionBillDeleteStatusValidator;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * 岗位申请单删除操作插件
+ * @entity: nckd_positionbill
+ * @from: kd.hr.homs.opplugin.web.orgbatch.AdminOrgBatchBillDeleteOpPlugin
+ * @operate: delete
+ * @author: jtd
+ * @date: 2025/12/31 21:29
+ */
+public class PositionBillDeleteOpPlugin extends AbstractOperationServicePlugIn {
+
+    @Override
+    public void onAddValidators(AddValidatorsEventArgs e) {
+        super.onAddValidators(e);
+        e.addValidator(new PositionBillDeleteStatusValidator());
+    }
+
+    @Override
+    public void beginOperationTransaction(BeginOperationTransactionArgs args) {
+        super.beginOperationTransaction(args);
+        DynamicObject[] datas = args.getDataEntities();
+        if (datas.length > 0) {
+            List<Long> selectedRows = Arrays.stream(datas).map((dyn) -> dyn.getLong(PositionBillConstant.ID_KEY)).collect(Collectors.toList());
+            HRBaseServiceHelper positionBillEntryHelper = new HRBaseServiceHelper(PositionBillConstant.NCKD_POSITIONBILLENTRY_ENTITY);
+            QFilter billIdFilter = new QFilter(PositionBillConstant.NCKD_BILLID, QCP.equals, selectedRows);
+            String selectProperties = QueryFieldBuilder.create().add(PositionBillConstant.ID_KEY)
+                    .add(PositionBillConstant.NUMBER_KEY)
+                    .add(PositionBillConstant.NCKD_CHANGETYPE, PositionBillConstant.NUMBER_KEY)
+                    .add(PositionBillConstant.NCKD_POSITION_KEY)
+                    .buildSelect();
+            DynamicObject[] positionBillEntryDyns = positionBillEntryHelper.query(selectProperties, new QFilter[]{billIdFilter});
+            List<Long> addPositionEntryIdList = Arrays.stream(positionBillEntryDyns).filter((dyn) -> HRStringUtils.equals(dyn.getDynamicObject(PositionBillConstant.NCKD_CHANGETYPE).getString(PositionBillConstant.NUMBER_KEY), PositionBillConstant.ADD_TAG)).map((dyn) -> dyn.getLong(String.join(".", PositionBillConstant.NCKD_POSITION_KEY, PositionBillConstant.ID_KEY))).collect(Collectors.toList());
+            PositionBillServiceHelper.delAddMaster(addPositionEntryIdList);
+        }
+
+    }
+}

+ 1 - 0
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/operate/hr/PositionBillEntrySaveOpPlugin.java

@@ -7,6 +7,7 @@ import nckd.jxccl.hrmp.hbpm.plugin.operate.hr.validator.PositionBillEntryNumberV
 /**
  * 岗位申请单分录保存操作插件
  * @entity: nckd_positionbillentry
+ * @from: kd.hr.homs.opplugin.web.orgbatch.AdminorgBatchDetailSaveOp
  * @author: jtd
  * @date: 2025/12/23 19:17
  */

+ 53 - 0
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/operate/hr/PositionBillSaveOpPlugin.java

@@ -0,0 +1,53 @@
+package nckd.jxccl.hrmp.hbpm.plugin.operate.hr;
+
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.entity.plugin.AbstractOperationServicePlugIn;
+import kd.bos.entity.plugin.AddValidatorsEventArgs;
+import kd.bos.entity.plugin.args.BeginOperationTransactionArgs;
+import kd.bos.entity.plugin.args.EndOperationTransactionArgs;
+import kd.bos.logging.Log;
+import kd.bos.logging.LogFactory;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
+import kd.hr.hbp.business.servicehelper.HRBaseServiceHelper;
+import nckd.jxccl.hrmp.hbpm.business.hr.service.impl.PositionBillSaveHelper;
+import nckd.jxccl.hrmp.hbpm.common.hr.PositionBillConstant;
+import nckd.jxccl.hrmp.hbpm.plugin.operate.hr.validator.PositionBillSaveAndSubmitValidator;
+import nckd.jxccl.hrmp.hbpm.plugin.operate.hr.validator.PositionBillSaveValidator;
+
+/**
+ * 岗位申请单保存操作插件
+ * @entity: nckd_positionbill
+ * @operate: save
+ * @from: kd.hr.homs.business.domain.orgbatch.service.impl.OrgBatchBillSaveHelper
+ * @author: jtd
+ * @date: 2026/1/1 17:57
+ */
+public class PositionBillSaveOpPlugin extends AbstractOperationServicePlugIn {
+    private static final Log logger = LogFactory.getLog(PositionBillSaveOpPlugin.class);
+
+    public void onAddValidators(AddValidatorsEventArgs e) {
+        logger.info("PositionBillSaveOpPlugin.onAddValidators start.");
+        super.onAddValidators(e);
+        e.addValidator(new PositionBillSaveAndSubmitValidator());
+        e.addValidator(new PositionBillSaveValidator());
+    }
+
+    public void beginOperationTransaction(BeginOperationTransactionArgs e) {
+        logger.info("PositionBillSaveOpPlugin.beginOperationTransaction start.");
+        if (e.getDataEntities().length != 0) {
+            DynamicObject dataEntity = e.getDataEntities()[0];
+            PositionBillSaveHelper.getInstance().positionBillSave(dataEntity);
+        }
+    }
+
+    public void endOperationTransaction(EndOperationTransactionArgs e) {
+        Long billId = e.getDataEntities()[0].getLong(PositionBillConstant.ID_KEY);
+        HRBaseServiceHelper positionBillEntityHelper = new HRBaseServiceHelper(PositionBillConstant.NCKD_POSITIONBILLENTRY_ENTITY);
+        QFilter positionIdFilter = new QFilter(PositionBillConstant.CREATOR_KEY, QCP.equals, 0);
+        QFilter billIdFilter = new QFilter(PositionBillConstant.NCKD_BILLID, QCP.equals, billId);
+        positionIdFilter.and(billIdFilter);
+        positionBillEntityHelper.deleteByFilter(positionIdFilter.toArray());
+    }
+
+}

+ 8 - 7
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/operate/hr/validator/AbsBillPositionSaveValidator.java

@@ -17,7 +17,7 @@ import kd.bos.orm.query.QFilter;
 import kd.hr.hbp.business.servicehelper.HRBaseServiceHelper;
 import kd.hr.hbp.common.util.HRObjectUtils;
 import kd.hr.hbp.common.util.HRStringUtils;
-import nckd.jxccl.hrmp.hbpm.business.hr.PositionBillServiceHelper;
+import nckd.jxccl.hrmp.hbpm.business.hr.service.impl.PositionBillServiceHelper;
 import nckd.jxccl.hrmp.hbpm.common.hr.PositionBillConstant;
 
 import java.util.List;
@@ -25,6 +25,7 @@ import java.util.Map;
 
 /**
  * 岗位申请单分录校验器
+ * @from: kd.hr.homs.opplugin.web.orgbatch.validator.AbsBillOrgSaveValidator
  * @author: jtd
  * @date: 2025/12/23 20:55
  */
@@ -35,7 +36,7 @@ public abstract class AbsBillPositionSaveValidator extends AbstractValidator  {
     public void initialize() {
         super.initialize();
 
-        String ignoreBillNoForContent = getOption().getVariableValue("OP_VALIDATOR_PREFIX_IGNORE", Boolean.FALSE.toString());
+        String ignoreBillNoForContent = getOption().getVariableValue(PositionBillConstant.OP_VALIDATOR_SUFFIX_IGNORE, Boolean.FALSE.toString());
         if (Boolean.TRUE.toString().equals(ignoreBillNoForContent)) {
             setAddBillNoForContent(false);
         }
@@ -52,21 +53,21 @@ public abstract class AbsBillPositionSaveValidator extends AbstractValidator  {
         // 跳过系统默认的权限校验,数据、操作权限等
         operateOption.setVariableValue(OperateOptionConst.SKIPCHECKPERMISSION, Boolean.TRUE.toString());
         // 跳过字段值合规性校验
-        operateOption.setVariableValue("SkipMustInput", Boolean.TRUE.toString());
+        operateOption.setVariableValue(PositionBillConstant.OP_SKIPMUSTINPUT, Boolean.TRUE.toString());
         Map<Object, ExtendedDataEntity> entityMap = Maps.newHashMapWithExpectedSize(entities.length);
 
         for(ExtendedDataEntity entity : entities) {
             DynamicObject positionDy = entity.getDataEntity();
-            long positionId = positionDy.getLong(String.join("_", PositionBillConstant.NCKD_POSITION, PositionBillConstant.ID_KEY));
+            long positionId = positionDy.getLong(String.join("_", PositionBillConstant.NCKD_POSITION_KEY, PositionBillConstant.ID_KEY));
             entityMap.put(positionId, entity);
         }
 
         for(ExtendedDataEntity entity : entities) {
             DynamicObject positionEntity = entity.getDataEntity();
-            long positionId = positionEntity.getLong(String.join("_", PositionBillConstant.NCKD_POSITION, PositionBillConstant.ID_KEY));
+            long positionId = positionEntity.getLong(String.join("_", PositionBillConstant.NCKD_POSITION_KEY, PositionBillConstant.ID_KEY));
             DynamicObject addPositionDy = PositionBillServiceHelper.getPositionHrDy(positionEntity);
             addPositionDy.set(PositionBillConstant.ID_KEY, positionId);
-            addPositionDy.set(PositionBillConstant.BOID_KEY, positionEntity.get(String.join(".", PositionBillConstant.NCKD_POSITION, PositionBillConstant.BOID_KEY)));
+            addPositionDy.set(PositionBillConstant.BOID_KEY, positionEntity.get(String.join(".", PositionBillConstant.NCKD_POSITION_KEY, PositionBillConstant.BOID_KEY)));
             DynamicObject parentPositionVersionDy = positionEntity.getDynamicObject(PositionBillConstant.NCKD_PARENT);
             if (parentPositionVersionDy != null) {
                 long parentOrgBoId = parentPositionVersionDy.getLong(PositionBillConstant.BOID_KEY);
@@ -79,7 +80,7 @@ public abstract class AbsBillPositionSaveValidator extends AbstractValidator  {
                             .and(PositionBillConstant.ID_KEY, QCP.equals, parentOrgBoId);
                     DynamicObject currentParentDy = positionHrServiceHelper.loadDynamicObject(qFilter);
                     if (currentParentDy != null) {
-                        addPositionDy.set(PositionBillConstant.NCKD_PARENT, currentParentDy);
+                        addPositionDy.set(PositionBillConstant.PARENT_KEY, currentParentDy);
                     }
                 }
             }

+ 1 - 0
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/operate/hr/validator/PositionAddSaveValidator.java

@@ -4,6 +4,7 @@ import nckd.jxccl.hrmp.hbpm.common.hr.PositionBillConstant;
 
 /**
  * 岗位申请-岗位新设保存校验器
+ * @from: kd.hr.homs.opplugin.web.orgbatch.validator.OrgAddSaveValidator
  * @author: jtd
  * @date: 2025-11-08 17:23
  */

+ 46 - 0
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/operate/hr/validator/PositionBillDeleteStatusValidator.java

@@ -0,0 +1,46 @@
+package nckd.jxccl.hrmp.hbpm.plugin.operate.hr.validator;
+
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.entity.ExtendedDataEntity;
+import kd.bos.entity.validate.AbstractValidator;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
+import kd.hr.hbp.business.servicehelper.HRBaseServiceHelper;
+import kd.sdk.hr.hdm.common.enums.reg.RegBillStatusEnum;
+import nckd.jxccl.hrmp.hbpm.common.hr.PositionBillConstant;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * 岗位申请单删除校验器
+ * @from: kd.hr.homs.opplugin.web.orgbatch.validator.AdminOrgBatchBillDeleteStatusValidator
+ * @author: jtd
+ * @date: 2026/1/2 15:56
+ */
+public class PositionBillDeleteStatusValidator extends AbstractValidator {
+    @Override
+    public void validate() {
+        ExtendedDataEntity[] dataEntities = getDataEntities();
+        if (dataEntities.length != 0) {
+            List<Long> selectedRows = Arrays.stream(dataEntities).map((dataEntityx) -> dataEntityx.getDataEntity().getLong(PositionBillConstant.ID_KEY)).collect(Collectors.toList());
+            HRBaseServiceHelper hrBaseServiceHelper = new HRBaseServiceHelper(PositionBillConstant.NCKD_POSITIONBILL_ENTITY);
+            QFilter qFilter = new QFilter(PositionBillConstant.ID_KEY, QCP.in, selectedRows);
+            qFilter.and(PositionBillConstant.BILL_STATUS_KEY, QCP.in, Arrays.asList(RegBillStatusEnum.ALREADYSUBMIT.getCode(), RegBillStatusEnum.APPROVING.getCode(), RegBillStatusEnum.APPROVEPASSED.getCode(), RegBillStatusEnum.APPROVEREJECTED.getCode(), RegBillStatusEnum.ABANDONED.getCode()));
+            DynamicObject[] dynamicObjects = hrBaseServiceHelper.queryOriginalArray(PositionBillConstant.ID_KEY, new QFilter[]{qFilter});
+            String msg = "只允许删除“暂存”或“待重新提交”状态的数据。";
+            if (dynamicObjects.length > 0) {
+                Set<Long> ids = Arrays.stream(dynamicObjects).map((dynamicObject) -> dynamicObject.getLong(PositionBillConstant.ID_KEY)).collect(Collectors.toSet());
+
+                for(ExtendedDataEntity dataEntity : dataEntities) {
+                    if (ids.contains(dataEntity.getDataEntity().getLong(PositionBillConstant.ID_KEY))) {
+                        addErrorMessage(dataEntity, msg);
+                    }
+                }
+            }
+
+        }
+    }
+}

+ 21 - 0
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/operate/hr/validator/PositionBillEntryImportValidator.java

@@ -0,0 +1,21 @@
+package nckd.jxccl.hrmp.hbpm.plugin.operate.hr.validator;
+
+import kd.bos.entity.validate.AbstractValidator;
+
+/**
+ * 岗位申请单分录导入数据校验器
+ * @from: kd.hr.homs.opplugin.web.orgbatch.validator.AdminOrgBatchDetailImportValidator
+ * @author: jtd
+ * @date: 2026/1/4 11:27
+ */
+public class PositionBillEntryImportValidator extends AbstractValidator {
+    private final String this_bill_msg = "岗位已存在%s中,不允许同时对岗位进行多种变动操作。";
+    private final String this_bill_msg_no_type = "岗位已存在本单中,不允许同时对岗位进行多种变动操作。";
+    private final String loop_self = "不能选择自己或者自己的下级岗位为上级岗位,请修改。";
+
+
+    @Override
+    public void validate() {
+        // 导入数据校验业务逻辑
+    }
+}

+ 5 - 4
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/operate/hr/validator/PositionBillEntryNameValidator.java

@@ -16,6 +16,7 @@ import java.util.Set;
 
 /**
  * 岗位申请单分录名称校验器
+ * @from: kd.hr.homs.opplugin.web.orgbatch.validator.AdminOrgBatchDetailNameValidator
  * @author: jtd
  * @date: 2025/12/23 21:16
  */
@@ -24,7 +25,7 @@ public class PositionBillEntryNameValidator extends AbstractValidator {
     public void validate() {
         OperateOption option = validateContext.getOption();
         // 获取组织下的岗位同胞数据 {orgBoid:{positionId:positionName}}
-        String billPositionNameMapStr = option.getVariableValue("OP_BILL_SIBLING_NAMES_MAP", "");
+        String billPositionNameMapStr = option.getVariableValue(PositionBillConstant.OP_BILL_SIBLING_NAMES_MAP, "");
         if (HRStringUtils.isNotEmpty(billPositionNameMapStr)) {
             JSONObject orgBoIdToSiblingNameMap = JSONObject.parseObject(billPositionNameMapStr);
             Set<String> errorIds = Sets.newHashSetWithExpectedSize(getDataEntities().length);
@@ -39,8 +40,8 @@ public class PositionBillEntryNameValidator extends AbstractValidator {
 
                 // 获取岗位数据
                 ILocaleString positionNameMap = dataEntity.getLocaleString(PositionBillConstant.NAME_KEY);
-                long positionId = dataEntity.getLong(String.join(".", PositionBillConstant.NCKD_POSITION, PositionBillConstant.ID_KEY));
-                long positionBoId = dataEntity.getLong(String.join(".", PositionBillConstant.NCKD_POSITION, PositionBillConstant.BOID_KEY));
+                long positionId = dataEntity.getLong(String.join(".", PositionBillConstant.NCKD_POSITION_KEY, PositionBillConstant.ID_KEY));
+                long positionBoId = dataEntity.getLong(String.join(".", PositionBillConstant.NCKD_POSITION_KEY, PositionBillConstant.BOID_KEY));
                 // 获取该组织下的岗位名称数据
                 JSONObject siblingNameMap = orgBoIdToSiblingNameMap.getJSONObject(String.valueOf(orgBoId));
                 if (siblingNameMap != null) {
@@ -64,7 +65,7 @@ public class PositionBillEntryNameValidator extends AbstractValidator {
             }
 
             if (option.containsVariable("isimport") && Boolean.parseBoolean(option.getVariableValue("isimport"))) {
-                // 业务逻辑
+                // 导入业务逻辑
             }
 
         }

+ 4 - 3
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/operate/hr/validator/PositionBillEntryNumberValidator.java

@@ -10,6 +10,7 @@ import nckd.jxccl.hrmp.hbpm.common.hr.PositionBillConstant;
 
 /**
  * 岗位申请单分录编码校验器
+ * @from: kd.hr.homs.opplugin.web.orgbatch.validator.AdminOrgBatchDetailNumberValidator
  * @author: jtd
  * @date: 2025/12/24 11:04
  */
@@ -18,7 +19,7 @@ public class PositionBillEntryNumberValidator extends AbstractValidator {
     public void validate() {
         OperateOption option = validateContext.getOption();
         // 获取岗位编码数据 {positionId:number}
-        String billPositionNumberMapStr = option.getVariableValue("OP_BILL_NUMBER_MAP", "");
+        String billPositionNumberMapStr = option.getVariableValue(PositionBillConstant.OP_BILL_NUMBER_MAP, "");
         if (HRStringUtils.isNotEmpty(billPositionNumberMapStr)) {
             JSONObject numberMap = JSONObject.parseObject(billPositionNumberMapStr);
 
@@ -26,7 +27,7 @@ public class PositionBillEntryNumberValidator extends AbstractValidator {
                 DynamicObject dataEntity = data.getDataEntity();
                 String number = dataEntity.getString(PositionBillConstant.NUMBER_KEY);
                 if (HRStringUtils.isNotEmpty(number)) {
-                    long positionId = dataEntity.getLong(String.join(".", PositionBillConstant.NCKD_POSITION, PositionBillConstant.ID_KEY));
+                    long positionId = dataEntity.getLong(String.join(".", PositionBillConstant.NCKD_POSITION_KEY, PositionBillConstant.ID_KEY));
 
                     for(String siblingId : numberMap.keySet()) {
                         if (!siblingId.equals(String.valueOf(positionId)) && number.equals(numberMap.getString(siblingId))) {
@@ -38,7 +39,7 @@ public class PositionBillEntryNumberValidator extends AbstractValidator {
         }
 
         if (option.containsVariable("isimport") && Boolean.parseBoolean(option.getVariableValue("isimport"))) {
-            // 业务逻辑
+            // 导入业务逻辑
         }
 
     }

+ 175 - 0
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/operate/hr/validator/PositionBillSaveAndSubmitValidator.java

@@ -0,0 +1,175 @@
+package nckd.jxccl.hrmp.hbpm.plugin.operate.hr.validator;
+
+import com.google.common.collect.Maps;
+import kd.bos.common.enums.EnableEnum;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.entity.ExtendedDataEntity;
+import kd.bos.entity.validate.AbstractValidator;
+import kd.bos.entity.validate.ValidateResultCollection;
+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.orm.util.CollectionUtils;
+import kd.hr.hbp.business.servicehelper.HRBaseServiceHelper;
+import kd.hr.hbp.common.constants.history.HisModelDataStatusEnum;
+import kd.hr.hbp.common.util.HRStringUtils;
+import nckd.jxccl.hrmp.hbpm.common.hr.PositionBillConstant;
+import nckd.jxccl.hrmp.hbpm.common.hr.PositionChangeTypeEnum;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * 岗位社区内单保存并提交校验器
+ * @from: kd.hr.homs.opplugin.web.orgbatch.OrgBatchBillSaveAndSubmitValidator
+ * @author: jtd
+ * @date: 2026/1/2 16:01
+ */
+public class PositionBillSaveAndSubmitValidator extends AbstractValidator {
+    private static final Log logger = LogFactory.getLog(PositionBillSaveAndSubmitValidator.class);
+    private String operateKey;
+
+    /**
+     * 获取所有岗位的历史版本数据
+     * @param billId
+     * @return
+     */
+    private Map<Long, Long> getBoIdPositionIdMap(Long billId) {
+        // from: kd.hr.homs.business.domain.batchbill.service.impl.OrgBatchBillConverter.processDynamicObject
+        // unSafeAndDeleteDataMap获取到是空的,因为mergesplitstatus默认是2,而岗位并不需要考虑拆分合并的数据所以视作无数据即可
+        // 拿到所有岗位ID,实际上并不需要新增的岗位
+        HRBaseServiceHelper baseHelper = new HRBaseServiceHelper(PositionBillConstant.NCKD_POSITIONBILLENTRY_ENTITY);
+        QFilter billIdFilter = new QFilter(PositionBillConstant.NCKD_BILLID, QCP.equals, billId);
+        DynamicObject[] objects = baseHelper.loadDynamicObjectArray(billIdFilter.toArray());
+        // from: kd.hr.homs.business.domain.orgbatch.service.impl.OrgBatchChgFeasibleCheckServiceImpl.check
+        // 获取所有岗位的BOID
+        Set<Long> ownBoIdSet = Arrays.stream(objects).map(object -> object.getLong(String.join(".", PositionBillConstant.NCKD_POSITION_KEY, PositionBillConstant.BOID_KEY))).collect(Collectors.toSet());
+        // from: kd.hr.homs.business.domain.orgbatch.repository.OrgBatchBillCheckHelper.queryNewBoIdOrgIdMap
+        // 查询出对应的历史版本
+        QFilter adminFilter = new QFilter(PositionBillConstant.BOID_KEY, QCP.in, ownBoIdSet);
+        adminFilter.and(new QFilter(PositionBillConstant.DATA_STATUS, QCP.in, HisModelDataStatusEnum.EFFECTING));
+        adminFilter.and(new QFilter(PositionBillConstant.ENABLE, QCP.equals, EnableEnum.YES.getCode()));
+        adminFilter.and(new QFilter(PositionBillConstant.IS_CURRENT_VERSION, QCP.equals, EnableEnum.NO.getCode()));
+        HRBaseServiceHelper positionHelper = new HRBaseServiceHelper(PositionBillConstant.HBPM_POSITIONHR);
+        DynamicObjectCollection positionColl = positionHelper.queryOriginalCollection(String.join(",", PositionBillConstant.BOID_KEY, PositionBillConstant.ID_KEY), new QFilter[]{adminFilter}, String.format("%s desc", PositionBillConstant.BSED_KEY));
+        Map<Long, List<DynamicObject>> positionGroupMap = positionColl.stream().collect(Collectors.groupingBy((dy) -> dy.getLong(PositionBillConstant.BOID_KEY)));
+        Map<Long, Long> boIdPositionIdMap = Maps.newHashMapWithExpectedSize(positionColl.size());
+
+        for(Map.Entry<Long, List<DynamicObject>> entry : positionGroupMap.entrySet()) {
+            Long positionId = entry.getValue().get(0).getLong(PositionBillConstant.ID_KEY);
+            boIdPositionIdMap.put(entry.getKey(), positionId);
+        }
+
+        return boIdPositionIdMap;
+    }
+
+    /**
+     * 校验变更信息中的岗位是否最新一笔历史版本
+     * @from: kd.hr.homs.business.domain.orgbatch.service.impl.OrgBatchChgFeasibleCheckServiceImpl#checkInfoChg(java.lang.String, kd.bos.dataentity.entity.DynamicObject, java.util.List)
+     * @param dynamicObject
+     * @return
+     */
+    private String checkChangeHandler(DynamicObject dynamicObject, Map<Long, Long> boIdOrgIdMap) {
+        DynamicObject position = dynamicObject.getDynamicObject(String.join("_", PositionBillConstant.NCKD_POSITION_KEY, PositionBillConstant.CHANGE_TAG));
+        Long boId = position.getLong(PositionBillConstant.BOID_KEY);
+        Long positionId = position.getLong(PositionBillConstant.ID_KEY);
+        String positionName = position.getString(PositionBillConstant.NAME_KEY);
+        Long newPositionId = boIdOrgIdMap.get(boId);
+        if (!Objects.isNull(newPositionId) && !newPositionId.equals(positionId)) {
+            return String.format("“变更信息”中“%s”:当前岗位已发生变化,请基于最新的信息进行调整。", new Object[]{positionName});
+        }
+
+        return "";
+    }
+
+    @Override
+    public void validate() {
+        this.operateKey = getOption().getVariableValue(PositionBillConstant.OP_OPERATE_KEY, "");
+        long startTime = System.currentTimeMillis();
+        ValidateResultCollection validateResultCollection = getValidateContext().getValidateResults();
+        if (validateResultCollection == null || CollectionUtils.isEmpty(validateResultCollection.getValidateErrors()) || CollectionUtils.isEmpty((validateResultCollection.getValidateErrors().get(0)).getAllErrorInfo())) {
+            ExtendedDataEntity[] dataEntities = getDataEntities();
+            List<String> entryKeyList = new ArrayList(8);
+
+            for(ExtendedDataEntity dataEntity : dataEntities) {
+                Map<Long, Long> boIdPositionIdMap = getBoIdPositionIdMap(dataEntity.getDataEntity().getLong(PositionBillConstant.ID_KEY));
+                if (entryKeyList.isEmpty()) {
+                    entryKeyList = Arrays.stream(PositionChangeTypeEnum.values()).map(changeTypeEnum -> changeTypeEnum.getTag(PositionBillConstant.NCKD_ENTRYENTITYUNDERLINE_KEY)).collect(Collectors.toList());
+                }
+
+                DynamicObject checkObject = dataEntity.getDataEntity();
+                String message = showMessageBeforeCheck(checkObject, entryKeyList);
+                if (HRStringUtils.isEmpty(message)) {
+                    // 这里不校验新增岗位的数据
+                    for (DynamicObject dynamicObject : dataEntity.getDataEntity().getDynamicObjectCollection(PositionBillConstant.NCKD_ENTRYENTITY_CHANGE_KEY)) {
+                        String errorMessage = checkChangeHandler(dynamicObject, boIdPositionIdMap);
+                        if (HRStringUtils.isNotBlank(errorMessage)) {
+                            addErrorMessage(dataEntity, errorMessage);
+                        }
+                    }
+                } else {
+                    addErrorMessage(dataEntity, message);
+                }
+            }
+
+            logger.info(String.format(Locale.ROOT, "PositionBillSaveAndSubmitValidator() time cost is: %s", System.currentTimeMillis() - startTime));
+        }
+    }
+
+    private String showMessageBeforeCheck(DynamicObject checkObject, List<String> entryKeyList) {
+        String message = null;
+        boolean isChange = isChange(checkObject, entryKeyList);
+        this.operateKey = HRStringUtils.isEmpty(this.operateKey) ? getOperateKey() : this.operateKey;
+        switch (this.operateKey) {
+            case PositionBillConstant.SAVE_OP:
+                if (!isChange) {
+                    message = "没有“岗位调整”的数据,请调整后再操作“保存”";
+                }
+                break;
+            case PositionBillConstant.SUBMIT_OP:
+                if (!getIsHasWorkFlow()) {
+                    message = "提交失败,当前单据没有可用的工作流,请保存单据后前往“流程服务云>工作流服务>设计中心>流程设计”中新增或发布流程。";
+                }
+            case "wftask_save":
+                if (!isChange) {
+                    message = "没有“岗位调整”的数据,请调整后再操作“提交”。";
+                }
+                break;
+            case PositionBillConstant.SUBMITEFFECT_OP:
+                if (!isChange) {
+                    message = "没有“岗位调整”的数据,请调整后再操作“提交并生效”。";
+                }
+        }
+
+        return message;
+    }
+
+    private boolean getIsHasWorkFlow() {
+        String entityNumber = getDataEntities()[0].getDataEntity().getDataEntityType().getName();
+        HRBaseServiceHelper wfHelper = new HRBaseServiceHelper("wf_model");
+        QFilter qFilter = new QFilter("entrabill", "=", entityNumber);
+        qFilter.and("publish", "=", '1').and("discard", "=", '0');
+        return wfHelper.isExists(qFilter);
+    }
+
+    private boolean isChange(DynamicObject checkObject, List<String> entryKeyList) {
+        logger.info("isChange entryKeys:{}", entryKeyList);
+
+        for(String entryKey : entryKeyList) {
+            DynamicObjectCollection entryColl = checkObject.getDynamicObjectCollection(entryKey);
+            if (!CollectionUtils.isEmpty(entryColl)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+}

+ 200 - 0
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/operate/hr/validator/PositionBillSaveValidator.java

@@ -0,0 +1,200 @@
+package nckd.jxccl.hrmp.hbpm.plugin.operate.hr.validator;
+
+import com.google.common.collect.Lists;
+import kd.bos.common.enums.EnableEnum;
+import kd.bos.dataentity.OperateOption;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.entity.ExtendedDataEntity;
+import kd.bos.entity.operate.OperateOptionConst;
+import kd.bos.entity.operate.result.OperateErrorInfo;
+import kd.bos.entity.operate.result.OperationResult;
+import kd.bos.entity.validate.AbstractValidator;
+import kd.bos.entity.validate.ValidateResult;
+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.servicehelper.operation.OperationServiceHelper;
+import kd.hr.hbp.business.servicehelper.HRBaseServiceHelper;
+import kd.hr.hbp.common.util.HRStringUtils;
+import nckd.jxccl.hrmp.hbpm.business.hr.service.impl.PositionBillSaveHelper;
+import nckd.jxccl.hrmp.hbpm.business.hr.service.impl.PositionBillServiceHelper;
+import nckd.jxccl.hrmp.hbpm.common.hr.PositionBillConstant;
+import nckd.jxccl.hrmp.hbpm.common.hr.PositionChangeTypeEnum;
+
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Collectors;
+
+/**
+ * 岗位申请单保存校验器
+ * @from: kd.hr.homs.opplugin.web.orgbatch.validator.AdminOrgBillSaveValidator
+ * @author: jtd
+ * @date: 2026/1/2 16:21
+ */
+public class PositionBillSaveValidator extends AbstractValidator {
+    private static final Log LOG = LogFactory.getLog(PositionBillSaveValidator.class);
+    private final Map<String, HRBaseServiceHelper> helperMap = new ConcurrentHashMap(PositionChangeTypeEnum.values().length);
+    private final String suffix = "“%s”中:";
+    private final String suffix_with_name = "“%s”中“%s”:";
+
+    @Override
+    public void validate() {
+        ExtendedDataEntity[] entities = getDataEntities();
+
+        for(ExtendedDataEntity entity : entities) {
+            checkNotCommonEntryData(entity);
+        }
+    }
+
+    private void checkNotCommonEntryData(ExtendedDataEntity entity) {
+        PositionBillSaveHelper positionBillSaveHelper = PositionBillSaveHelper.getInstance();
+        DynamicObject dataEntity = entity.getDataEntity();
+        long billId = dataEntity.getLong(PositionBillConstant.ID_KEY);
+        Date effDate = dataEntity.getDate(PositionBillConstant.NCKD_EFFDT);
+        List<DynamicObject> positionBillEntryEntityDyns = getAllDbEntryDys(billId);
+        Map<Long, List<DynamicObject>> positionId2DynFromDBListMap = positionBillEntryEntityDyns.stream().collect(Collectors.groupingBy((dyn) -> dyn.getLong(String.join(".", PositionBillConstant.NCKD_POSITION_KEY, PositionBillConstant.ID_KEY))));
+        DynamicObjectCollection allEntryEntityDyn = Arrays.stream(PositionChangeTypeEnum.values()).map(changeTypeEnum -> dataEntity.getDynamicObjectCollection(changeTypeEnum.getTag(PositionBillConstant.NCKD_ENTRYENTITYUNDERLINE_KEY))).collect(DynamicObjectCollection::new, DynamicObjectCollection::addAll, DynamicObjectCollection::addAll);
+        if (!allEntryEntityDyn.isEmpty()) {
+            List<Long> positionIdList = positionBillSaveHelper.getAllEntryPositionId(allEntryEntityDyn);
+            Map<Long, DynamicObject> positionId2BasicInfoDynMap = PositionBillServiceHelper.getPositionId2BasicInfoDynMapByIds(positionIdList);
+            List<DynamicObject> needSaveEntryDynList = Lists.newArrayListWithExpectedSize(allEntryEntityDyn.size());
+
+            for(DynamicObject entryEntityDyn : allEntryEntityDyn) {
+                String suffix = positionBillSaveHelper.getSuffixFromEntryEntityDyn(entryEntityDyn);
+                String changeTypeNumber = PositionChangeTypeEnum.getNumberByTag(suffix);
+                Long positionId = positionBillSaveHelper.getPositionId(entryEntityDyn, suffix);
+                if (positionId != null && positionId != 0L) {
+                    DynamicObject positionBillEntryDyn = null;
+                    List<DynamicObject> dbEntryDys = positionId2DynFromDBListMap.get(positionId);
+                    if (dbEntryDys != null) {
+                        for(DynamicObject dbEntryDy : dbEntryDys) {
+                            String dbChangeTypeNumber = dbEntryDy.getString(String.join(".", PositionBillConstant.NCKD_CHANGETYPE, PositionBillConstant.NUMBER_KEY));
+                            if (HRStringUtils.equals(dbChangeTypeNumber, changeTypeNumber)) {
+                                positionBillEntryDyn = dbEntryDy;
+                                break;
+                            }
+                        }
+                    }
+
+                    if (positionBillEntryDyn == null) {
+                        HRBaseServiceHelper helper = getHelperByChangeType(changeTypeNumber);
+                        if (helper == null) {
+                            continue;
+                        }
+
+                        positionBillEntryDyn = helper.generateEmptyDynamicObject();
+                        positionBillEntryDyn.set(PositionBillConstant.NCKD_BILLID, dataEntity.getLong(PositionBillConstant.ID_KEY));
+                        DynamicObject basicInfoDyn = positionId2BasicInfoDynMap.get(positionId);
+                        positionBillSaveHelper.assembleSaveEntryDyn(positionBillEntryDyn, basicInfoDyn);
+                    }
+
+                    positionBillSaveHelper.coverdEntryValue(positionBillEntryDyn, entryEntityDyn, suffix);
+                    Object enable = positionBillEntryDyn.get(PositionBillConstant.ENABLE);
+                    if (enable == null) {
+                        positionBillEntryDyn.set(PositionBillConstant.ENABLE, EnableEnum.YES.getCode());
+                    }
+
+                    positionBillEntryDyn.set(PositionBillConstant.NCKD_BSED, effDate);
+                    needSaveEntryDynList.add(positionBillEntryDyn);
+                }
+            }
+
+            Map<String, List<DynamicObject>> groupByMap = needSaveEntryDynList.stream().collect(Collectors.groupingBy((dy) -> dy.getString(String.join(".", PositionBillConstant.NCKD_CHANGETYPE, PositionBillConstant.NUMBER_KEY))));
+            OperateOption operateOption = OperateOption.create();
+            operateOption.setVariableValue(PositionBillConstant.OP_VALIDATOR_BILL_POSITION_ALL_CHANGE_POSITION_KEY, PositionBillServiceHelper.getThisBillAllValidateDataStr(dataEntity));
+            operateOption.setVariableValue(PositionBillConstant.OP_VALIDATOR_BILL_POSITION_NEW_POSITION_NUMBERS_KEY, PositionBillServiceHelper.getThisBillPositionNumbersStr(dataEntity));
+            operateOption.setVariableValue(PositionBillConstant.OP_BILL_SIBLING_NAMES_MAP, PositionBillServiceHelper.getThisBillPositionNamesStr(dataEntity));
+            operateOption.setVariableValue(PositionBillConstant.OP_VALIDATOR_SUFFIX_IGNORE, Boolean.TRUE.toString());
+
+            for(Map.Entry<String, List<DynamicObject>> entry : groupByMap.entrySet()) {
+                String changeTypeNumber = entry.getKey();
+                List<DynamicObject> entryDynList = entry.getValue();
+                Map<Object, DynamicObject> saveMap = entryDynList.stream().collect(Collectors.toMap((dy) -> dy.get(PositionBillConstant.ID_KEY), (dy) -> dy, (v1, v2) -> v1));
+                String tagName = PositionChangeTypeEnum.getTipByNumber(changeTypeNumber);
+                String entityNumber = PositionChangeTypeEnum.getTagByNumber(PositionBillConstant.NCKD_POSBILLENTRY_KEY, changeTypeNumber);
+                OperationResult operationResult = executeOperateOnlyValidate(entryDynList.toArray(new DynamicObject[0]), entityNumber, operateOption, PositionBillConstant.SAVE_OP);
+                if (operationResult != null && !operationResult.isSuccess()) {
+                    for(ValidateResult validateError : operationResult.getValidateResult().getValidateErrors()) {
+                        for(OperateErrorInfo operateErrorInfo : validateError.getAllErrorInfo()) {
+                            Object pkValue = operateErrorInfo.getPkValue();
+                            DynamicObject errorDy = saveMap.get(pkValue);
+                            String message = operateErrorInfo.getMessage();
+                            if (errorDy == null) {
+                                addErrorMessage(entity, String.format(this.suffix, tagName) + message);
+                            } else {
+                                DynamicObject versionDy = errorDy.getDynamicObject(PositionBillConstant.NCKD_POSITION_KEY);
+                                if (HRStringUtils.isNotEmpty(message) && message.contains(versionDy.getString(PositionBillConstant.NAME_KEY))) {
+                                    addErrorMessage(entity, String.format(this.suffix, tagName) + message);
+                                } else {
+                                    addErrorMessage(entity, String.format(this.suffix_with_name, tagName, versionDy.getString(PositionBillConstant.NAME_KEY)) + message);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+
+        }
+    }
+
+    private OperationResult executeOperateOnlyValidate(DynamicObject[] positionBillEntries, String entityNumber, OperateOption option, String opKey) {
+        OperateOption operateOption = option;
+        if (option == null) {
+            operateOption = OperateOption.create();
+        }
+
+        operateOption.setVariableValue(OperateOptionConst.ISHASRIGHT, Boolean.TRUE.toString());
+        operateOption.setVariableValue(OperateOptionConst.ONLY_VALIDATE, Boolean.TRUE.toString());
+
+        try {
+            return OperationServiceHelper.executeOperate(opKey, entityNumber, positionBillEntries, operateOption);
+        } catch (Exception ex) {
+            LOG.error("executeSaveOperateOnlyValidate_error", ex);
+            throw ex;
+        }
+    }
+
+    private List<DynamicObject> getAllDbEntryDys(long billId) {
+        List<DynamicObject> entryDys = Lists.newArrayListWithExpectedSize(10);
+
+        for(PositionChangeTypeEnum changeTypeEnum : PositionChangeTypeEnum.values()) {
+            DynamicObject[] entries = getDbEntryDysByChangeType(billId, changeTypeEnum.getNumber());
+            if (entries != null) {
+                entryDys.addAll(Arrays.asList(entries));
+            }
+        }
+
+        return entryDys;
+    }
+
+    private DynamicObject[] getDbEntryDysByChangeType(long billId, String changeTypeNumber) {
+        HRBaseServiceHelper helper = getHelperByChangeType(changeTypeNumber);
+        if (helper == null) {
+            return new DynamicObject[0];
+        } else {
+            QFilter billIdFilter = new QFilter(PositionBillConstant.NCKD_BILLID, QCP.equals, billId);
+            QFilter changeTypeFilter = new QFilter(String.join(".", PositionBillConstant.NCKD_CHANGETYPE, PositionBillConstant.NUMBER_KEY), QCP.equals, changeTypeNumber);
+            return helper.loadDynamicObjectArray(new QFilter[]{billIdFilter, changeTypeFilter});
+        }
+    }
+
+    private HRBaseServiceHelper getHelperByChangeType(String changeTypeNumber) {
+        String entityNumber = PositionChangeTypeEnum.getTagByNumber(PositionBillConstant.NCKD_POSBILLENTRY_KEY, changeTypeNumber);
+        if (HRStringUtils.isNotEmpty(entityNumber)) {
+            HRBaseServiceHelper helper = helperMap.get(entityNumber);
+            if (helper == null) {
+                helper = new HRBaseServiceHelper(entityNumber);
+                helperMap.put(entityNumber, helper);
+            }
+
+            return helper;
+        } else {
+            return null;
+        }
+    }
+}

+ 16 - 0
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/operate/hr/validator/PositionChangeSaveValidator.java

@@ -0,0 +1,16 @@
+package nckd.jxccl.hrmp.hbpm.plugin.operate.hr.validator;
+
+import nckd.jxccl.hrmp.hbpm.common.hr.PositionBillConstant;
+
+/**
+ * 岗位申请-岗位变更保存校验器
+ * @from: kd.hr.homs.opplugin.web.orgbatch.validator.OrgParentSaveValidator
+ * @author: jtd
+ * @date: 2025/12/31 22:01
+ */
+public class PositionChangeSaveValidator extends AbsBillPositionSaveValidator {
+    @Override
+    String getOperationKey() {
+        return PositionBillConstant.CONFIRMCHANGE_OP;
+    }
+}

+ 12 - 0
code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/common/PerfManagerFormConstant.java

@@ -85,4 +85,16 @@ public class PerfManagerFormConstant extends FormConstant {
     public static final String POSTWAGEUNITLIST_ENTITYID = "nckd_postwageunitlist";
     public static final String NCKD_YEAR = "nckd_year";
     /*-------------------------------------- 年度绩效归档记录 end --------------------------------------*/
+
+
+    /*-------------------------------------- 年度绩效归档记录 begin --------------------------------------*/
+    /** 文件印发及盖章时间-实体标识 */
+    public static final String DOCSTAMP_ENTITYID = "nckd_docstamp";
+    /** HR员工 */
+    public static final String NCKD_PERSON = "nckd_person";
+    /** 盖章时间 */
+    public static final String NCKD_STAMPTIME = "nckd_stamptime";
+    /** 文件印发时间 */
+    public static final String NCKD_FILEISSUETIME = "nckd_fileissuetime";
+    /*-------------------------------------- 年度绩效归档记录 end --------------------------------------*/
 }

+ 93 - 11
code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/form/print/BatchModDocstampPopupFormPlugin.java

@@ -1,13 +1,32 @@
 package nckd.jxccl.opmc.pm.plugin.form.print;
 
+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.EntityMetadataCache;
+import kd.bos.entity.MainEntityType;
+import kd.bos.entity.operate.result.IOperateInfo;
+import kd.bos.entity.operate.result.OperationResult;
+import kd.bos.form.FormShowParameter;
 import kd.bos.form.events.AfterDoOperationEventArgs;
 import kd.bos.form.plugin.AbstractFormPlugin;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
+import kd.bos.servicehelper.BusinessDataServiceHelper;
+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.exception.ValidationException;
+import nckd.jxccl.base.common.utils.ConvertUtil;
+import nckd.jxccl.base.entity.helper.EntityHelper;
+import nckd.jxccl.opmc.pm.common.PerfManagerFormConstant;
 
 import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.List;
+import java.util.StringJoiner;
+import java.util.stream.Collectors;
 
 /**
 * 批量修改文件印发及盖章时间
@@ -18,18 +37,81 @@ import java.util.Map;
 */
 public class BatchModDocstampPopupFormPlugin extends AbstractFormPlugin implements Plugin {
 
+
     @Override
     public void afterDoOperation(AfterDoOperationEventArgs e) {
         String operateKey = e.getOperateKey();
-        if(e.getOperationResult() != null && e.getOperationResult().isSuccess())
-        if(FormConstant.AFFIRM_OP.equalsIgnoreCase(operateKey)){
-            Date fileIssueTime = this.getModel().getDataEntity(true).getDate("nckd_fileissuetime");
-            Date stampTime = this.getModel().getDataEntity(true).getDate("nckd_stamptime");
-            Map<String,Date> returnDate = new  HashMap<>();
-            returnDate.put("nckd_fileissuetime",fileIssueTime);
-            returnDate.put("nckd_stamptime",stampTime);
-            this.getView().returnDataToParent(returnDate);
-            this.getView().close();
+        if(e.getOperationResult() != null && e.getOperationResult().isSuccess()) {
+            FormShowParameter showParameter = this.getView().getFormShowParameter();
+            //获取列表选择的人员
+            Object personIds = showParameter.getCustomParam("personIds");
+            List<Object> list = ConvertUtil.toList(personIds);
+            if (FormConstant.AFFIRM_OP.equalsIgnoreCase(operateKey)) {
+                Date fileIssueTime = this.getModel().getDataEntity(true).getDate(PerfManagerFormConstant.NCKD_FILEISSUETIME);
+                Date stampTime = this.getModel().getDataEntity(true).getDate(PerfManagerFormConstant.NCKD_STAMPTIME);
+                DynamicObjectCollection query = QueryServiceHelper.query(PerfManagerFormConstant.DOCSTAMP_ENTITYID,
+                        FormConstant.ID_KEY,
+                        new QFilter[]{new QFilter(String.join(".", FormConstant.NCKD_PERSON, FormConstant.ID_KEY), QCP.in, list)});
+                List<Long> ids = query.stream().map(dynamicObject -> dynamicObject.getLong(FormConstant.ID_KEY)).collect(Collectors.toList());
+                MainEntityType docStampEntityType = EntityMetadataCache.getDataEntityType(PerfManagerFormConstant.DOCSTAMP_ENTITYID);
+                DynamicObject[] load = BusinessDataServiceHelper.load(ids.toArray(new Long[0]), docStampEntityType);
+                // 提取查询结果中的人员ID
+                List<DynamicObject> save = new java.util.ArrayList<>();
+                java.util.Set<Long> foundPersonIds = new java.util.HashSet<>();
+                for (DynamicObject dynamicObject : load) {
+                    Long personId = dynamicObject.getLong(String.join(".", FormConstant.NCKD_PERSON, FormConstant.ID_KEY));
+                    foundPersonIds.add(personId);
+                    dynamicObject.set(PerfManagerFormConstant.NCKD_STAMPTIME, stampTime);
+                    dynamicObject.set(PerfManagerFormConstant.NCKD_FILEISSUETIME, fileIssueTime);
+                    save.add(dynamicObject);
+                }
+
+                // 计算不在查询结果中的人员ID(即没有文档印章记录的人员ID)
+                java.util.List<Long> missingPersonIds = new java.util.ArrayList<>();
+                for (Object personId : list) {
+                    Long id = ConvertUtil.toLong(personId);
+                    if (!foundPersonIds.contains(id)) {
+                        missingPersonIds.add(id);
+                    }
+                }
+                for (Long missingPersonId : missingPersonIds) {
+                    DynamicObject dynamicObject = EntityHelper.newEntity(PerfManagerFormConstant.DOCSTAMP_ENTITYID);
+                    DynamicObject employee = EntityHelper.newEntity(FormConstant.HRPI_EMPLOYEE,missingPersonId);
+                    dynamicObject.set(FormConstant.NCKD_PERSON,employee);
+                    dynamicObject.set(PerfManagerFormConstant.NCKD_STAMPTIME, stampTime);
+                    dynamicObject.set(PerfManagerFormConstant.NCKD_FILEISSUETIME, fileIssueTime);
+                    save.add(dynamicObject);
+
+                }
+                OperationResult operationResult = SaveServiceHelper.saveOperate(
+                        PerfManagerFormConstant.DOCSTAMP_ENTITYID,
+                        save.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());
+                }else{
+                    this.getView().returnDataToParent("true");
+                    this.getView().close();
+                }
+
+
+
+               /* Date fileIssueTime = this.getModel().getDataEntity(true).getDate("nckd_fileissuetime");
+                Date stampTime = this.getModel().getDataEntity(true).getDate("nckd_stamptime");
+                Map<String, Date> returnDate = new HashMap<>();
+                returnDate.put("nckd_fileissuetime", fileIssueTime);
+                returnDate.put("nckd_stamptime", stampTime);
+                this.getView().returnDataToParent(returnDate);
+                this.getView().close();*/
+            }
         }
     }
 }

+ 35 - 6
code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/form/print/PerfBatchPrintListPlugin.java

@@ -2,6 +2,8 @@ package nckd.jxccl.opmc.pm.plugin.form.print;
 
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
 import kd.bos.dataentity.utils.StringUtils;
 import kd.bos.entity.datamodel.events.PackageDataEvent;
 import kd.bos.entity.report.ReportColumn;
@@ -11,15 +13,16 @@ import kd.bos.form.ShowType;
 import kd.bos.form.control.Toolbar;
 import kd.bos.form.control.events.ItemClickEvent;
 import kd.bos.form.events.ClosedCallBackEvent;
+import kd.bos.form.events.PreOpenFormEventArgs;
+import kd.bos.report.ReportList;
 import kd.bos.report.plugin.AbstractReportFormPlugin;
 import kd.sdk.plugin.Plugin;
 import nckd.jxccl.base.common.constant.FormConstant;
-import nckd.jxccl.base.common.utils.ConvertUtil;
 import nckd.jxccl.base.common.utils.DateUtil;
 
-import java.util.Date;
+import java.util.ArrayList;
 import java.util.EventObject;
-import java.util.Map;
+import java.util.List;
 
 /**
 * 人员考评套打列表
@@ -30,6 +33,14 @@ import java.util.Map;
 */
 public class PerfBatchPrintListPlugin extends AbstractReportFormPlugin implements Plugin {
 
+    @Override
+    public void preOpenForm(PreOpenFormEventArgs e) {
+        // 1. 获取表单显示参数对象
+        FormShowParameter showParameter = (FormShowParameter) e.getSource();
+        // 2. 设置页面标题
+        showParameter.setCaption("套打列表");
+        super.preOpenForm(e);
+    }
     @Override
     public void registerListener(EventObject e) {
         super.registerListener(e);
@@ -42,11 +53,28 @@ public class PerfBatchPrintListPlugin extends AbstractReportFormPlugin implement
         String itemKey = evt.getItemKey();
         String operationKey = evt.getOperationKey();
         if("nckd_baritemap".equalsIgnoreCase(itemKey)){
+            ReportList reportList = this.getView().getControl(FormConstant.REPORTLISTAP);
+            int[] selectedRowIndexes = reportList.getEntryState().getSelectedRows();
+            List<Long> personIds =  new ArrayList<>();
+            if(selectedRowIndexes != null && selectedRowIndexes.length > 0) {
+                for (int selectedRowIndex : selectedRowIndexes) {
+                    DynamicObject rowData = reportList.getReportModel().getRowData(selectedRowIndex);
+                    personIds.add(rowData.getDynamicObject(FormConstant.NCKD_PERSON).getLong(FormConstant.ID_KEY));
+                }
+            }else{
+                int rowCount = reportList.getReportModel().getRowCount();
+                DynamicObjectCollection rowDataColl = reportList.getReportModel().getRowData(1, rowCount, false);
+                for (DynamicObject dynamicObject : rowDataColl) {
+                    long personId = dynamicObject.getLong(String.join(".", FormConstant.NCKD_PERSON, FormConstant.ID_KEY));
+                    personIds.add(personId);
+                }
+            }
             FormShowParameter showParameter = new FormShowParameter();
             showParameter.setFormId("nckd_batchmoddocstamppopu");
             showParameter.getOpenStyle().setShowType(ShowType.Modal);
             showParameter.setCloseCallBack(new CloseCallBack(this, "nckd_batchmoddocstamppopu"));
             showParameter.setCaption("批量修改文件印发及盖章时间");
+            showParameter.setCustomParam( "personIds", personIds);
             this.getView().showForm(showParameter);
         }
     }
@@ -57,15 +85,16 @@ public class PerfBatchPrintListPlugin extends AbstractReportFormPlugin implement
         if("nckd_batchmoddocstamppopu".equalsIgnoreCase(actionId)){
             Object returnData = closedCallBackEvent.getReturnData();
             if(returnData != null){
-                Map<String, Date> returnDate = ConvertUtil.toMap(returnData);
-                this.getPageCache().put("fileIssueTime", JSON.toJSONString(returnDate));
+                /*Map<String, Date> returnDate = ConvertUtil.toMap(returnData);
+                this.getPageCache().put("fileIssueTime", JSON.toJSONString(returnDate));*/
+                this.getView().showSuccessNotification( "文件印发及盖章时间修改成功");
                 this.getView().invokeOperation(FormConstant.REFRESH_OP);
             }
         }
     }
 
 
-    @Override
+   @Override
     public void packageData(PackageDataEvent e) {
         String fileIssueTime = this.getPageCache().get("fileIssueTime");
         if(StringUtils.isNotEmpty(fileIssueTime)){

+ 191 - 14
code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/form/print/PrintPerfDetailReportListDataPlugin.java

@@ -2,31 +2,41 @@ package nckd.jxccl.opmc.pm.plugin.form.print;
 
 import kd.bos.algo.DataSet;
 import kd.bos.algo.GroupbyDataSet;
+import kd.bos.algo.JoinType;
+import kd.bos.algo.Row;
+import kd.bos.common.enums.EnableEnum;
+import kd.bos.context.RequestContext;
 import kd.bos.dataentity.entity.LocaleString;
 import kd.bos.entity.EntityMetadataCache;
 import kd.bos.entity.QueryEntityType;
-import kd.bos.entity.cache.AppCache;
-import kd.bos.entity.cache.IAppCache;
 import kd.bos.entity.report.AbstractReportColumn;
 import kd.bos.entity.report.AbstractReportListDataPlugin;
 import kd.bos.entity.report.DynamicReportColumnEvent;
 import kd.bos.entity.report.FastFilter;
 import kd.bos.entity.report.ReportColumn;
 import kd.bos.entity.report.ReportQueryParam;
-import kd.bos.mvc.list.ListDataProvider;
 import kd.bos.orm.query.QCP;
 import kd.bos.orm.query.QFilter;
+import kd.bos.servicehelper.QueryServiceHelper;
+import kd.bos.servicehelper.model.PermissionStatus;
 import kd.hr.hbp.business.servicehelper.HRQueryEntityHelper;
+import kd.sdk.hr.hbp.business.helper.permission.HRPermissionServiceHelper;
 import kd.sdk.plugin.Plugin;
+import nckd.jxccl.base.common.algo.DistinctConcatFunction;
+import nckd.jxccl.base.common.algo.GroupMaxStrFunction;
 import nckd.jxccl.base.common.constant.FormConstant;
 import nckd.jxccl.base.common.utils.DateUtil;
 import nckd.jxccl.base.common.utils.QueryFieldBuilder;
 import nckd.jxccl.opmc.pm.common.PerfManagerFormConstant;
 
 import java.time.LocalDate;
+import java.time.LocalDateTime;
 import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 /**
 * 年度绩效结果明细-报表取数插件
@@ -42,6 +52,7 @@ public class PrintPerfDetailReportListDataPlugin extends AbstractReportListDataP
         super.getDynamicColumns(event);
     }
 
+
     @Override
     public DataSet query(ReportQueryParam reportQueryParam, Object o) throws Throwable {
 
@@ -55,27 +66,41 @@ public class PrintPerfDetailReportListDataPlugin extends AbstractReportListDataP
 
         int currentYear = LocalDate.now().getYear() - 1; // 不包含今年
         Date endDate = DateUtil.toDate(LocalDate.of(currentYear, 1, 1));
+
+
         //查询最近5年的数据
         /*QFilter qFilter = new QFilter(PerfManagerFormConstant.NCKD_BEGINYEAR, QCP.less_equals, endDate)
                 .and(new QFilter(PerfManagerFormConstant.NCKD_ENDYEAR, QCP.large_equals, beginDate));*/
         QFilter qFilter = QFilter.of("1=1");
+        qFilter.and(String.join(".", FormConstant.HRPI_EMPPOSORGREL, FormConstant.POS_STATUS,FormConstant.POST_STATE_CLS, FormConstant.NUMBER_KEY),QCP.equals,"1010_S");
 
         // 处理快速过滤条件
         processFastFilter(reportQueryParam, qFilter);
 
         //其他过滤条件
         processFilter(reportQueryParam, qFilter);
+        //权限过滤
+        QFilter dataRule = HRPermissionServiceHelper.getDataRule(
+                RequestContext.get().getCurrUserId(), "nckd_pm", PerfManagerFormConstant.PERFMANAGER_ENTITYID,
+                PermissionStatus.View, new HashMap<>());
+        if(dataRule != null){
+            qFilter.and(dataRule);
+        }
 
         // 执行基础查询
-        QueryEntityType queryEntityType = (QueryEntityType) EntityMetadataCache.getDataEntityType("annualperfdetailquery");
+        QueryEntityType queryEntityType = (QueryEntityType) EntityMetadataCache.getDataEntityType("printperfquery");
         DataSet dataSet = HRQueryEntityHelper.getInstance().getQueryDataSet(queryEntityType,queryFieldBuilder.buildSelect(), new QFilter[]{qFilter}, null);
-
-        dataSet.print( true);
+        DataSet dataSetCopy = dataSet.copy();
+        Set<Long> personIds = new HashSet();
+        while (dataSetCopy.hasNext()) {
+            Row next = dataSetCopy.next();
+            Long personId = next.getLong(String.join(".", FormConstant.NCKD_PERSON, FormConstant.ID_KEY));
+            personIds.add(personId);
+        }
 
         //过滤调实际结束实际之外的年份分录
         DataSet withYearFields = dataSet.filter("year("+String.join(".", PerfManagerFormConstant.PERFMANAGERENTRY, PerfManagerFormConstant.NCKD_APPRAISALYEAR) +") " +
                 "<= year(CASE WHEN nckd_actendyear is not null THEN nckd_actendyear ELSE "+PerfManagerFormConstant.NCKD_ENDYEAR+" end)");
-        withYearFields.print(true);
 
         // 动态添加年份字段;行转列
         int tempIndex = 1;
@@ -86,7 +111,6 @@ public class PrintPerfDetailReportListDataPlugin extends AbstractReportListDataP
             );
             tempIndex++;
         }
-        withYearFields.print(true);
 
         // 按分组字段聚合
         GroupbyDataSet groupbyDataSet = withYearFields.groupBy(new String[]{
@@ -99,14 +123,17 @@ public class PrintPerfDetailReportListDataPlugin extends AbstractReportListDataP
                 String.join(".", FormConstant.HRPI_EMPPOSORGREL, FormConstant.ADMINORG, FormConstant.NCKD_FOURTHORG, FormConstant.ID_KEY),
                 String.join(".", FormConstant.HRPI_EMPPOSORGREL, FormConstant.ADMINORG, FormConstant.NCKD_FIFTHORG, FormConstant.ID_KEY),
                 String.join(".", FormConstant.HRPI_EMPPOSORGREL, FormConstant.ADMINORG, FormConstant.NCKD_SIXTHORG, FormConstant.ID_KEY),
-                String.join(".", FormConstant.HRPI_EMPPOSORGREL, FormConstant.POS_STATUS, FormConstant.ID_KEY),
+                String.join(".", FormConstant.HRPI_EMPENTREL, FormConstant.LABOR_REL_STATUS, FormConstant.ID_KEY),
                 String.join(".", FormConstant.NCKD_PERSON, FormConstant.NCKD_JOINWORKTIME),
                 String.join(".", FormConstant.NCKD_PERSON, FormConstant.BIRTHDAY),
                 String.join(".", FormConstant.NCKD_PERSON, FormConstant.GENDER,FormConstant.NAME_KEY),
                 String.join(".", FormConstant.HRPI_PEREDUEXP, FormConstant.EDUCATION_KEY,FormConstant.NAME_KEY),
 //                String.join(".", FormConstant.NCKD_EMPPOSORGREL, FormConstant.POSITION_KEY, FormConstant.ID_KEY),
                 String.join(".", "last_perfmanager", PerfManagerFormConstant.NCKD_BEGINYEAR),
-                String.join(".", "last_perfmanager", PerfManagerFormConstant.NCKD_ENDYEAR)
+                String.join(".", "last_perfmanager", PerfManagerFormConstant.NCKD_ENDYEAR),
+                String.join(".", PerfManagerFormConstant.DOCSTAMP_ENTITYID, PerfManagerFormConstant.NCKD_STAMPTIME),
+                String.join(".", PerfManagerFormConstant.DOCSTAMP_ENTITYID, PerfManagerFormConstant.NCKD_FILEISSUETIME),
+                String.join(".", PerfManagerFormConstant.HRPI_EMPPOSORGREL, PerfManagerFormConstant.POSITION_KEY, FormConstant.ID_KEY),
         });
         int tempIndex1 = 1;
         for (int year = fiveYearsAgo; year <= currentYear; year++) {
@@ -114,10 +141,156 @@ public class PrintPerfDetailReportListDataPlugin extends AbstractReportListDataP
                     .max("temp_"+tempIndex1, tempIndex1+"_result");
             tempIndex1++;
         }
-        IAppCache nckdPm = AppCache.get("nckd_pm");
+        //职称/技能使用逗号分拼接
+        groupbyDataSet.agg(new DistinctConcatFunction(),"hrpi_perprotitle.professional.name","perprotitlenames");
+        groupbyDataSet.agg(new DistinctConcatFunction(),"nckd_hrpi_empskill.nckd_qualiname","qualinames");
+
+        DataSet annualPerfDetailQueryDataSet = groupbyDataSet.finish();
+        String[] mainTableFieldNames = annualPerfDetailQueryDataSet.getRowMeta().getFieldNames();
+        // 创建新数组,长度比原数组多1
+        String[] newMainTableFieldNames = new String[mainTableFieldNames.length + 1];
+        System.arraycopy(mainTableFieldNames, 0, newMainTableFieldNames, 0, mainTableFieldNames.length);
+        // 在最后添加新字段
+        newMainTableFieldNames[mainTableFieldNames.length] = "REPLACE(REPLACE(REPLACE(concat(perprotitlenames,';',qualinames),'null,',''),'null;',''),'null','') as perprotitlOrQuali";
+        mainTableFieldNames = newMainTableFieldNames;
+        annualPerfDetailQueryDataSet.select(mainTableFieldNames);
+
+//        获取近5年的岗位信息
+        DataSet positionDateSet = getPositions(fiveYearsAgo, currentYear,personIds);
+        String[] pivotFieldNames = positionDateSet.getRowMeta().getFieldNames();
+        annualPerfDetailQueryDataSet = annualPerfDetailQueryDataSet.join(positionDateSet, JoinType.LEFT)
+                .on(String.join(".", FormConstant.NCKD_PERSON, FormConstant.ID_KEY), String.join(".", FormConstant.EMPLOYEE_KEY, FormConstant.ID_KEY))
+                .select(mainTableFieldNames, pivotFieldNames).finish();
+
+        DataSet perfRankMgmtDataSet = getPerfRankMgmt(personIds, fiveYearsAgo, currentYear);
+
+        mainTableFieldNames = annualPerfDetailQueryDataSet.getRowMeta().getFieldNames();
+        pivotFieldNames = perfRankMgmtDataSet.getRowMeta().getFieldNames();
+        java.util.List<String> filteredFieldNames = new java.util.ArrayList<>();
+        for (String fieldName : pivotFieldNames) {
+            if (!"nckd_person.id".equals(fieldName)) {
+                filteredFieldNames.add(fieldName);
+            }
+        }
+        pivotFieldNames = filteredFieldNames.toArray(new String[0]);
+        return annualPerfDetailQueryDataSet.join(perfRankMgmtDataSet, JoinType.LEFT)
+                .on(String.join(".", FormConstant.NCKD_PERSON, FormConstant.ID_KEY), String.join(".", FormConstant.NCKD_PERSON, FormConstant.ID_KEY))
+                .select(mainTableFieldNames, pivotFieldNames).finish();
+    }
+
+    private static DataSet getPerfRankMgmt(Set<Long> personIds, int beginYear, int endYear) {
+        // 年度绩效排名管理
+        QueryFieldBuilder perfRankMgmtFieldBuilder = QueryFieldBuilder.create()
+                .addIdNumberName(FormConstant.NCKD_PERSON)
+                .add("nckd_toprank")
+                .addGroup(new String[]{"nckd_perfrankmgmt"},"nckd_topranks","nckd_theyear");
+        QFilter perfRankMgmtFilter = new QFilter("nckd_isranking", "=", EnableEnum.YES.getCode())
+                .and(FormConstant.NCKD_PERSON, QCP.in, personIds)
+                .and("nckd_perfrankmgmt.nckd_theyear",QCP.large_equals, beginYear)
+                .and("nckd_perfrankmgmt.nckd_theyear",QCP.less_equals, endYear);
+        DataSet perfRankMgmtDataSet = QueryServiceHelper.queryDataSet("PrintPerfDetailReportListDataPlugin_perfRank", "nckd_perfrankmgmtentry", perfRankMgmtFieldBuilder.buildSelect(), new QFilter[]{perfRankMgmtFilter}, perfRankMgmtFieldBuilder.buildOrder(), 10000);
+        int tempIndex = 1;
+        for (int year = beginYear; year <= endYear; year++) {
+            //排名
+            String toprankField = "CASE WHEN nckd_perfrankmgmt.nckd_theyear = "+year+" THEN nckd_toprank ELSE null END";
+            perfRankMgmtDataSet = perfRankMgmtDataSet.addField(toprankField, "perfrankmgmt_topran_temp_" + tempIndex);
+            //总人数
+            String topranksField = "CASE WHEN nckd_perfrankmgmt.nckd_theyear = "+year+" THEN nckd_perfrankmgmt.nckd_topranks ELSE null END";
+            perfRankMgmtDataSet = perfRankMgmtDataSet.addField(topranksField, "perfrankmgmt_topranks_temp_" + tempIndex);
+            tempIndex++;
+        }
+        GroupbyDataSet groupbyDataSet = perfRankMgmtDataSet.groupBy(new String[]{String.join(".", FormConstant.NCKD_PERSON, FormConstant.ID_KEY)});
+        tempIndex = 1;
+        for (int year = beginYear; year <= endYear; year++) {
+            groupbyDataSet.max("perfrankmgmt_topran_temp_"+tempIndex, "perfrank_topran_"+tempIndex);
+            groupbyDataSet.max("perfrankmgmt_topranks_temp_"+tempIndex, "perfrank_topranks_"+tempIndex);
+            tempIndex++;
+        }
+        return groupbyDataSet.finish();
+    }
+
+
+    /**
+     * 获取近N年的岗位信息
+     * 用于查询每个员工在指定年份范围内每年年底(12月31日)所在的有效岗位
+     * 当一个员工在同一年有多个有效岗位时,选择结束日期最晚的那个岗位
+     *
+     * @param beginYear 起始年份(包含)
+     * @param endYear   结束年份(包含)
+     * @return 包含每个员工每年岗位信息的数据集
+     */
+    private DataSet getPositions(int beginYear,int endYear,Set<Long> personIds){
+        // 查询全职任职关系,获取员工、岗位、任职起止时间等信息
+        QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create()
+                .add(FormConstant.STARTDATE)  // 任职开始日期
+                .add(FormConstant.ENDDATE)    // 任职结束日期
+                .addIdNumberName(FormConstant.POSITION_KEY)  // 岗位信息(ID、编码、名称)
+                .addIdNumberNameWithExtras(new String[]{FormConstant.EMPLOYEE_KEY},FormConstant.EMP_NUMBER_KEY)  // 员工信息(ID、编码、姓名)+ 工号
+                .orderDesc(FormConstant.EMPLOYEE_KEY,FormConstant.STARTDATE);  // 按员工ID和开始日期降序排列
+        // 筛选条件:只查询全职任职(IS_PRIMARY = YES)
+        QFilter qFilter = new QFilter(FormConstant.IS_PRIMARY,QCP.equals, EnableEnum.YES.getCode());
+        if(!personIds.isEmpty()){
+            qFilter = new QFilter(FormConstant.EMPLOYEE_KEY,QCP.in,personIds.toArray());
+        }
+        DataSet dataSet = QueryServiceHelper.queryDataSet("PrintPerfDetailReportListDataPlugin_EMPREL", FormConstant.HRPI_EMPPOSORGREL, queryFieldBuilder.buildSelect(), new QFilter[]{qFilter}, queryFieldBuilder.buildOrder(), 1000000);
+
+        int tempIndex = 1;
+        // 遍历指定年份范围,为每一年生成对应的岗位查询字段
+        for (int year = beginYear; year <= endYear; year++) {
+            // 获取每年12-31 23:59:59作为目标日期,用于判断该员工当年年底的岗位状态
+            Date targetDate = DateUtil.toDate(LocalDateTime.of(year, 12, 31, 23, 59, 59));
+            String targetDateStr = DateUtil.format(targetDate, DateUtil.NORM_DATE_PATTERN); // 使用日期格式而非日期时间格式
+
+            // 创建复合字段:如果在目标日期员工处于有效任职状态,则生成"结束日期|岗位名称"格式的字符串
+            // 这样使用GroupMaxStrFunction时,会根据结束日期选择最晚的那个任职记录
+            //为什么用“00000000000000|”,不用null。因为当GroupMaxStrFunction进行字符串比较时,有效的日期值(如'20231231235959|经济技术部部长')会比'00000000000000|'大,从而被正确选择
+            String combinedField = "CASE WHEN " + FormConstant.STARTDATE + " <= to_date('" + targetDateStr + "','yyyy-MM-dd') " +
+                    "AND " + FormConstant.ENDDATE + " >= to_date('" + targetDateStr + "','yyyy-MM-dd') " +
+                    "THEN CONCAT(TO_CHAR(" + FormConstant.ENDDATE + ", 'YYYYMMDDHHmmss'), '|', " +
+                    String.join(".", FormConstant.POSITION_KEY, FormConstant.NAME_KEY) + ") ELSE '00000000000000|' END";
+
+            // 添加岗位复合字段(包含结束日期和岗位名称)
+            dataSet = dataSet.addField(combinedField, "position_temp_" + tempIndex);
 
+            // 同时创建仅包含日期部分的字段,用于后续解析时去除日期部分,只保留岗位名称
+            String dateField = "CASE WHEN " + FormConstant.STARTDATE + " <= to_date('" + targetDateStr + "','yyyy-MM-dd') " +
+                    "AND " + FormConstant.ENDDATE + " >= to_date('" + targetDateStr + "','yyyy-MM-dd') " +
+                    "THEN CONCAT(TO_CHAR(" + FormConstant.ENDDATE + ", 'YYYYMMDDHHmmss'),'|') ELSE '00000000000000|' END";
+            dataSet = dataSet.addField(dateField, "position_date_" + tempIndex);
+
+//            dataSet = dataSet.addField("'"+year+"'", "position_year_" + tempIndex);
+            tempIndex++;
+        }
+
+        // 行转列处理:按员工ID分组,使用GroupMaxStrFunction获取每个员工每年结束日期最晚的任职记录
+        tempIndex = 1;
+        GroupMaxStrFunction groupMaxStr = new GroupMaxStrFunction();
+        // 按员工ID进行分组聚合
+        GroupbyDataSet groupbyDataSet = dataSet.groupBy(new String[]{String.join(".", FormConstant.EMPLOYEE_KEY, FormConstant.ID_KEY)});
+        // 对每一年的数据进行聚合,获取结束日期最晚的任职记录
+        for (int year = beginYear; year <= endYear; year++) {
+            // 获取岗位复合字段的最大值(即结束日期最晚的记录)
+            groupbyDataSet.agg(new GroupMaxStrFunction(),"position_temp_"+tempIndex, "position_max_"+tempIndex);
+            // 同时获取日期字段的最大值,用于后续解析
+            groupbyDataSet.agg(groupMaxStr,"position_date_"+tempIndex, "position_date_max_"+tempIndex);
+            tempIndex++;
+        }
         DataSet result = groupbyDataSet.finish();
-        result.print( true);
+
+        // 解析复合字段,提取真正的岗位名称
+        // 通过去除日期部分(YYYYMMDDHHmmss|)来获取原始的岗位名称
+        tempIndex = 1;
+        for (int year = beginYear; year <= endYear; year++) {
+            final int currentYearIndex = year - beginYear + 1;
+            result = result.addField(
+                    // 如果岗位字段有效(不为默认值'00000000000000|'),则去除日期部分,只保留岗位名称
+                    "CASE WHEN position_max_" + tempIndex + " IS NOT NULL AND position_max_" + tempIndex + " != '00000000000000|' THEN " +
+                            "REPLACE(position_max_" + tempIndex + ",position_date_max_"+tempIndex+",'') " +  // 去除日期部分,得到岗位名称
+                            "ELSE null END",
+                    "position_" + tempIndex  // 最终的岗位名称字段
+            );
+            tempIndex++;
+        }
         return result;
     }
 
@@ -168,17 +341,21 @@ public class PrintPerfDetailReportListDataPlugin extends AbstractReportListDataP
                 .add(String.join(".", FormConstant.NCKD_PERSON, FormConstant.BIRTHDAY))
                 .add(String.join(".", FormConstant.NCKD_PERSON, FormConstant.GENDER,FormConstant.NAME_KEY))
                 .add(String.join(".", FormConstant.HRPI_PEREDUEXP, FormConstant.EDUCATION_KEY,FormConstant.NAME_KEY))
-                .addIdNumberName(FormConstant.HRPI_EMPPOSORGREL,FormConstant.POS_STATUS)
+                .addIdNumberName(FormConstant.HRPI_EMPENTREL,FormConstant.LABOR_REL_STATUS)
                 .addIdNumberName(FormConstant.HRPI_EMPPOSORGREL,FormConstant.ADMINORG,FormConstant.NCKD_FIRSTORG)
                 .addIdNumberName(FormConstant.HRPI_EMPPOSORGREL,FormConstant.ADMINORG,FormConstant.NCKD_SECONDORG)
                 .addIdNumberName(FormConstant.HRPI_EMPPOSORGREL,FormConstant.ADMINORG,FormConstant.NCKD_THIRDORG)
                 .addIdNumberName(FormConstant.HRPI_EMPPOSORGREL,FormConstant.ADMINORG,FormConstant.NCKD_FOURTHORG)
                 .addIdNumberName(FormConstant.HRPI_EMPPOSORGREL,FormConstant.ADMINORG,FormConstant.NCKD_FIFTHORG)
                 .addIdNumberName(FormConstant.HRPI_EMPPOSORGREL,FormConstant.ADMINORG,FormConstant.NCKD_SIXTHORG)
+                .addIdNumberName( PerfManagerFormConstant.HRPI_EMPPOSORGREL, PerfManagerFormConstant.POSITION_KEY)
 //                .addIdNumberName(FormConstant.HRPI_EMPPOSORGREL,FormConstant.POSITION_KEY)
                 .addGroup(new String[]{"last_perfmanager"},
                         PerfManagerFormConstant.NCKD_BEGINYEAR,
-                        PerfManagerFormConstant.NCKD_ENDYEAR);
+                        PerfManagerFormConstant.NCKD_ENDYEAR)
+                .addGroup(new String[]{PerfManagerFormConstant.DOCSTAMP_ENTITYID},PerfManagerFormConstant.NCKD_STAMPTIME,PerfManagerFormConstant.NCKD_FILEISSUETIME)
+                .add(String.join(".", FormConstant.HRPI_PERPROTITLE, FormConstant.PROFESSIONAL_KEY,FormConstant.NAME_KEY))
+                .add(String.join(".", FormConstant.NCKD_HRPI_EMPSKILL, FormConstant.NCKD_QUALINAME));
 
     }
 

+ 9 - 0
code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/form/result/AnnualPerfDetailFormPlugin.java

@@ -12,6 +12,7 @@ import kd.bos.form.FormShowParameter;
 import kd.bos.form.MessageBoxOptions;
 import kd.bos.form.ShowType;
 import kd.bos.form.events.AfterDoOperationEventArgs;
+import kd.bos.form.events.PreOpenFormEventArgs;
 import kd.bos.form.plugin.AbstractFormPlugin;
 import kd.bos.report.ReportList;
 import kd.bos.servicehelper.operation.OperationServiceHelper;
@@ -36,6 +37,14 @@ import java.util.stream.Stream;
 */
 public class AnnualPerfDetailFormPlugin extends AbstractFormPlugin implements Plugin {
 
+    @Override
+    public void preOpenForm(PreOpenFormEventArgs e) {
+        // 1. 获取表单显示参数对象
+        FormShowParameter showParameter = (FormShowParameter) e.getSource();
+        // 2. 设置页面标题
+        showParameter.setCaption("年度绩效结果明细");
+        super.preOpenForm(e);
+    }
 
     @Override
     public void afterDoOperation(AfterDoOperationEventArgs e) {

+ 45 - 10
code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/form/result/AnnualPerfDetailReportListDataPlugin.java

@@ -2,6 +2,7 @@ package nckd.jxccl.opmc.pm.plugin.form.result;
 
 import kd.bos.algo.DataSet;
 import kd.bos.algo.GroupbyDataSet;
+import kd.bos.context.RequestContext;
 import kd.bos.dataentity.entity.LocaleString;
 import kd.bos.entity.EntityMetadataCache;
 import kd.bos.entity.QueryEntityType;
@@ -12,8 +13,11 @@ import kd.bos.entity.report.ReportColumn;
 import kd.bos.entity.report.ReportQueryParam;
 import kd.bos.orm.query.QCP;
 import kd.bos.orm.query.QFilter;
+import kd.bos.servicehelper.model.PermissionStatus;
 import kd.hr.hbp.business.servicehelper.HRQueryEntityHelper;
+import kd.sdk.hr.hbp.business.helper.permission.HRPermissionServiceHelper;
 import kd.sdk.plugin.Plugin;
+import nckd.jxccl.base.common.algo.DistinctConcatFunction;
 import nckd.jxccl.base.common.constant.FormConstant;
 import nckd.jxccl.base.common.utils.DateUtil;
 import nckd.jxccl.base.common.utils.QueryFieldBuilder;
@@ -21,6 +25,7 @@ import nckd.jxccl.opmc.pm.common.PerfManagerFormConstant;
 
 import java.time.LocalDate;
 import java.util.Date;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -33,6 +38,7 @@ import java.util.Map;
 */
 public class AnnualPerfDetailReportListDataPlugin extends AbstractReportListDataPlugin implements Plugin {
 
+
     @Override
     public DataSet query(ReportQueryParam reportQueryParam, Object o) throws Throwable {
 
@@ -44,12 +50,13 @@ public class AnnualPerfDetailReportListDataPlugin extends AbstractReportListData
         int fiveYearsAgo = LocalDate.now().minusYears(now.getYear() - 2018).getYear();
         Date beginDate = DateUtil.toDate(LocalDate.of(fiveYearsAgo, 1, 1));
 
-        int currentYear = LocalDate.now().getYear() - 1; // 不包含今年
+        int currentYear = LocalDate.now().getYear(); // 不包含今年
         Date endDate = DateUtil.toDate(LocalDate.of(currentYear, 1, 1));
         //查询最近5年的数据
         /*QFilter qFilter = new QFilter(PerfManagerFormConstant.NCKD_BEGINYEAR, QCP.less_equals, endDate)
                 .and(new QFilter(PerfManagerFormConstant.NCKD_ENDYEAR, QCP.large_equals, beginDate));*/
         QFilter qFilter = QFilter.of("1=1");
+        qFilter.and(String.join(".", FormConstant.HRPI_EMPPOSORGREL, FormConstant.POS_STATUS,FormConstant.POST_STATE_CLS, FormConstant.NUMBER_KEY),QCP.equals,"1010_S");
 
         // 处理快速过滤条件
         processFastFilter(reportQueryParam, qFilter);
@@ -57,6 +64,14 @@ public class AnnualPerfDetailReportListDataPlugin extends AbstractReportListData
         //其他过滤条件
         processFilter(reportQueryParam, qFilter);
 
+        //权限过滤
+        QFilter dataRule = HRPermissionServiceHelper.getDataRule(
+                RequestContext.get().getCurrUserId(), "nckd_pm", PerfManagerFormConstant.PERFMANAGER_ENTITYID,
+                PermissionStatus.View, new HashMap<>());
+        if(dataRule != null){
+            qFilter.and(dataRule);
+        }
+
         // 执行基础查询
         QueryEntityType queryEntityType = (QueryEntityType) EntityMetadataCache.getDataEntityType("annualperfdetailquery");
         DataSet dataSet = HRQueryEntityHelper.getInstance().getQueryDataSet(queryEntityType,queryFieldBuilder.buildSelect(), new QFilter[]{qFilter}, null);
@@ -77,7 +92,7 @@ public class AnnualPerfDetailReportListDataPlugin extends AbstractReportListData
             );
             tempIndex++;
         }
-        withYearFields.print(true);
+
 
         // 按分组字段聚合
         GroupbyDataSet groupbyDataSet = withYearFields.groupBy(new String[]{
@@ -90,10 +105,15 @@ public class AnnualPerfDetailReportListDataPlugin extends AbstractReportListData
                 String.join(".", FormConstant.HRPI_EMPPOSORGREL, FormConstant.ADMINORG, FormConstant.NCKD_FOURTHORG, FormConstant.ID_KEY),
                 String.join(".", FormConstant.HRPI_EMPPOSORGREL, FormConstant.ADMINORG, FormConstant.NCKD_FIFTHORG, FormConstant.ID_KEY),
                 String.join(".", FormConstant.HRPI_EMPPOSORGREL, FormConstant.ADMINORG, FormConstant.NCKD_SIXTHORG, FormConstant.ID_KEY),
-                String.join(".", FormConstant.HRPI_EMPPOSORGREL, FormConstant.POS_STATUS, FormConstant.ID_KEY),
+                String.join(".", FormConstant.NCKD_PERSON, FormConstant.NCKD_JOINWORKTIME),
+                String.join(".", FormConstant.NCKD_PERSON, FormConstant.BIRTHDAY),
+                String.join(".", FormConstant.NCKD_PERSON, FormConstant.GENDER,FormConstant.NAME_KEY),
+                String.join(".", FormConstant.HRPI_PEREDUEXP, FormConstant.EDUCATION_KEY,FormConstant.NAME_KEY),
+
 //                String.join(".", FormConstant.NCKD_EMPPOSORGREL, FormConstant.POSITION_KEY, FormConstant.ID_KEY),
                 String.join(".", "last_perfmanager", PerfManagerFormConstant.NCKD_BEGINYEAR),
-                String.join(".", "last_perfmanager", PerfManagerFormConstant.NCKD_ENDYEAR)
+                String.join(".", "last_perfmanager", PerfManagerFormConstant.NCKD_ENDYEAR),
+                String.join(".", PerfManagerFormConstant.HRPI_EMPPOSORGREL, PerfManagerFormConstant.POSITION_KEY, FormConstant.ID_KEY),
         });
         int tempIndex1 = 1;
         for (int year = fiveYearsAgo; year <= currentYear; year++) {
@@ -101,17 +121,26 @@ public class AnnualPerfDetailReportListDataPlugin extends AbstractReportListData
                     .max("temp_"+tempIndex1, tempIndex1+"_result");
             tempIndex1++;
         }
-
+        //职称/技能使用逗号分拼接
+        groupbyDataSet.agg(new DistinctConcatFunction(),"hrpi_perprotitle.professional.name","perprotitlenames");
+        groupbyDataSet.agg(new DistinctConcatFunction(),"nckd_hrpi_empskill.nckd_qualiname","qualinames");
         DataSet result = groupbyDataSet.finish();
-        result.print( true);
-        return result;
+        // 创建新数组,长度比原数组多1
+        String[] mainTableFieldNames = result.getRowMeta().getFieldNames();
+        String[] newMainTableFieldNames = new String[mainTableFieldNames.length + 1];
+        System.arraycopy(mainTableFieldNames, 0, newMainTableFieldNames, 0, mainTableFieldNames.length);
+        // 在最后添加新字段
+        newMainTableFieldNames[mainTableFieldNames.length] = "REPLACE(REPLACE(REPLACE(concat(perprotitlenames,';',qualinames),'null,',''),'null;',''),'null','') as perprotitlOrQuali";
+        mainTableFieldNames = newMainTableFieldNames;
+
+        return   result.select(mainTableFieldNames);
     }
 
     @Override
     public List<AbstractReportColumn> getColumns(List<AbstractReportColumn> columns) throws Throwable {
         LocalDate now = LocalDate.now();
         int fiveYearsAgo = LocalDate.now().minusYears(now.getYear()-2018).getYear();
-        int currentYear = LocalDate.now().getYear() - 1; // 不包含今年
+        int currentYear = LocalDate.now().getYear() ; // 不包含今年
 
         for (AbstractReportColumn column : columns) {
             if (column instanceof ReportColumn) {
@@ -150,17 +179,23 @@ public class AnnualPerfDetailReportListDataPlugin extends AbstractReportListData
                 .addGroup(new String[]{PerfManagerFormConstant.PERFMANAGERENTRY},PerfManagerFormConstant.ID_KEY)
                 .addGroup(new String[]{FormConstant.NCKD_EMPPOSORGREL,FormConstant.EMPLOYEE_KEY}, FormConstant.EMP_NUMBER_KEY, FormConstant.NAME_KEY)
                 .addIdNumberName(FormConstant.NCKD_PERSON)
-                .addIdNumberName(FormConstant.HRPI_EMPPOSORGREL,FormConstant.POS_STATUS)
+                .add(String.join(".", FormConstant.NCKD_PERSON, FormConstant.NCKD_JOINWORKTIME))
+                .add(String.join(".", FormConstant.NCKD_PERSON, FormConstant.BIRTHDAY))
+                .add(String.join(".", FormConstant.NCKD_PERSON, FormConstant.GENDER,FormConstant.NAME_KEY))
+                .add(String.join(".", FormConstant.HRPI_PEREDUEXP, FormConstant.EDUCATION_KEY,FormConstant.NAME_KEY))
                 .addIdNumberName(FormConstant.HRPI_EMPPOSORGREL,FormConstant.ADMINORG,FormConstant.NCKD_FIRSTORG)
                 .addIdNumberName(FormConstant.HRPI_EMPPOSORGREL,FormConstant.ADMINORG,FormConstant.NCKD_SECONDORG)
                 .addIdNumberName(FormConstant.HRPI_EMPPOSORGREL,FormConstant.ADMINORG,FormConstant.NCKD_THIRDORG)
                 .addIdNumberName(FormConstant.HRPI_EMPPOSORGREL,FormConstant.ADMINORG,FormConstant.NCKD_FOURTHORG)
                 .addIdNumberName(FormConstant.HRPI_EMPPOSORGREL,FormConstant.ADMINORG,FormConstant.NCKD_FIFTHORG)
                 .addIdNumberName(FormConstant.HRPI_EMPPOSORGREL,FormConstant.ADMINORG,FormConstant.NCKD_SIXTHORG)
+                .addIdNumberName( PerfManagerFormConstant.HRPI_EMPPOSORGREL, PerfManagerFormConstant.POSITION_KEY)
 //                .addIdNumberName(FormConstant.HRPI_EMPPOSORGREL,FormConstant.POSITION_KEY)
                 .addGroup(new String[]{"last_perfmanager"},
                         PerfManagerFormConstant.NCKD_BEGINYEAR,
-                        PerfManagerFormConstant.NCKD_ENDYEAR);
+                        PerfManagerFormConstant.NCKD_ENDYEAR)
+                .add(String.join(".", FormConstant.HRPI_PERPROTITLE, FormConstant.PROFESSIONAL_KEY,FormConstant.NAME_KEY))
+                .add(String.join(".", FormConstant.NCKD_HRPI_EMPSKILL, FormConstant.NCKD_QUALINAME));
 
     }
 

+ 20 - 16
code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/operate/cycle/CycleGenerateOpPlugin.java

@@ -22,6 +22,7 @@ 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.servicehelper.model.PermissionStatus;
 import kd.bos.servicehelper.operation.OperationServiceHelper;
 import kd.hr.hbp.business.servicehelper.HRQueryEntityHelper;
 import kd.hr.hbp.common.model.AuthorizedOrgResultWithSub;
@@ -184,21 +185,13 @@ public class CycleGenerateOpPlugin extends AbstractOperationServicePlugIn implem
         }else{
             return personPerfInfoMap;
         }*/
-        // 只处理权限范围内的人员
-        AuthorizedOrgResultWithSub userAdminOrgWithSub = HRPermissionServiceHelper.getUserAdminOrgsWithSub(
-                currUserId, "nckd_pm", PerfManagerFormConstant.PERFMANAGER_ENTITYID,
-                PermItemConst.ITEM_VIEW, "hrpi_empposorgrel.adminorg", new HashMap<>());
 
-        if (!userAdminOrgWithSub.isHasAllOrgPerm()) {
-            List<Long> orgIds = extractOrgIds(userAdminOrgWithSub.getHasPermOrgsWithSub());
-            newHireFilter.and(String.join( ".",FormConstant.ADMINORG,FormConstant.ID_KEY), QCP.in, orgIds);
-        }
 
 
         DynamicObjectCollection newHirePersonList = queryNewHirePersons(newHireFilter);
 
         // 构建考核周期查询条件
-        QFilter perfManagerFilter = buildPerfManagerFilter(userAdminOrgWithSub);
+        QFilter perfManagerFilter = buildPerfManagerFilter();
         QueryFieldBuilder perfManagerQueryFieldBuilder = buildPerfManagerQueryFieldBuilder();
         QueryEntityType perfManagerQueryEntityType = (QueryEntityType) EntityMetadataCache.getDataEntityTypeNoCache("nckd_perfmanager_query");
 
@@ -208,7 +201,6 @@ public class CycleGenerateOpPlugin extends AbstractOperationServicePlugIn implem
             DataSet perfManagerQueryDataSet = HRQueryEntityHelper.getInstance().getQueryDataSet(
                     perfManagerQueryEntityType, perfManagerQueryFieldBuilder.buildSelectLowerCase(),
                     new QFilter[]{perfManagerFilter}, perfManagerQueryFieldBuilder.buildOrder());
-            perfManagerQueryDataSet.print(true);
 
             // 收集所有人员ID
             collectPersonIds(personIds, perfManagerQueryDataSet.copy());
@@ -245,12 +237,21 @@ public class CycleGenerateOpPlugin extends AbstractOperationServicePlugIn implem
      * 构建新入职员工查询条件
      */
     private static QFilter buildNewHireFilter(LocalDateTime lastBegin, LocalDateTime lastEnd) {
-        return new QFilter(String.join(".", FormConstant.HRPI_EMPENTREL, FormConstant.ENTRYDATE), QCP.large_equals, lastBegin)
+        QFilter filter = new QFilter(String.join(".", FormConstant.HRPI_EMPENTREL, FormConstant.ENTRYDATE), QCP.large_equals, lastBegin)
                 .and(String.join(".", FormConstant.HRPI_EMPENTREL, FormConstant.ENTRYDATE), QCP.less_equals, lastEnd)
                 .and(String.join(".", FormConstant.HRPI_EMPENTREL, FormConstant.LABOR_REL_STATUS, FormConstant.IS_HIRED),
                         QCP.equals, EnableEnum.YES.getCode())
                 //岗位绩效工资制
-                .and(String.join(".",FormConstant.POSITION_KEY,FormConstant.NCKD_PAYSTDPLAN, FormConstant.NUMBER_KEY),QCP.equals,FormConstant.POST_PERF_WAGE_SYS);
+                .and(String.join(".", FormConstant.POSITION_KEY, FormConstant.NCKD_PAYSTDPLAN, FormConstant.NUMBER_KEY), QCP.equals, FormConstant.POST_PERF_WAGE_SYS);
+        //数据范围过滤(考评周期有什么权限那么就能生成什么范围的人员)
+        QFilter dataRule = HRPermissionServiceHelper.getDataRule(
+                RequestContext.get().getCurrUserId(), "nckd_pm",  PerfManagerFormConstant.PERFMANAGER_ENTITYID,
+                PermItemConst.ITEM_VIEW, new HashMap<>());
+        if (dataRule != null) {
+            Object value = dataRule.getValue();
+            filter.and(FormConstant.ADMINORG,QCP.in, value);
+        }
+        return filter;
 
     }
 
@@ -278,11 +279,14 @@ public class CycleGenerateOpPlugin extends AbstractOperationServicePlugIn implem
     /**
      * 构建考核周期查询条件
      */
-    private static QFilter buildPerfManagerFilter(AuthorizedOrgResultWithSub userAdminOrgWithSub) {
+    private static QFilter buildPerfManagerFilter() {
         QFilter perfManagerFilter = QFilter.of("1=1");
-        if (!userAdminOrgWithSub.isHasAllOrgPerm()) {
-            List<Long> orgIds = extractOrgIds(userAdminOrgWithSub.getHasPermOrgsWithSub());
-            perfManagerFilter.and(String.join(".", FormConstant.HRPI_EMPPOSORGREL, FormConstant.ADMINORG), QCP.in, orgIds);
+        // 只处理权限范围内的人员
+        QFilter dataRule = HRPermissionServiceHelper.getDataRule(
+                RequestContext.get().getCurrUserId(), "nckd_pm",  PerfManagerFormConstant.PERFMANAGER_ENTITYID,
+                PermItemConst.ITEM_VIEW, new HashMap<>());
+        if (dataRule != null) {
+            perfManagerFilter.and(dataRule);
         }
 //        perfManagerFilter.and(String.join(".", FormConstant.HRPI_EMPPOSORGREL, FormConstant.IS_SEQLATESTRECORD), QCP.equals,EnableEnum.YES.getCode());
         //岗位绩效工资制

+ 9 - 9
code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/operate/salary/SalaryAdjOpPlugin.java

@@ -96,12 +96,9 @@ public class SalaryAdjOpPlugin extends AbstractOperationServicePlugIn implements
 
         Long currUserId = RequestContext.get().getCurrUserId();
         DynamicObject currUser = UserServiceHelper.getUserInfoByID(currUserId, FormConstant.ID_KEY);
-        // 只处理权限范围内的人员
-        AuthorizedOrgResultWithSub userAdminOrgWithSub = HRPermissionServiceHelper.getUserAdminOrgsWithSub(
-                currUserId, "nckd_pm", PerfManagerFormConstant.PERFMANAGER_ENTITYID,
-                PermItemConst.ITEM_VIEW, "hrpi_empposorgrel.adminorg", new HashMap<>());
+
         // 构建考核周期查询条件
-        QFilter perfManagerFilter = buildPerfManagerFilter(userAdminOrgWithSub);
+        QFilter perfManagerFilter = buildPerfManagerFilter();
         perfManagerFilter.and(PerfManagerFormConstant.NCKD_SALARYADJUSTGENFLAG,QCP.not_equals,EnableEnum.YES.getCode());
         QueryFieldBuilder perfManagerQueryFieldBuilder = buildPerfManagerQueryFieldBuilder();
         DynamicObjectCollection perfManagerList = QueryServiceHelper.query(PerfManagerFormConstant.PERFMANAGER_ENTITYID, perfManagerQueryFieldBuilder.buildSelect(), new QFilter[]{perfManagerFilter});
@@ -657,11 +654,14 @@ public class SalaryAdjOpPlugin extends AbstractOperationServicePlugIn implements
     /**
      * 构建考核周期查询条件
      */
-    private static QFilter buildPerfManagerFilter(AuthorizedOrgResultWithSub userAdminOrgWithSub) {
+    private static QFilter buildPerfManagerFilter() {
         QFilter perfManagerFilter = QFilter.of("1=1");
-        if (!userAdminOrgWithSub.isHasAllOrgPerm()) {
-            List<Long> orgIds = extractOrgIds(userAdminOrgWithSub.getHasPermOrgsWithSub());
-            perfManagerFilter.and(String.join(".", FormConstant.NCKD_EMPPOSORGREL, FormConstant.ADMINORG), QCP.in, orgIds);
+        // 只处理权限范围内的人员
+        QFilter dataRule = HRPermissionServiceHelper.getDataRule(
+                RequestContext.get().getCurrUserId(), "nckd_pm",  PerfManagerFormConstant.PERFMANAGER_ENTITYID,
+                PermItemConst.ITEM_VIEW, new HashMap<>());
+        if (dataRule != null) {
+            perfManagerFilter.and(dataRule);
         }
         perfManagerFilter.and(PerfManagerFormConstant.NCKD_THESTATUS, QCP.equals, EnableEnum.YES.getCode());
         return perfManagerFilter;

+ 14 - 2
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/business/coordination/SinsurCoordSplitService.java

@@ -1,7 +1,6 @@
 package nckd.jxccl.sit.hcsi.business.coordination;
 
 
-import com.kingdee.bos.framework.core.exception.BizException;
 import kd.bos.dataentity.OperateOption;
 import kd.bos.dataentity.entity.DynamicObject;
 import kd.bos.dataentity.entity.DynamicObjectCollection;
@@ -11,7 +10,6 @@ import kd.bos.logging.Log;
 import kd.bos.logging.LogFactory;
 import kd.bos.org.utils.DynamicObjectUtils;
 import kd.bos.servicehelper.operation.OperationServiceHelper;
-import kd.bos.servicehelper.operation.SaveServiceHelper;
 import nckd.jxccl.sit.hcsi.common.constant.SitConstant;
 
 import java.util.HashSet;
@@ -79,6 +77,7 @@ public class SinsurCoordSplitService {
                 DynamicObjectUtils.copy(oldEntry, newEntry);
                 newBill.set("welfarepayer_r31", oldEntry.getDynamicObject("nckd_welfarepayer"));
                 newBill.set("welfarepayertheory_r31", oldEntry.getDynamicObject("nckd_welfarepayertheory"));
+                newBill.set("sinsurstd_r31", getSinSurStdByWelfPayerId(oldEntry.getLong("nckd_welfarepayer.id")));
             }
             newBillCol.add(newBill);
         }
@@ -174,6 +173,19 @@ public class SinsurCoordSplitService {
         return isNeedSplit;
     }
 
+    /**
+     * 根据实际参保单位获取参保标准
+     * 直接取参保单位上参保标准字段
+     *
+     * @param welfPayerId
+     * @return
+     */
+    public DynamicObject getSinSurStdByWelfPayerId (Long welfPayerId) {
+        DynamicObject dyn = SitConstant.WELFARETYPE_HELPER.loadOne(welfPayerId);
+        return dyn.getDynamicObject("mulsinsurstd");
+    }
+
+
     /**
      * 获取社保员工变动处理单数据包
      * @return

+ 2 - 1
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/opplugin/web/coordination/SinsurEmpConfirmOpEx.java

@@ -7,6 +7,7 @@ import kd.bos.entity.plugin.args.EndOperationTransactionArgs;
 import kd.hr.hbp.common.util.HRStringUtils;
 import kd.hr.hbp.opplugin.web.HRDataBaseOp;
 import nckd.jxccl.sit.hcsi.validate.web.SinsurEmpCoordBillValidator;
+import nckd.jxccl.sit.hcsi.validate.web.SinsurEmpCoordConfirmEffectValidator;
 
 /**
  * Tyx 2025-10-28
@@ -22,6 +23,6 @@ public class SinsurEmpConfirmOpEx extends HRDataBaseOp {
     @Override
     public void onAddValidators(AddValidatorsEventArgs e) {
         super.onAddValidators(e);
-        e.addValidator(new SinsurEmpCoordBillValidator());
+        e.addValidator(new SinsurEmpCoordConfirmEffectValidator());
     }
 }

+ 25 - 0
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/utils/SITCoordinationUtils.java

@@ -4,6 +4,7 @@ import kd.bos.dataentity.entity.DynamicObject;
 import kd.bos.dataentity.entity.DynamicObjectCollection;
 import kd.bos.orm.query.QCP;
 import kd.bos.orm.query.QFilter;
+import kd.bos.util.StringUtils;
 import kd.hr.hbp.business.servicehelper.HRBaseServiceHelper;
 import kd.sdk.sit.sitbp.common.StdDimDTO;
 import kd.sdk.sit.sitbp.common.StdInsuranceItemDTO;
@@ -160,5 +161,29 @@ public class SITCoordinationUtils {
         return result;
     }
 
+    /**
+     * 根据险种判断参保标准是否启用了险种维度
+     * @param map
+     * @param insurTypeId 险种ID
+     */
+    public boolean getEnableDimByInsurTypeId(Map<Long, StdResultInfoDTO.StdInsurTypeResultInfoDTO> map, Long insurTypeId) {
+        StdResultInfoDTO.StdInsurTypeResultInfoDTO infoDTO = map.get(insurTypeId);
+        List<StdResultInfoDTO.StdDimRsInfo> stdDimRsInfoList = infoDTO.getStdDimRsInfos();
+        for (StdResultInfoDTO.StdDimRsInfo stdDimRsInfo : stdDimRsInfoList) {
+            List<StdDimDTO> stdDimDTOList = stdDimRsInfo.getStdDimDTOs();
+            for (StdDimDTO stdDimDTO : stdDimDTOList) {
+                String fieldKey = stdDimDTO.getField();
+                if(!StringUtils.isEmpty(fieldKey)) {
+                    if(fieldKey.contains("nckd_sinsurdima")) {
+                        return true;
+                    }
+                }
+            }
+        }
+        return false;
+    }
+
+
+
 
 }

+ 54 - 0
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/validate/web/SinsurEmpCoordConfirmEffectValidator.java

@@ -0,0 +1,54 @@
+package nckd.jxccl.sit.hcsi.validate.web;
+
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.utils.ObjectUtils;
+import kd.bos.entity.ExtendedDataEntity;
+import kd.bos.entity.validate.AbstractValidator;
+import kd.bos.util.StringUtils;
+import kd.sdk.sit.sitbp.business.helper.SITBPServiceHelper;
+import kd.sdk.sit.sitbp.common.StdDimDTO;
+import kd.sdk.sit.sitbp.common.StdResultInfoDTO;
+import nckd.jxccl.sit.hcsi.utils.SITCoordinationUtils;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+
+/**
+ * 社保核定单确认生效/拆单校验器
+ * 核定单中提单生效时,增加险种维度的校验,参保标准启用了险种维度的,校验提醒险种维度必填,参保标准未启用险种维度的,险种维度可以非必填
+ */
+public class SinsurEmpCoordConfirmEffectValidator extends AbstractValidator {
+
+    private SITCoordinationUtils SITCoordinationUtils = new SITCoordinationUtils();
+    @Override
+    public void validate() {
+        for (ExtendedDataEntity dataEntity : dataEntities) {
+            DynamicObject bill = dataEntity.getDataEntity();
+            DynamicObject sinsurStd = bill.getDynamicObject("sinsurstd_r31");
+            StdResultInfoDTO stdResultInfoDTO = SITBPServiceHelper.getStdInfoAndStdDim(Arrays.asList(sinsurStd.getLong("id"))).get(sinsurStd.getLong("id"));
+            List<StdResultInfoDTO.StdInsurTypeResultInfoDTO> StdInsurTypeResultInfoDTOs = stdResultInfoDTO.getStdInsurTypeResultInfoDTOS();
+            Map<Long, StdResultInfoDTO.StdInsurTypeResultInfoDTO> map = StdInsurTypeResultInfoDTOs.stream().collect(Collectors.toMap((dyx) -> {
+                return dyx.getInsurTypeId();
+            }, (dyx) -> {
+                return dyx;
+            }, (key1, key2) -> {
+                return key2;
+            }));
+            // 判断各险种是否启用险种维度,如果启用则再判断险种维度是否有选,没选的话添加错误信息
+            for(DynamicObject entry: bill.getDynamicObjectCollection("nckd_entryentity")) {
+                DynamicObject welfAreType = entry.getDynamicObject("nckd_welfaretype");
+                boolean isEnable = SITCoordinationUtils.getEnableDimByInsurTypeId(map, welfAreType.getLong("id"));
+                // 如果启用了险种维度,再判断你险种维度是否选择
+                if(isEnable) {
+                    DynamicObject dimensionDyn = entry.getDynamicObject("nckd_sinsurdimension");
+                    if(ObjectUtils.isEmpty(dimensionDyn)) {
+                        this.addFatalErrorMessage(dataEntity, "第" + entry.getInt("seq") + "行,请选择险种维度!");
+                    }
+                }
+            }
+        }
+    }
+}

+ 9 - 1
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/mas/common/MasConstant.java → code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/constants/MasConstant.java

@@ -1,4 +1,4 @@
-package nckd.jxccl.swc.mas.common;
+package nckd.jxccl.swc.constants;
 
 import nckd.jxccl.base.common.constant.FormConstant;
 
@@ -187,6 +187,8 @@ public class MasConstant extends FormConstant {
     public static final String NCKD_DEFERPAYMONEY = "nckd_deferpaymoney";
     /** 支付总年数 */
     public static final String NCKD_PAYOUTTIMES = "nckd_payouttimes";
+    /** 支付总年数 */
+    public static final String NCKD_TOTALBONUSAMT = "nckd_totalbonusamt";
     /*-------------------------------------- 延期支付比例 end --------------------------------------*/
 
     /*-------------------------------------- 子企业负责人正职年度薪酬核定标准_变更单 begin --------------------------------------*/
@@ -205,4 +207,10 @@ public class MasConstant extends FormConstant {
     /*-------------------------------------- 企业负责人个人年度薪酬标准核定表 end --------------------------------------*/
 
 
+    /*-------------------------------------- 企业负责人个人年度薪酬标准核定表 begin --------------------------------------*/
+    /** 企业负责人个人年度薪酬标准核定表-实体标识 */
+    public static final String ENTLDRTERMBONUSAPPR_ENTITYID = "nckd_entldrtermbonusappr";
+    /*-------------------------------------- 企业负责人个人年度薪酬标准核定表 end --------------------------------------*/
+
+
 }

+ 81 - 2
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/stm/common/StmConstant.java → code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/constants/StmConstant.java

@@ -1,4 +1,4 @@
-package nckd.jxccl.swc.stm.common;
+package nckd.jxccl.swc.constants;
 
 import com.google.common.collect.Lists;
 import nckd.jxccl.base.common.constant.FormConstant;
@@ -6,7 +6,7 @@ import nckd.jxccl.base.common.constant.FormConstant;
 import java.util.List;
 
 /**
- * 动态表单插件
+ * 工资总额
  */
 public class StmConstant extends FormConstant {
 
@@ -235,4 +235,83 @@ public class StmConstant extends FormConstant {
 
     public static final List<String> IGNORE_FIELDS = Lists.newArrayList(NCKD_YEAR,NCKD_PAYUNIT,NCKD_DEP,UNITSTBUDGETAPPLY_ENTITYID,GRPTTLWGBGTSUB_ENTITYID,StmConstant.NCKD_PAYUNIT,String.join( ".", StmConstant.NCKD_PAYUNIT, FormConstant.NAME_KEY));
     public static final List<String> IGNORE_SUMMARY_FIELDS = Lists.newArrayList(NCKD_DMTEAMTOTAL ,NCKD_DMOTHERTTOTAL ,NCKD_PROFMGRTOTAL,NCKD_TOTALWAGE );
+
+
+
+    /** 集团工资结算核定-实体标识 */
+    public static final String GRPSALSTLAPPR_ENTITYID = "nckd_grpsalstlappr";
+    /** 单据名称 */
+    public static final String NCKD_NAME = "nckd_name";
+    /** 单据体 */
+    public static final String NCKD_ENTRYENTITY = "nckd_entryentity";
+    /** 缺省id字段 */
+    public static final String ID = "id";
+    /** 分录行号 */
+    public static final String SEQ = "seq";
+    /** 单位 */
+    public static final String NCKD_UNIT = "nckd_unit";
+    /** 上年实际计提工资总额与应提工资总额差额 */
+    public static final String NCKD_LYRACTVSEXPDIFF = "nckd_lyractvsexpdiff";
+    /** 负责人累计平均人数 */
+    public static final String NCKD_RESPAVGNUM = "nckd_respavgnum";
+    /** 负责人薪酬合计 */
+    public static final String NCKD_RESPWGTTL = "nckd_respwgttl";
+    /** 专务、巡察专员累计平均人数 */
+    public static final String NCKD_SPECINSPAVGNUM = "nckd_specinspavgnum";
+    /** 专务、巡察专员薪酬合计 */
+    public static final String NCKD_SPECINSPWGTTL = "nckd_specinspwgttl";
+    /** 任期激励 */
+    public static final String NCKD_TERMBONUS = "nckd_termbonus";
+    /** 组织绩效考核累计平均人数 */
+    public static final String NCKD_ORGPERFAVGNUM = "nckd_orgperfavgnum";
+    /** 组织绩效考核薪酬合计 */
+    public static final String NCKD_ORGPERFWGTTL = "nckd_orgperfwgttl";
+    /** 组织绩效考核人均 */
+    public static final String NCKD_ORGPERFAVG = "nckd_orgperfavg";
+    /** 一次性单项工资 */
+    public static final String NCKD_ONETIMEITEMWG = "nckd_onetimeitemwg";
+    /** 全部员工累计平均人数 */
+    public static final String NCKD_ALLEMPAVGNUM = "nckd_allempavgnum";
+    /** 本年应提工资总额 */
+    public static final String NCKD_CYEXPECTEDTOTAL = "nckd_cyexpectedtotal";
+    /** 全部员工工资总额 */
+    public static final String NCKD_ALLEMPWGTTL = "nckd_allempwgttl";
+    /** 全部员工人均 */
+    public static final String NCKD_ALLEMPAVG = "nckd_allempavg";
+    /** 本年实际计提工资总额(单体审计报告数) */
+    public static final String NCKD_CYACTAUDITTOTAL = "nckd_cyactaudittotal";
+    /** 本年实际计提工资总额与应提工资总额差额 */
+    public static final String NCKD_CYACTVSEXPDIFF = "nckd_cyactvsexpdiff";
+    /** 备注 */
+    public static final String NCKD_REMARK = "nckd_remark";
+    /** 上年补提或冲回以前年度差额 */
+    public static final String NCKD_LYRPRIORADJDIFF = "nckd_lyrprioradjdiff";
+    /** 上年年薪人员差额 */
+    public static final String NCKD_LYRANNSALDIFF = "nckd_lyrannsaldiff";
+    /** 上年任期激励差额 */
+    public static final String NCKD_LYRTERMBONUSDIFF = "nckd_lyrtermbonusdiff";
+    /** 上年组织绩效差额 */
+    public static final String NCKD_LYRORGPERFDIFF = "nckd_lyrorgperfdiff";
+    /** 上年单项工资差额 */
+    public static final String NCKD_LYRITEMWGDIFF = "nckd_lyritemwgdiff";
+    /** 补提或冲回以前年度差额 */
+    public static final String NCKD_CYPRIORADJDIFF = "nckd_cyprioradjdiff";
+    /** 年薪人员计提数 */
+    public static final String NCKD_ANNSALACCRUED = "nckd_annsalaccrued";
+    /** 任期激励计提数 */
+    public static final String NCKD_TERMBONUSACCRUED = "nckd_termbonusaccrued";
+    /** 组织绩效计提数 */
+    public static final String NCKD_ORGPERFACCRUED = "nckd_orgperfaccrued";
+    /** 单项工资计提数 */
+    public static final String NCKD_ITEMWGACCRUED = "nckd_itemwgaccrued";
+    /** 本年补提或冲回以前年度差额 */
+    public static final String NCKD_CYPRIORADJDIFF2 = "nckd_cyprioradjdiff2";
+    /** 本年年薪人员差额 */
+    public static final String NCKD_CYANNSALDIFF = "nckd_cyannsaldiff";
+    /** 本年任期激励差额 */
+    public static final String NCKD_CYTERMBONUSDIFF = "nckd_cytermbonusdiff";
+    /** 本年组织绩效差额 */
+    public static final String NCKD_CYORGPERFDIFF = "nckd_cyorgperfdiff";
+    /** 本年单项工资差额 */
+    public static final String NCKD_CYITEMWGDIFF = "nckd_cyitemwgdiff";
 }

+ 1 - 1
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/mas/plugin/form/assessmentmgm/EntldrMgrPerfAssmtFormPlugin.java

@@ -16,7 +16,7 @@ import nckd.jxccl.base.common.constant.FormConstant;
 import nckd.jxccl.base.common.utils.ConvertUtil;
 import nckd.jxccl.base.common.utils.DateUtil;
 import nckd.jxccl.base.common.utils.QueryFieldBuilder;
-import nckd.jxccl.swc.mas.common.MasConstant;
+import nckd.jxccl.swc.constants.MasConstant;
 
 import java.time.LocalDateTime;
 import java.util.Arrays;

+ 1 - 1
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/mas/plugin/form/assessmentmgm/EntldrMgrTermAssmtFormPlugin.java

@@ -15,7 +15,7 @@ import kd.sdk.plugin.Plugin;
 import nckd.jxccl.base.common.constant.FormConstant;
 import nckd.jxccl.base.common.utils.ConvertUtil;
 import nckd.jxccl.base.common.utils.QueryFieldBuilder;
-import nckd.jxccl.swc.mas.common.MasConstant;
+import nckd.jxccl.swc.constants.MasConstant;
 
 import java.util.Arrays;
 import java.util.Comparator;

+ 1 - 1
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/mas/plugin/form/empmgt/LoadPartyPostPopupFormPlugin.java

@@ -4,7 +4,7 @@ import kd.bos.form.events.AfterDoOperationEventArgs;
 import kd.bos.form.plugin.AbstractFormPlugin;
 import kd.sdk.plugin.Plugin;
 import nckd.jxccl.base.common.constant.FormConstant;
-import nckd.jxccl.swc.mas.common.MasConstant;
+import nckd.jxccl.swc.constants.MasConstant;
 
 /**
 * 载入党政职务履历弹窗

+ 1 - 1
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/mas/plugin/form/empmgt/LoadppDatePopupFormPlugin.java

@@ -4,7 +4,7 @@ import kd.bos.form.events.AfterDoOperationEventArgs;
 import kd.bos.form.plugin.AbstractFormPlugin;
 import kd.sdk.plugin.Plugin;
 import nckd.jxccl.base.common.constant.FormConstant;
-import nckd.jxccl.swc.mas.common.MasConstant;
+import nckd.jxccl.swc.constants.MasConstant;
 
 import java.util.HashMap;
 import java.util.Map;

+ 9 - 8
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/mas/plugin/form/empmgt/SubCoHeadServiceListPlugin.java

@@ -30,7 +30,7 @@ import nckd.jxccl.base.common.utils.ShowOperExecuteResult;
 import nckd.jxccl.base.entity.helper.EntityHelper;
 import nckd.jxccl.base.hrpi.helper.EmpPosOrgRelHelper;
 import nckd.jxccl.base.orm.helper.QFilterCommonHelper;
-import nckd.jxccl.swc.mas.common.MasConstant;
+import nckd.jxccl.swc.constants.MasConstant;
 
 import java.time.LocalDateTime;
 import java.time.temporal.ChronoUnit;
@@ -136,16 +136,18 @@ public class SubCoHeadServiceListPlugin extends AbstractListPlugin implements Pl
         Date startOfYear = DateUtil.toDate(DateUtil.beginOfYear(now));
         Date endOfYear = DateUtil.toDate(DateUtil.endOfYear(now));
 
-        // 只处理权限范围内的人员
-        Long currUserId = RequestContext.get().getCurrUserId();
-        AuthorizedOrgResultWithSub userAdminOrgWithSub = HRPermissionServiceHelper.getUserAdminOrgsWithSub(
-                currUserId, "nckd_pm", MasConstant.SUBCOHEADSERVICE_ENTITYID,
-                PermItemConst.ITEM_VIEW, "nckd_employee.hsbs_empposorgrel.adminorg", new HashMap<>());
         QueryFieldBuilder subCoHeadServiceFieldBuilder = QueryFieldBuilder.create()
                 .addIdNumberName(MasConstant.NCKD_EMPLOYEE);
         //查询当年已生成子企业负责人任职情况的人员
         QFilter subCoHeadServiceFilter = new QFilter(MasConstant.NCKD_YEAR, QCP.large_equals, startOfYear)
                 .and(MasConstant.NCKD_YEAR, QCP.less_equals, endOfYear);
+        // 只处理权限范围内的人员
+        QFilter dataRule = HRPermissionServiceHelper.getDataRule(
+                RequestContext.get().getCurrUserId(), "nckd_mas", MasConstant.SUBCOHEADSERVICE_ENTITYID,
+                PermItemConst.ITEM_VIEW, new HashMap<>());
+        if (dataRule != null) {
+            subCoHeadServiceFilter.and(dataRule);
+        }
         DynamicObjectCollection subCoHeadServiceFilterQuery = QueryServiceHelper.query(MasConstant.SUBCOHEADSERVICE_ENTITYID, subCoHeadServiceFieldBuilder.buildSelect(), new QFilter[]{subCoHeadServiceFilter});
         List<Long> employeeIds = subCoHeadServiceFilterQuery.stream()
                 .map(dynamicObject -> dynamicObject.getLong(String.join(".", MasConstant.NCKD_EMPLOYEE, FormConstant.ID_KEY)))
@@ -159,7 +161,6 @@ public class SubCoHeadServiceListPlugin extends AbstractListPlugin implements Pl
                 .add(MasConstant.NCKD_CHANGETIME)
                 .add(MasConstant.NCKD_POSNAME)
                 .addIdNumberName(MasConstant.NCKD_POSCHTP)
-                .addIdNumberName(MasConstant.NCKD_POSLEVEL)
                 .addIdNumberName(MasConstant.NCKD_POSGRADE)
                 .addIdNumberName(MasConstant.NCKD_APPRWAY)
                 .add(MasConstant.NCKD_OFFICEDEPT)
@@ -168,7 +169,7 @@ public class SubCoHeadServiceListPlugin extends AbstractListPlugin implements Pl
                 .addIdNumberName(MasConstant.NCKD_ORGPOSGRD)
                 .addIdNumberName(MasConstant.EMPLOYEE_KEY)
                 .orderDesc(MasConstant.STARTDATE, MasConstant.ENDDATE);
-        QFilter allPartyPoshFilter = new QFilter(MasConstant.EMPLOYEE_KEY, QCP.not_in, employeeIds);
+        QFilter allPartyPoshFilter = new QFilter(String.join(".",MasConstant.EMPLOYEE_KEY,FormConstant.ID_KEY), QCP.not_in, employeeIds);
         if(!payUnitIdList.isEmpty()){
             allPartyPoshFilter.and(String.join(".",MasConstant.NCKD_PAYUNIT,FormConstant.ID_KEY), QCP.in, payUnitIdList);
         }

+ 8 - 7
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/mas/plugin/form/empmgt/TenurePersonListListPlugin.java

@@ -30,7 +30,7 @@ import nckd.jxccl.base.common.utils.ShowOperExecuteResult;
 import nckd.jxccl.base.entity.helper.EntityHelper;
 import nckd.jxccl.base.hrpi.helper.EmpPosOrgRelHelper;
 import nckd.jxccl.base.orm.helper.QFilterCommonHelper;
-import nckd.jxccl.swc.mas.common.MasConstant;
+import nckd.jxccl.swc.constants.MasConstant;
 
 import java.time.LocalDateTime;
 import java.time.temporal.ChronoUnit;
@@ -99,15 +99,17 @@ public class TenurePersonListListPlugin extends AbstractListPlugin implements Pl
         Date startOfYear = DateUtil.toDate(DateUtil.beginOfYear(now));
         Date endOfYear = DateUtil.toDate(DateUtil.endOfYear(now));
 
-        // 只处理权限范围内的人员
-        Long currUserId = RequestContext.get().getCurrUserId();
-        AuthorizedOrgResultWithSub userAdminOrgWithSub = HRPermissionServiceHelper.getUserAdminOrgsWithSub(
-                currUserId, "nckd_pm", MasConstant.SUBCOHEADSERVICE_ENTITYID,
-                PermItemConst.ITEM_VIEW, "nckd_employee.hsbs_empposorgrel.adminorg", new HashMap<>());
         QueryFieldBuilder subCoHeadServiceFieldBuilder = QueryFieldBuilder.create()
                 .addIdNumberName(MasConstant.NCKD_EMPLOYEE);
         //查询任期区间已生成的人员
         QFilter tenurePersonListFilterFilter = new QFilter(MasConstant.NCKD_TERM, QCP.equals, term.getLong(FormConstant.ID_KEY));
+        // 只处理权限范围内的人员
+        QFilter dataRule = HRPermissionServiceHelper.getDataRule(
+                RequestContext.get().getCurrUserId(), "nckd_mas", MasConstant.TENUREPERSONLIST_ENTITYID,
+                PermItemConst.ITEM_VIEW, new HashMap<>());
+        if (dataRule != null) {
+            tenurePersonListFilterFilter.and(dataRule);
+        }
         DynamicObjectCollection tenurePersonListFilterQuery = QueryServiceHelper.query(MasConstant.TENUREPERSONLIST_ENTITYID, subCoHeadServiceFieldBuilder.buildSelect(), new QFilter[]{tenurePersonListFilterFilter});
         List<Long> employeeIds = tenurePersonListFilterQuery.stream()
                 .map(dynamicObject -> dynamicObject.getLong(String.join(".", MasConstant.NCKD_EMPLOYEE, FormConstant.ID_KEY)))
@@ -121,7 +123,6 @@ public class TenurePersonListListPlugin extends AbstractListPlugin implements Pl
                 .add(MasConstant.NCKD_CHANGETIME)
                 .add(MasConstant.NCKD_POSNAME)
                 .addIdNumberName(MasConstant.NCKD_POSCHTP)
-                .addIdNumberName(MasConstant.NCKD_POSLEVEL)
                 .addIdNumberName(MasConstant.NCKD_POSGRADE)
                 .addIdNumberName(MasConstant.NCKD_APPRWAY)
                 .add(MasConstant.NCKD_OFFICEDEPT)

+ 1 - 2
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/mas/plugin/form/incentivemgmt/AbstractIncentiveApprFormPlugin.java

@@ -9,12 +9,11 @@ import kd.bos.form.plugin.AbstractFormPlugin;
 import kd.bos.orm.query.QCP;
 import kd.bos.orm.query.QFilter;
 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.utils.ConvertUtil;
 import nckd.jxccl.base.common.utils.QueryFieldBuilder;
-import nckd.jxccl.swc.mas.common.MasConstant;
+import nckd.jxccl.swc.constants.MasConstant;
 
 import java.util.Objects;
 import java.util.stream.Stream;

+ 1 - 2
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/mas/plugin/form/incentivemgmt/EntldrTermBonusApprFormPlugin.java

@@ -6,11 +6,10 @@ import kd.bos.entity.datamodel.RowDataEntity;
 import kd.bos.entity.datamodel.events.AfterAddRowEventArgs;
 import kd.bos.entity.datamodel.events.ChangeData;
 import kd.bos.entity.datamodel.events.PropertyChangedArgs;
-import kd.bos.form.plugin.AbstractFormPlugin;
 import kd.sdk.plugin.Plugin;
 import nckd.jxccl.base.common.constant.FormConstant;
 import nckd.jxccl.base.common.utils.ConvertUtil;
-import nckd.jxccl.swc.mas.common.MasConstant;
+import nckd.jxccl.swc.constants.MasConstant;
 
 import java.util.EventObject;
 import java.util.Objects;

+ 1 - 4
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/mas/plugin/form/structappr/AbstractStructApprFormPlugin.java

@@ -13,15 +13,12 @@ import kd.bos.entity.operate.result.OperationResult;
 import kd.bos.entity.validate.BillStatus;
 import kd.bos.form.ConfirmCallBackListener;
 import kd.bos.form.ConfirmTypes;
-import kd.bos.form.IFormView;
-import kd.bos.form.IPageCache;
 import kd.bos.form.MessageBoxOptions;
 import kd.bos.form.MessageBoxResult;
 import kd.bos.form.ShowType;
 import kd.bos.form.events.AfterDoOperationEventArgs;
 import kd.bos.form.events.MessageBoxClosedEvent;
 import kd.bos.form.plugin.AbstractFormPlugin;
-import kd.bos.mvc.SessionManager;
 import kd.bos.orm.query.QCP;
 import kd.bos.orm.query.QFilter;
 import kd.bos.servicehelper.BusinessDataServiceHelper;
@@ -39,7 +36,7 @@ import nckd.jxccl.base.common.utils.ShowOperExecuteResult;
 import nckd.jxccl.base.common.utils.StrFormatter;
 import nckd.jxccl.base.entity.helper.EntityHelper;
 import nckd.jxccl.base.orm.helper.QFilterCommonHelper;
-import nckd.jxccl.swc.mas.common.MasConstant;
+import nckd.jxccl.swc.constants.MasConstant;
 
 import java.math.BigDecimal;
 import java.math.RoundingMode;

Някои файлове не бяха показани, защото твърде много файлове са промени