1
0

25 Коммитууд d08be3ddd0 ... 335c95509c

Эзэн SHA1 Мессеж Огноо
  wyc 335c95509c Merge branch 'refs/heads/feat-hr-psms_1.0' 1 долоо хоног өмнө
  放平心態\GIN 2a53a76c43 feat(hrmp): 初始化hrmp云模块并集成组织管理功能 1 долоо хоног өмнө
  wyc 6c53e66704 Merge remote-tracking branch 'origin/master' 1 долоо хоног өмнө
  wyc de34e0fd5f feat(build): 更新模块依赖配置 1 долоо хоног өмнө
  turborao 549dfe295e ``` 1 долоо хоног өмнө
  turborao fd193deeac feat(swc): 新增延迟退休日期计算及预警任务插件 1 долоо хоног өмнө
  Tyx 59413b8f35 Merge remote-tracking branch 'origin/master' 1 долоо хоног өмнө
  Tyx 1018cd90e6 1.考勤模块代码模块目录调整 1 долоо хоног өмнө
  wyc a4377738a0 chore(gradle): 移除epm云模块引用 1 долоо хоног өмнө
  wyc 7f6075ad17 feat(gradle): 添加odc和wtc云模块配置 1 долоо хоног өмнө
  wyc 99ebe6d588 Merge remote-tracking branch 'origin/master' 1 долоо хоног өмнө
  wyc 507df28295 feat(wtc): 初始化wtc云init应用基础模块 1 долоо хоног өмнө
  Tyx 0cb7468795 Merge remote-tracking branch 'origin/master' 1 долоо хоног өмнө
  Tyx e93c7dfa7b 1.社保差异明细表取数插件 1 долоо хоног өмнө
  wyc 14588912e8 chore(epm): 移除无用的模板文件和依赖配置 1 долоо хоног өмнө
  Tyx 0a40b00530 Merge remote-tracking branch 'origin/master' 1 долоо хоног өмнө
  Tyx 7616e00a4c 1.社保外部系统数据导入相关插件 1 долоо хоног өмнө
  turborao d69cdf6077 更新 'build.gradle' 1 долоо хоног өмнө
  turborao e082792d36 更新 'gradle.properties' 1 долоо хоног өмнө
  turborao f2c3730117 更新 'config.gradle' 1 долоо хоног өмнө
  turborao 844b0ad5d1 更新 'gradle.properties' 1 долоо хоног өмнө
  turborao ba10e98a1c 更新 'build.gradle' 1 долоо хоног өмнө
  turborao 0c78fb68dd 更新 'build.gradle' 1 долоо хоног өмнө
  turborao 0a160f3df4 更新 'config.gradle' 1 долоо хоног өмнө
  Tyx c7cc305c60 社保/考勤模块 2 долоо хоног өмнө
100 өөрчлөгдсөн 5263 нэмэгдсэн , 38 устгасан
  1. 37 0
      build.gradle
  2. 4 0
      code/base/nckd-jxccl-base-common/src/main/java/nckd/jxccl/base/common/constant/FormConstant.java
  3. 1 1
      code/hrmp/nckd-jxccl-hrmp/build.gradle
  4. 0 0
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/haos/business/.gitkeep
  5. 22 0
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/haos/common/AppflgConstant.java
  6. 32 0
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/haos/common/adminorg/AdminOrgConstant.java
  7. 0 0
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/haos/mservice/.gitkeep
  8. 0 0
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/haos/plugin/form/.gitkeep
  9. 0 0
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/haos/plugin/operate/.gitkeep
  10. 101 0
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/haos/plugin/operate/adminorg/AdminOrgDetailConfirmChangeOpPlugin.java
  11. 51 0
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/haos/plugin/operate/adminorg/AdminOrgDetailSaveOpPlugin.java
  12. 0 0
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/haos/plugin/other/.gitkeep
  13. 0 0
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/haos/plugin/report/.gitkeep
  14. 0 0
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/haos/plugin/workflow/.gitkeep
  15. 0 0
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/haos/webapi/.gitkeep
  16. 0 0
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/business/.gitkeep
  17. 22 0
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/common/AppflgConstant.java
  18. 22 0
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/common/position/PositionConstant.java
  19. 0 0
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/mservice/.gitkeep
  20. 0 0
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/form/.gitkeep
  21. 0 0
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/list/.gitkeep
  22. 29 0
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/list/position/PositionListPlugin.java
  23. 0 0
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/operate/.gitkeep
  24. 0 0
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/other/.gitkeep
  25. 0 0
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/report/.gitkeep
  26. 0 0
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/workflow/.gitkeep
  27. 0 0
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/webapi/.gitkeep
  28. 0 0
      code/hrmp/nckd-jxccl-hrmp/src/main/java/resources/.gitkeep
  29. 0 0
      code/hrmp/nckd-jxccl-hrmp/src/main/resources/.gitkeep
  30. 0 0
      code/hrmp/nckd-jxccl-hrmp/src/test/java/nckd/hrmp/app/business/test/.gitkeep
  31. 0 0
      code/hrmp/nckd-jxccl-hrmp/src/test/java/nckd/hrmp/app/common/test/.gitkeep
  32. 0 0
      code/hrmp/nckd-jxccl-hrmp/src/test/java/nckd/hrmp/app/mservice/test/.gitkeep
  33. 0 0
      code/hrmp/nckd-jxccl-hrmp/src/test/java/nckd/hrmp/app/plugin/test/.gitkeep
  34. 0 0
      code/hrmp/nckd-jxccl-hrmp/src/test/java/nckd/hrmp/app/report/test/.gitkeep
  35. 0 0
      code/hrmp/nckd-jxccl-hrmp/src/test/java/nckd/hrmp/app/webapi/test/.gitkeep
  36. 0 0
      code/hrmp/nckd-jxccl-hrmp/src/test/resources/.gitkeep
  37. 45 32
      code/nckd-cosmic-debug/build.gradle
  38. 14 0
      code/odc/nckd-jxccl-odc/build.gradle
  39. 0 0
      code/odc/nckd-jxccl-odc/src/main/java/nckd/jxccl/odc/homs/business/.gitkeep
  40. 5 5
      code/odc/nckd-jxccl-odc/src/main/java/nckd/jxccl/odc/homs/common/AppflgConstant.java
  41. 58 0
      code/odc/nckd-jxccl-odc/src/main/java/nckd/jxccl/odc/homs/common/orgbatch/OrgBatchConstant.java
  42. 0 0
      code/odc/nckd-jxccl-odc/src/main/java/nckd/jxccl/odc/homs/mservice/.gitkeep
  43. 0 0
      code/odc/nckd-jxccl-odc/src/main/java/nckd/jxccl/odc/homs/plugin/form/.gitkeep
  44. 52 0
      code/odc/nckd-jxccl-odc/src/main/java/nckd/jxccl/odc/homs/plugin/form/orgbatch/AdminOrgCopyDialogFormPlugin.java
  45. 0 0
      code/odc/nckd-jxccl-odc/src/main/java/nckd/jxccl/odc/homs/plugin/list/.gitkeep
  46. 95 0
      code/odc/nckd-jxccl-odc/src/main/java/nckd/jxccl/odc/homs/plugin/list/orgbatch/OrgBatchChgBillListPlugin.java
  47. 0 0
      code/odc/nckd-jxccl-odc/src/main/java/nckd/jxccl/odc/homs/plugin/operate/.gitkeep
  48. 0 0
      code/odc/nckd-jxccl-odc/src/main/java/nckd/jxccl/odc/homs/plugin/other/.gitkeep
  49. 0 0
      code/odc/nckd-jxccl-odc/src/main/java/nckd/jxccl/odc/homs/plugin/report/.gitkeep
  50. 0 0
      code/odc/nckd-jxccl-odc/src/main/java/nckd/jxccl/odc/homs/plugin/workflow/.gitkeep
  51. 0 0
      code/odc/nckd-jxccl-odc/src/main/java/nckd/jxccl/odc/homs/webapi/.gitkeep
  52. 0 0
      code/odc/nckd-jxccl-odc/src/main/java/resources/.gitkeep
  53. 0 0
      code/odc/nckd-jxccl-odc/src/main/resources/.gitkeep
  54. 0 0
      code/odc/nckd-jxccl-odc/src/test/java/nckd/odc/homs/business/test/.gitkeep
  55. 0 0
      code/odc/nckd-jxccl-odc/src/test/java/nckd/odc/homs/common/test/.gitkeep
  56. 0 0
      code/odc/nckd-jxccl-odc/src/test/java/nckd/odc/homs/mservice/test/.gitkeep
  57. 0 0
      code/odc/nckd-jxccl-odc/src/test/java/nckd/odc/homs/plugin/test/.gitkeep
  58. 0 0
      code/odc/nckd-jxccl-odc/src/test/java/nckd/odc/homs/report/test/.gitkeep
  59. 0 0
      code/odc/nckd-jxccl-odc/src/test/java/nckd/odc/homs/webapi/test/.gitkeep
  60. 0 0
      code/odc/nckd-jxccl-odc/src/test/resources/.gitkeep
  61. 202 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/business/importtaskguide/ImportTaskGuideExportService.java
  62. 431 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/business/importtaskguide/ImportTaskGuideImportService.java
  63. 236 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/business/importtaskguide/utils/ImportTaskUtils.java
  64. 7 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/common/constant/SitConstant.java
  65. 45 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/formplugin/web/file/attach/FileSIBasePluginEx.java
  66. 138 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/formplugin/web/tp/SinsurTempDataListPlugin.java
  67. 422 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/formplugin/web/tp/SinsurTemplateEdit.java
  68. 487 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/formplugin/web/tp/SitItemSelectAddItemPlugin.java
  69. 122 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/formplugin/web/tp/SitItemSelectItemEntryPlugin.java
  70. 240 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/formplugin/web/tp/SitItemSelectTreePlugin.java
  71. 77 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/formplugin/web/tp/basedata/SinsurImpTaskListPlugin.java
  72. 128 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/formplugin/web/tp/basedata/TaskGuideImportFormPlugin.java
  73. 73 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/formplugin/web/tp/enums/SinsurPresetItemEnum.java
  74. 158 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/formplugin/web/tp/guide/TaskImpGuideListPlugin.java
  75. 158 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/formplugin/web/tp/helper/SinsurTemplateHelper.java
  76. 186 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/formplugin/web/tp/helper/SitItemSelectAddItemServiceHelper.java
  77. 110 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/rptdata/DetailCompareReportDataPlugin.java
  78. 58 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/utils/ReportUtils.java
  79. 498 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/init/plugin/other/DelayedRetirementDateCalcTask.java
  80. 14 0
      code/wtc/nckd-jxccl-wtc/build.gradle
  81. 0 0
      code/wtc/nckd-jxccl-wtc/src/main/java/nckd/jxccl/wtc/init/business/.gitkeep
  82. 22 0
      code/wtc/nckd-jxccl-wtc/src/main/java/nckd/jxccl/wtc/init/common/AppflgConstant.java
  83. 0 0
      code/wtc/nckd-jxccl-wtc/src/main/java/nckd/jxccl/wtc/init/mservice/.gitkeep
  84. 0 0
      code/wtc/nckd-jxccl-wtc/src/main/java/nckd/jxccl/wtc/init/plugin/form/.gitkeep
  85. 0 0
      code/wtc/nckd-jxccl-wtc/src/main/java/nckd/jxccl/wtc/init/plugin/operate/.gitkeep
  86. 0 0
      code/wtc/nckd-jxccl-wtc/src/main/java/nckd/jxccl/wtc/init/plugin/other/.gitkeep
  87. 0 0
      code/wtc/nckd-jxccl-wtc/src/main/java/nckd/jxccl/wtc/init/plugin/report/.gitkeep
  88. 0 0
      code/wtc/nckd-jxccl-wtc/src/main/java/nckd/jxccl/wtc/init/plugin/workflow/.gitkeep
  89. 0 0
      code/wtc/nckd-jxccl-wtc/src/main/java/nckd/jxccl/wtc/init/webapi/.gitkeep
  90. 90 0
      code/wtc/nckd-jxccl-wtc/src/main/java/nckd/jxccl/wtc/wtabm/vaapply/VaApplyBillEditEx.java
  91. 59 0
      code/wtc/nckd-jxccl-wtc/src/main/java/nckd/jxccl/wtc/wtabm/vaapply/VaInfoEditEx.java
  92. 47 0
      code/wtc/nckd-jxccl-wtc/src/main/java/nckd/jxccl/wtc/wtabm/web/common/constant/WtcConstant.java
  93. 108 0
      code/wtc/nckd-jxccl-wtc/src/main/java/nckd/jxccl/wtc/wtabm/web/common/util/WtcUtils.java
  94. 147 0
      code/wtc/nckd-jxccl-wtc/src/main/java/nckd/jxccl/wtc/wtabm/web/service/VaApplyValidateService.java
  95. 55 0
      code/wtc/nckd-jxccl-wtc/src/main/java/nckd/jxccl/wtc/wtabm/web/vaapply/VaApplyAuditOpPluginEx.java
  96. 30 0
      code/wtc/nckd-jxccl-wtc/src/main/java/nckd/jxccl/wtc/wtabm/web/vaapply/VaApplySubmitOpPluginEx.java
  97. 38 0
      code/wtc/nckd-jxccl-wtc/src/main/java/nckd/jxccl/wtc/wtabm/web/validate/VaApplySubmitValidator.java
  98. 79 0
      code/wtc/nckd-jxccl-wtc/src/main/java/nckd/jxccl/wtc/wtte/report/AbsentDetailReportDataPlugin.java
  99. 103 0
      code/wtc/nckd-jxccl-wtc/src/main/java/nckd/jxccl/wtc/wtte/report/AttendanceRateReportDataPlugin.java
  100. 105 0
      code/wtc/nckd-jxccl-wtc/src/main/java/nckd/jxccl/wtc/wtte/report/AttendanceRateReportFormPlugin.java

+ 37 - 0
build.gradle

@@ -24,6 +24,7 @@ def bos = ext.path.bos
 def trd = ext.path.trd
 def cus = ext.path.cus
 def biz = ext.path.biz
+def zip = ext.path.zip
 def outputdir = ext.path.outputdir
 
 //所有工程共用的配置
@@ -140,6 +141,42 @@ subprojects {
 		into cus
 		exclude '*sources.jar','*javadoc.jar','*cosmic-debug*.jar'
 	 }
+    
+    task hrzip(type: Zip) {
+      group 'build'
+      description '生成hr zip包'
+      from outputdir
+      include 'nckd-jxccl-hr*.jar'
+      destinationDirectory = file(zip)
+      archiveFileName = "nckd-hr.zip"
+    }
+  
+    task basezip(type: Zip) {
+      group 'build'
+      description '生成base zip包'
+      from outputdir
+      include 'nckd-jxccl-base*.jar'
+      destinationDirectory = file(zip)
+      archiveFileName = "nckd-base.zip"
+    }
+    
+    task swczip(type: Zip) {
+      group 'build'
+      description '生成swc zip包'
+      from outputdir
+      include 'nckd-jxccl-swc*.jar'
+      destinationDirectory = file(zip)
+      archiveFileName = "nckd-swc.zip"
+    }
+  
+    task rptzip(type: Zip) {
+      group 'build'
+      description '生成swc zip包'
+      from outputdir
+      include 'nckd-jxccl-rpt*.jar'
+      destinationDirectory = file(zip)
+      archiveFileName = "nckd-rpt.zip"
+    }
 	 
 	test.ignoreFailures true
 	

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

@@ -99,6 +99,8 @@ public class FormConstant {
     public static final String NCKD_ENTRYENTITY = "NCKD_ENTRYENTITY";
 
     //====================================== 通用字段 ======================================
+    /** BOID标识 */
+    public static final String BOID_KEY = "boid";
     /** ID标识 */
     public static final String ID_KEY = "id";
     /** 名称标识 */
@@ -193,6 +195,8 @@ public class FormConstant {
     public static final String DEP_EMP = "depemp";
     /**组织上下级结构长编码*/
     public static final String STRUCTLONGNUMBER = "structlongnumber";
+    /**组织上下级关系编码*/
+    public static final String STRUCTNUMBER = "structnumber";
     /** 人员*/
     public static final String EMPLOYEE_KEY = "employee";
     /**职级序列*/

+ 1 - 1
code/epm/nckd-jxccl-epm/build.gradle → code/hrmp/nckd-jxccl-hrmp/build.gradle

@@ -3,7 +3,7 @@
  * If there are any issues during the use process, you can provide feedback to the kingdee developer community website.
  * Website: https://developer.kingdee.com/developer?productLineId=29
  * Author: liebin.zheng
- * Generate Date: 2025-05-26 16:31:20
+ * Generate Date: 2025-10-20 16:06:47
  */
 
 dependencies {

+ 0 - 0
code/epm/nckd-jxccl-epm/src/main/java/nckd/jxccl/epm/init/business/.gitkeep → code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/haos/business/.gitkeep


+ 22 - 0
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/haos/common/AppflgConstant.java

@@ -0,0 +1,22 @@
+/**
+ * This is a kingdee cosmic template project that is automatically generated by the Kingdee cosmic development assistant plugin. 
+ * If there are any issues during the use process, you can provide feedback to the kingdee developer community website.
+ * Website: https://developer.kingdee.com/developer?productLineId=29
+ * Author: liebin.zheng
+ * Generate Date: 2025-10-20 16:06:47
+ */
+package nckd.jxccl.hrmp.haos.common;
+
+/**
+ * hrmp云app应用-通用常量类<br>
+ * 代码中不能存在硬编码敏感信息,如账号、密码、http外链、ftp外链、邮箱等。<br>
+ * 标识或缓存的常量,需以"KEY_"、"FID_"、"ENTRY_"或"SUBENTRY_"作为变量的前缀。<br>
+ *
+ * @author nckd
+ * @date 2025-10-20 16:06:47
+ */
+public class AppflgConstant {
+	
+	public static final String KEY_APP_NAME = "hrmp-app";
+
+}

+ 32 - 0
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/haos/common/adminorg/AdminOrgConstant.java

@@ -0,0 +1,32 @@
+package nckd.jxccl.hrmp.haos.common.adminorg;
+
+import nckd.jxccl.base.common.constant.FormConstant;
+
+/**
+ * 行政组织常量
+ * @author: jtd
+ * @date: 2025-10-13 14:15
+ */
+public class AdminOrgConstant extends FormConstant {
+
+    /**
+     * 组织结构字段
+     */
+    public static final String[] ADMINORG_STRUCT_FIELDS = {"nckd_firstdep","nckd_seconddep","nckd_thirddep","nckd_fourthdep","nckd_fifthdep","nckd_sixthdep"};
+
+    /**
+     * 物理层级
+     */
+    public static final String LEVEL = "level";
+
+    /**
+     * 变动类型
+     */
+    public static final String CHANGETYPE = "changetype";
+
+    /**
+     * 生效日期
+     */
+    public static final String BSED = "bsed";
+
+}

+ 0 - 0
code/epm/nckd-jxccl-epm/src/main/java/nckd/jxccl/epm/init/mservice/.gitkeep → code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/haos/mservice/.gitkeep


+ 0 - 0
code/epm/nckd-jxccl-epm/src/main/java/nckd/jxccl/epm/init/plugin/form/.gitkeep → code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/haos/plugin/form/.gitkeep


+ 0 - 0
code/epm/nckd-jxccl-epm/src/main/java/nckd/jxccl/epm/init/plugin/operate/.gitkeep → code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/haos/plugin/operate/.gitkeep


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

@@ -0,0 +1,101 @@
+package nckd.jxccl.hrmp.haos.plugin.operate.adminorg;
+
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.entity.plugin.AbstractOperationServicePlugIn;
+import kd.bos.entity.plugin.args.BeginOperationTransactionArgs;
+import kd.bos.entity.plugin.args.EndOperationTransactionArgs;
+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.hr.hbp.common.util.HRDateTimeUtils;
+import nckd.jxccl.base.orm.helper.QFilterCommonHelper;
+import nckd.jxccl.hrmp.haos.common.adminorg.AdminOrgConstant;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+/**
+ * 组织快速维护确认变更操作插件
+ * @author: jtd
+ * @date: 2025-10-16 9:47
+ */
+public class AdminOrgDetailConfirmChangeOpPlugin extends AbstractOperationServicePlugIn  {
+
+    private DynamicObjectCollection adminOrgOldDyColl;
+
+    private Boolean canDo(DynamicObject[] dataEntities) {
+        if (dataEntities == null || dataEntities.length <= 0) {
+            return false;
+        }
+
+        DynamicObject data = dataEntities[0];
+        // 非上级调整或未来生效
+        if (!"1020_S".equals(data.getDynamicObject(AdminOrgConstant.CHANGETYPE).getString(AdminOrgConstant.NUMBER_KEY)) || HRDateTimeUtils.dayAfter(data.getDate(AdminOrgConstant.BSED), HRDateTimeUtils.getNowDate())) {
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public void beginOperationTransaction(BeginOperationTransactionArgs e) {
+        super.beginOperationTransaction(e);
+
+        DynamicObject[] dataEntities = e.getDataEntities();
+        if (!canDo(dataEntities)) {
+            return;
+        }
+
+        // 获取组织及下级组织(旧数据)
+        QFilter qFilter = QFilter.of("1!=1", new Object[0]);
+        Arrays.stream(dataEntities).map(dataEntity -> dataEntity.getString(AdminOrgConstant.STRUCTLONGNUMBER)+"%").forEach(structlongnumber -> {
+            qFilter.or(QFilter.like(AdminOrgConstant.STRUCTLONGNUMBER, structlongnumber));
+        });
+        adminOrgOldDyColl = QueryServiceHelper.query(AdminOrgConstant.ADMINORGHR_ENTITYID, AdminOrgConstant.BOID_KEY, new QFilter[]{QFilter.isNotNull(AdminOrgConstant.STRUCTLONGNUMBER).and(qFilter).and(QFilterCommonHelper.getCurrentVersionFilter())});
+    }
+
+    @Override
+    public void endOperationTransaction(EndOperationTransactionArgs e) {
+        super.endOperationTransaction(e);
+
+        DynamicObject[] dataEntities = e.getDataEntities();
+        if (!canDo(dataEntities)) {
+            return;
+        }
+
+        // 获取组织及下级组织(新数据)含历史版本
+        List<Long> adminOrgBoIds = adminOrgOldDyColl.stream().map(adminOrg -> adminOrg.getLong(AdminOrgConstant.BOID_KEY)).collect(Collectors.toList());
+        DynamicObject[] adminOrgDys = BusinessDataServiceHelper.load(AdminOrgConstant.ADMINORGHR_ENTITYID, String.join(",", AdminOrgConstant.BOID_KEY, AdminOrgConstant.STRUCTLONGNUMBER, AdminOrgConstant.LEVEL, String.join(",", AdminOrgConstant.ADMINORG_STRUCT_FIELDS)), new QFilter[]{QFilter.isNotNull(AdminOrgConstant.STRUCTLONGNUMBER).and(new QFilter(AdminOrgConstant.STRUCTLONGNUMBER, QCP.not_equals, "")).and(new QFilter(AdminOrgConstant.BOID_KEY, QCP.in, adminOrgBoIds))}, AdminOrgConstant.BOID_KEY);
+        // 遍历获取结构编码
+        Map<String, String> structMap = Arrays.stream(adminOrgDys)
+                .map(adminOrgDy -> adminOrgDy.getString(AdminOrgConstant.STRUCTLONGNUMBER))
+                .flatMap(structNumber -> Arrays.stream(structNumber.split("!")))
+                .collect(Collectors.toMap(
+                        Function.identity(), // key就是遍历值 这里简写了 等价于 structNumber -> structNumber
+                        structNumber -> "", // value为空
+                        (existing, replacement) -> existing // 重复key处理 保留旧值或新值都可以 这里随便挑一个
+                ));
+
+        // 根据结构编码获取组织
+        DynamicObjectCollection adminOrgDyColl = QueryServiceHelper.query(AdminOrgConstant.ADMINORGHR_ENTITYID, String.join(",", AdminOrgConstant.BOID_KEY, AdminOrgConstant.STRUCTNUMBER), new QFilter[]{new QFilter(AdminOrgConstant.STRUCTNUMBER, QCP.in, new ArrayList<String>(structMap.keySet())).and(QFilterCommonHelper.getCurrentVersionFilter())}, AdminOrgConstant.LEVEL);
+        adminOrgDyColl.forEach(adminOrgDy -> structMap.put(adminOrgDy.getString(AdminOrgConstant.STRUCTNUMBER), adminOrgDy.getString(AdminOrgConstant.BOID_KEY)));
+
+        // 更新一二三四五六级组织
+        for (DynamicObject adminOrgDy : adminOrgDys) {
+            String[] structLongNumbers = adminOrgDy.getString(AdminOrgConstant.STRUCTLONGNUMBER).split("!");
+            for (int i = 0; i < AdminOrgConstant.ADMINORG_STRUCT_FIELDS.length; i++) {
+                adminOrgDy.set(AdminOrgConstant.ADMINORG_STRUCT_FIELDS[i], i < structLongNumbers.length ? structMap.get(structLongNumbers[i]) : null);
+            }
+        }
+
+        // 保存数据
+        SaveServiceHelper.save(adminOrgDys);
+    }
+}

+ 51 - 0
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/haos/plugin/operate/adminorg/AdminOrgDetailSaveOpPlugin.java

@@ -0,0 +1,51 @@
+package nckd.jxccl.hrmp.haos.plugin.operate.adminorg;
+
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.entity.plugin.AbstractOperationServicePlugIn;
+import kd.bos.entity.plugin.args.BeginOperationTransactionArgs;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
+import kd.bos.servicehelper.QueryServiceHelper;
+import nckd.jxccl.base.orm.helper.QFilterCommonHelper;
+import nckd.jxccl.hrmp.haos.common.adminorg.AdminOrgConstant;
+
+import java.util.Arrays;
+import java.util.stream.IntStream;
+
+/**
+ * 组织快速维护保存操作插件
+ * @author: jtd
+ * @date: 2025-10-13 11:08
+ */
+public class AdminOrgDetailSaveOpPlugin extends AbstractOperationServicePlugIn {
+
+    @Override
+    public void beginOperationTransaction(BeginOperationTransactionArgs e) {
+        super.beginOperationTransaction(e);
+
+        DynamicObject[] dataEntities = e.getDataEntities();
+        if (dataEntities != null) {
+            for (DynamicObject dataEntity : dataEntities) {
+                setAdminOrgStructHierarchy(dataEntity);
+            }
+        }
+    }
+
+    private void setAdminOrgStructHierarchy(DynamicObject dataEntity) {
+        String[] structNumbers = dataEntity.getString(AdminOrgConstant.STRUCTLONGNUMBER).split("!");
+        // 过滤组织上下级关系编码和是否当前生效数据
+        QFilter[] qFilters = {new QFilter(AdminOrgConstant.STRUCTNUMBER, QCP.in, Arrays.asList(structNumbers)), QFilterCommonHelper.getCurrentVersionFilter()};
+        DynamicObjectCollection adminOrgColl = QueryServiceHelper.query(AdminOrgConstant.ADMINORGHR_ENTITYID, AdminOrgConstant.ID_KEY, qFilters, AdminOrgConstant.LEVEL);
+        for (int i = 0; i < AdminOrgConstant.ADMINORG_STRUCT_FIELDS.length; i++) {
+            if (i < adminOrgColl.size() && adminOrgColl.get(i) != null) {
+            dataEntity.set(AdminOrgConstant.ADMINORG_STRUCT_FIELDS[i], adminOrgColl.get(i).getLong(AdminOrgConstant.ID_KEY));
+            } else if (i == adminOrgColl.size()) {
+                dataEntity.set(AdminOrgConstant.ADMINORG_STRUCT_FIELDS[i], dataEntity.getLong(AdminOrgConstant.ID_KEY));
+            } else {
+                dataEntity.set(AdminOrgConstant.ADMINORG_STRUCT_FIELDS[i], null);
+            }
+        }
+    }
+
+}

+ 0 - 0
code/epm/nckd-jxccl-epm/src/main/java/nckd/jxccl/epm/init/plugin/other/.gitkeep → code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/haos/plugin/other/.gitkeep


+ 0 - 0
code/epm/nckd-jxccl-epm/src/main/java/nckd/jxccl/epm/init/plugin/report/.gitkeep → code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/haos/plugin/report/.gitkeep


+ 0 - 0
code/epm/nckd-jxccl-epm/src/main/java/nckd/jxccl/epm/init/plugin/workflow/.gitkeep → code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/haos/plugin/workflow/.gitkeep


+ 0 - 0
code/epm/nckd-jxccl-epm/src/main/java/nckd/jxccl/epm/init/webapi/.gitkeep → code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/haos/webapi/.gitkeep


+ 0 - 0
code/epm/nckd-jxccl-epm/src/main/java/resources/.gitkeep → code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/business/.gitkeep


+ 22 - 0
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/common/AppflgConstant.java

@@ -0,0 +1,22 @@
+/**
+ * This is a kingdee cosmic template project that is automatically generated by the Kingdee cosmic development assistant plugin. 
+ * If there are any issues during the use process, you can provide feedback to the kingdee developer community website.
+ * Website: https://developer.kingdee.com/developer?productLineId=29
+ * Author: liebin.zheng
+ * Generate Date: 2025-10-20 16:06:47
+ */
+package nckd.jxccl.hrmp.hbpm.common;
+
+/**
+ * hrmp云app应用-通用常量类<br>
+ * 代码中不能存在硬编码敏感信息,如账号、密码、http外链、ftp外链、邮箱等。<br>
+ * 标识或缓存的常量,需以"KEY_"、"FID_"、"ENTRY_"或"SUBENTRY_"作为变量的前缀。<br>
+ *
+ * @author nckd
+ * @date 2025-10-20 16:06:47
+ */
+public class AppflgConstant {
+	
+	public static final String KEY_APP_NAME = "hrmp-app";
+
+}

+ 22 - 0
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/common/position/PositionConstant.java

@@ -0,0 +1,22 @@
+package nckd.jxccl.hrmp.hbpm.common.position;
+
+import nckd.jxccl.base.common.constant.FormConstant;
+
+/**
+ * 岗位常量
+ * @author: jtd
+ * @date: 2025-10-20 16:29
+ */
+public class PositionConstant extends FormConstant {
+
+    /**
+     * 是否来自工作流
+     */
+    public static final String NCKD_ISFROMWF = "nckd_isfromwf";
+
+    /**
+     * 是否生效
+     */
+    public static final String NCKD_ISEFFECT = "nckd_iseffect";
+
+}

+ 0 - 0
code/epm/nckd-jxccl-epm/src/main/resources/.gitkeep → code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/mservice/.gitkeep


+ 0 - 0
code/epm/nckd-jxccl-epm/src/test/java/nckd/epm/init/business/test/.gitkeep → code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/form/.gitkeep


+ 0 - 0
code/epm/nckd-jxccl-epm/src/test/java/nckd/epm/init/common/test/.gitkeep → code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/list/.gitkeep


+ 29 - 0
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/list/position/PositionListPlugin.java

@@ -0,0 +1,29 @@
+package nckd.jxccl.hrmp.hbpm.plugin.list.position;
+
+import kd.bos.form.events.SetFilterEvent;
+import kd.bos.list.plugin.AbstractListPlugin;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
+import kd.occ.ocpos.common.enums.BillStatusEnum;
+import nckd.jxccl.hrmp.hbpm.common.position.PositionConstant;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * 岗位信息维护列表插件
+ * @author: jtd
+ * @date: 2025-10-20 17:07
+ */
+public class PositionListPlugin extends AbstractListPlugin {
+
+    @Override
+    public void setFilter(SetFilterEvent e) {
+        super.setFilter(e);
+
+        // 来源工作流且生效的数据或非来源工作流的数据
+        QFilter qFilter = new QFilter(PositionConstant.NCKD_ISFROMWF, QCP.equals, Boolean.TRUE).and(new QFilter(PositionConstant.NCKD_ISEFFECT, QCP.equals, Boolean.TRUE)).or(new QFilter(PositionConstant.NCKD_ISFROMWF, QCP.not_equals, Boolean.TRUE)).or(QFilter.isNull(PositionConstant.NCKD_ISFROMWF));
+        e.addCustomQFilter(qFilter);
+    }
+}

+ 0 - 0
code/epm/nckd-jxccl-epm/src/test/java/nckd/epm/init/mservice/test/.gitkeep → code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/operate/.gitkeep


+ 0 - 0
code/epm/nckd-jxccl-epm/src/test/java/nckd/epm/init/plugin/test/.gitkeep → code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/other/.gitkeep


+ 0 - 0
code/epm/nckd-jxccl-epm/src/test/java/nckd/epm/init/report/test/.gitkeep → code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/report/.gitkeep


+ 0 - 0
code/epm/nckd-jxccl-epm/src/test/java/nckd/epm/init/webapi/test/.gitkeep → code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/workflow/.gitkeep


+ 0 - 0
code/epm/nckd-jxccl-epm/src/test/resources/.gitkeep → code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/webapi/.gitkeep


+ 0 - 0
code/hrmp/nckd-jxccl-hrmp/src/main/java/resources/.gitkeep


+ 0 - 0
code/hrmp/nckd-jxccl-hrmp/src/main/resources/.gitkeep


+ 0 - 0
code/hrmp/nckd-jxccl-hrmp/src/test/java/nckd/hrmp/app/business/test/.gitkeep


+ 0 - 0
code/hrmp/nckd-jxccl-hrmp/src/test/java/nckd/hrmp/app/common/test/.gitkeep


+ 0 - 0
code/hrmp/nckd-jxccl-hrmp/src/test/java/nckd/hrmp/app/mservice/test/.gitkeep


+ 0 - 0
code/hrmp/nckd-jxccl-hrmp/src/test/java/nckd/hrmp/app/plugin/test/.gitkeep


+ 0 - 0
code/hrmp/nckd-jxccl-hrmp/src/test/java/nckd/hrmp/app/report/test/.gitkeep


+ 0 - 0
code/hrmp/nckd-jxccl-hrmp/src/test/java/nckd/hrmp/app/webapi/test/.gitkeep


+ 0 - 0
code/hrmp/nckd-jxccl-hrmp/src/test/resources/.gitkeep


+ 45 - 32
code/nckd-cosmic-debug/build.gradle

@@ -1,33 +1,46 @@
-/*
- * This is a kingdee cosmic template project that is automatically generated by the Kingdee cosmic development assistant plugin. 
- * If there are any issues during the use process, you can provide feedback to the kingdee developer community website.
- * Website: https://developer.kingdee.com/developer?productLineId=29
- * Author: liebin.zheng
- * Generate Date: 2025-05-26 16:28:10
- */
-
-dependencies {
-
-	// 公共基础包
-	implementation project(':nckd-jxccl-base-common')
-	implementation project(':nckd-jxccl-base-helper')
-
-	// 引入hr云模块
-	implementation project(':nckd-jxccl-hr')
-	
-
-	// 引入epm云模块
-	implementation project(':nckd-jxccl-epm')
-
-
-	// 引入swc云模块
-	implementation project(':nckd-jxccl-swc')
-
-
-	// 引入rpt云模块
-	implementation project(':nckd-jxccl-rpt')
-

-	// 引入opmc云模块
-	implementation project(':nckd-jxccl-opmc')
-
+/*
+ * This is a kingdee cosmic template project that is automatically generated by the Kingdee cosmic development assistant plugin. 
+ * If there are any issues during the use process, you can provide feedback to the kingdee developer community website.
+ * Website: https://developer.kingdee.com/developer?productLineId=29
+ * Author: liebin.zheng
+ * Generate Date: 2025-05-26 16:28:10
+ */
+
+dependencies {
+
+	// 公共基础包
+	implementation project(':nckd-jxccl-base-common')
+	implementation project(':nckd-jxccl-base-helper')
+
+	// 引入hr云模块
+	implementation project(':nckd-jxccl-hr')
+
+
+	// 引入swc云模块
+	implementation project(':nckd-jxccl-swc')
+
+
+	// 引入rpt云模块
+	implementation project(':nckd-jxccl-rpt')
+
+
+	// 引入opmc云模块
+	implementation project(':nckd-jxccl-opmc')
+
+
+	// 引入odc云模块
+	implementation project(':nckd-jxccl-odc')
+
+
+	// 引入wtc云模块
+	implementation project(':nckd-jxccl-wtc')
+
+
+	// 引入odc云模块
+	implementation project(':nckd-jxccl-odc')
+
+
+	// 引入hrmp云模块
+	implementation project(':nckd-jxccl-hrmp')
+
 }

+ 14 - 0
code/odc/nckd-jxccl-odc/build.gradle

@@ -0,0 +1,14 @@
+/*
+ * This is a kingdee cosmic template project that is automatically generated by the Kingdee cosmic development assistant plugin. 
+ * If there are any issues during the use process, you can provide feedback to the kingdee developer community website.
+ * Website: https://developer.kingdee.com/developer?productLineId=29
+ * Author: liebin.zheng
+ * Generate Date: 2025-09-28 14:21:58
+ */
+
+dependencies {
+	api project(':nckd-jxccl-base-common')
+	api project(':nckd-jxccl-base-helper')
+} 
+
+

+ 0 - 0
code/odc/nckd-jxccl-odc/src/main/java/nckd/jxccl/odc/homs/business/.gitkeep


+ 5 - 5
code/epm/nckd-jxccl-epm/src/main/java/nckd/jxccl/epm/init/common/AppflgConstant.java → code/odc/nckd-jxccl-odc/src/main/java/nckd/jxccl/odc/homs/common/AppflgConstant.java

@@ -3,20 +3,20 @@
  * If there are any issues during the use process, you can provide feedback to the kingdee developer community website.
  * Website: https://developer.kingdee.com/developer?productLineId=29
  * Author: liebin.zheng
- * Generate Date: 2025-05-26 16:31:20
+ * Generate Date: 2025-05-26 16:28:10
  */
-package nckd.jxccl.epm.init.common;
+package nckd.jxccl.odc.homs.common;
 
 /**
- * epm云init应用-通用常量类<br>
+ * hr云init应用-通用常量类<br>
  * 代码中不能存在硬编码敏感信息,如账号、密码、http外链、ftp外链、邮箱等。<br>
  * 标识或缓存的常量,需以"KEY_"、"FID_"、"ENTRY_"或"SUBENTRY_"作为变量的前缀。<br>
  *
  * @author nckd
- * @date 2025-05-26 16:31:20
+ * @date 2025-05-26 16:28:10
  */
 public class AppflgConstant {
 	
-	public static final String KEY_APP_NAME = "epm-init";
+	public static final String KEY_APP_NAME = "hr-init";
 
 }

+ 58 - 0
code/odc/nckd-jxccl-odc/src/main/java/nckd/jxccl/odc/homs/common/orgbatch/OrgBatchConstant.java

@@ -0,0 +1,58 @@
+/**
+ * This is a kingdee cosmic template project that is automatically generated by the Kingdee cosmic development assistant plugin. 
+ * If there are any issues during the use process, you can provide feedback to the kingdee developer community website.
+ * Website: https://developer.kingdee.com/developer?productLineId=29
+ * Author: liebin.zheng
+ * Generate Date: 2025-05-26 16:28:10
+ */
+package nckd.jxccl.odc.homs.common.orgbatch;
+
+import nckd.jxccl.base.common.constant.FormConstant;
+
+/**
+ * 组织调整申请常量
+ * @author jtd
+ * @date 2025-09-26 15:16
+ */
+public class OrgBatchConstant extends FormConstant {
+	/**
+	 * 设置部门负责人OP
+	 */
+	public static final String SHOW_CHARGE_PERSON_OP = "showchargeperson";
+
+	/**
+	 * 组织复制OP
+	 */
+	public static final String ADMINORG_COPY_OP = "adminorgcopy";
+
+	/**
+	 * 设置部门负责人弹窗
+	 */
+	public static final String CHARGE_PERSON_DIALOG = "chargepersondialog";
+
+	/**
+	 * 组织复制弹窗表单ID
+	 */
+	public static final String NCKD_ADMINORG_COPY_DIALOG_FORMID = "nckd_adminorgcopydialog";
+
+	/**
+	 * 行政组织
+	 */
+	public static final String NCKD_ADMINORG_KEY = "nckd_adminorg";
+
+	/**
+	 * F7列表表单模板
+	 */
+	public static final String HAOS_ORGTREE_LIST_F7_FORMID = "haos_orgtreelistf7";
+
+	/**
+	 * 包含所有下级
+	 */
+	public static final String NCKD_INCLUDE_ALL_SUBORG_KEY = "nckd_includeallsuborg";
+
+	/**
+	 * 是否复制岗位
+	 */
+	public static final String NCKD_IS_COPY_POSITION_KEY = "nckd_iscopyposition";
+
+}

+ 0 - 0
code/odc/nckd-jxccl-odc/src/main/java/nckd/jxccl/odc/homs/mservice/.gitkeep


+ 0 - 0
code/odc/nckd-jxccl-odc/src/main/java/nckd/jxccl/odc/homs/plugin/form/.gitkeep


+ 52 - 0
code/odc/nckd-jxccl-odc/src/main/java/nckd/jxccl/odc/homs/plugin/form/orgbatch/AdminOrgCopyDialogFormPlugin.java

@@ -0,0 +1,52 @@
+package nckd.jxccl.odc.homs.plugin.form.orgbatch;
+
+import kd.bos.form.FormShowParameter;
+import kd.bos.form.ShowType;
+import kd.bos.form.events.AfterDoOperationEventArgs;
+import kd.bos.form.field.BasedataEdit;
+import kd.bos.form.plugin.AbstractFormPlugin;
+import nckd.jxccl.odc.homs.common.orgbatch.OrgBatchConstant;
+
+import java.util.EventObject;
+
+/**
+ * 组织复制弹窗表单插件
+ * @author: jtd
+ * @date: 2025-09-26 16:35
+ */
+public class AdminOrgCopyDialogFormPlugin extends AbstractFormPlugin {
+
+    @Override
+    public void afterBindData(EventObject e) {
+        super.afterBindData(e);
+
+        // 界面构建完成后自动触发行政组织F7弹窗
+        BasedataEdit adminOrg = this.getView().getControl(OrgBatchConstant.NCKD_ADMINORG_KEY);
+        if (adminOrg != null) {
+            adminOrg.click();
+        }
+    }
+
+    @Override
+    public void afterDoOperation(AfterDoOperationEventArgs afterDoOperationEventArgs) {
+        super.afterDoOperation(afterDoOperationEventArgs);
+
+        if (afterDoOperationEventArgs.getOperationResult().isSuccess()) {
+            // 创建弹出参数对象
+            FormShowParameter formShowParameter = new FormShowParameter();
+            // 设置要弹出的动态表单标识
+            formShowParameter.setFormId("");
+            // 设置打开方式为模态框
+            formShowParameter.getOpenStyle().setShowType(ShowType.Modal);
+            // 设置自定义参数
+            formShowParameter.setCustomParam("adminOrg", this.getModel().getValue(OrgBatchConstant.NCKD_ADMINORG_KEY));// 行政组织
+            formShowParameter.setCustomParam("includeAllAdminSubOrg", this.getModel().getValue(OrgBatchConstant.NCKD_INCLUDE_ALL_SUBORG_KEY));// 包含所有下级
+            formShowParameter.setCustomParam("isCopyPosition", this.getModel().getValue(OrgBatchConstant.NCKD_IS_COPY_POSITION_KEY));// 是否复制岗位
+            // 执行弹出操作
+            //this.getView().showForm(formShowParameter);
+
+            // 关闭当前表单
+            this.getView().close();
+        }
+    }
+}

+ 0 - 0
code/odc/nckd-jxccl-odc/src/main/java/nckd/jxccl/odc/homs/plugin/list/.gitkeep


+ 95 - 0
code/odc/nckd-jxccl-odc/src/main/java/nckd/jxccl/odc/homs/plugin/list/orgbatch/OrgBatchChgBillListPlugin.java

@@ -0,0 +1,95 @@
+package nckd.jxccl.odc.homs.plugin.list.orgbatch;
+
+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.StyleCss;
+import kd.bos.form.events.BeforeDoOperationEventArgs;
+import kd.bos.form.events.ClosedCallBackEvent;
+import kd.bos.form.operate.AbstractOperate;
+import kd.bos.list.ListShowParameter;
+import kd.bos.list.plugin.AbstractListPlugin;
+import kd.hr.haos.business.domain.adminorg.service.impl.AdminOrgDetailHelper;
+import nckd.jxccl.odc.homs.common.orgbatch.OrgBatchConstant;
+
+/**
+ * 组织调整申请界面插件
+ * @author: jtd
+ * @date: 2025-09-26 15:16
+ */
+public class OrgBatchChgBillListPlugin extends AbstractListPlugin {
+
+    @Override
+    public void beforeDoOperation(BeforeDoOperationEventArgs args) {
+        super.beforeDoOperation(args);
+
+        boolean rootInit = (new AdminOrgDetailHelper()).checkRootInit(this.getView());
+        if (!rootInit) {
+            args.setCancel(true);
+        } else {
+            AbstractOperate operate = (AbstractOperate)args.getSource();
+            String operateKey = operate.getOperateKey();
+            openOperationPage(operateKey, args);
+        }
+    }
+
+    private void openOperationPage(String opKey, BeforeDoOperationEventArgs args) {
+        if (OrgBatchConstant.SHOW_CHARGE_PERSON_OP.equals(opKey)) {
+            // 创建弹出列表界面对象
+            ListShowParameter listShowParameter = new ListShowParameter();
+            // 设置F7列表表单模板(根据基础资料类型选择)
+            listShowParameter.setFormId(OrgBatchConstant.HAOS_ORGTREE_LIST_F7_FORMID);
+            // 设置基础资料标识
+            listShowParameter.setBillFormId(OrgBatchConstant.ADMINORGHR_ENTITYID);
+            // 设置打开方式为模态窗口
+            listShowParameter.getOpenStyle().setShowType(ShowType.Modal);
+            // 设置界面大小
+            StyleCss inlineStyleCss = new StyleCss();
+            inlineStyleCss.setHeight("580");
+            inlineStyleCss.setWidth("960");
+            listShowParameter.getOpenStyle().setInlineStyleCss(inlineStyleCss);
+            // 必须设置为true,表示是可选择界面
+            listShowParameter.setLookUp(true);
+            // 设置是否多选
+            listShowParameter.setMultiSelect(false);
+            // 设置是否显示标题
+            listShowParameter.setShowTitle(false);
+            // 设置回调(不设置会导致空指针)
+            listShowParameter.setCloseCallBack(new CloseCallBack(this, OrgBatchConstant.CHARGE_PERSON_DIALOG));
+            // 弹出F7选择界面
+            this.getView().showForm(listShowParameter);
+        }
+
+        if (OrgBatchConstant.ADMINORG_COPY_OP.equals(opKey)) {
+            // 创建弹出参数对象
+            FormShowParameter formShowParameter = new FormShowParameter();
+            // 设置要弹出的动态表单标识
+            formShowParameter.setFormId(OrgBatchConstant.NCKD_ADMINORG_COPY_DIALOG_FORMID);
+            // 设置打开方式为模态框
+            formShowParameter.getOpenStyle().setShowType(ShowType.Modal);
+            // 执行弹出操作
+            this.getView().showForm(formShowParameter);
+        }
+
+    }
+
+    @Override
+    public void closedCallBack(ClosedCallBackEvent closedCallBackEvent) {
+        super.closedCallBack(closedCallBackEvent);
+
+        String actionId = closedCallBackEvent.getActionId();
+        ListSelectedRowCollection returnData = (ListSelectedRowCollection) closedCallBackEvent.getReturnData();
+        if (returnData != null && returnData.size() > 0) {
+            return;
+        }
+
+        // 设置部门负责人回调
+        if (OrgBatchConstant.CHARGE_PERSON_DIALOG.equals(actionId)) {
+            ListSelectedRow listSelectedRow = returnData.get(0);
+            // 跳转到部门负责人设置界面
+            (new AdminOrgDetailHelper()).showDeptLeaderSet(this, (Long) listSelectedRow.getPrimaryKeyValue());
+        }
+    }
+}

+ 0 - 0
code/odc/nckd-jxccl-odc/src/main/java/nckd/jxccl/odc/homs/plugin/operate/.gitkeep


+ 0 - 0
code/odc/nckd-jxccl-odc/src/main/java/nckd/jxccl/odc/homs/plugin/other/.gitkeep


+ 0 - 0
code/odc/nckd-jxccl-odc/src/main/java/nckd/jxccl/odc/homs/plugin/report/.gitkeep


+ 0 - 0
code/odc/nckd-jxccl-odc/src/main/java/nckd/jxccl/odc/homs/plugin/workflow/.gitkeep


+ 0 - 0
code/odc/nckd-jxccl-odc/src/main/java/nckd/jxccl/odc/homs/webapi/.gitkeep


+ 0 - 0
code/odc/nckd-jxccl-odc/src/main/java/resources/.gitkeep


+ 0 - 0
code/odc/nckd-jxccl-odc/src/main/resources/.gitkeep


+ 0 - 0
code/odc/nckd-jxccl-odc/src/test/java/nckd/odc/homs/business/test/.gitkeep


+ 0 - 0
code/odc/nckd-jxccl-odc/src/test/java/nckd/odc/homs/common/test/.gitkeep


+ 0 - 0
code/odc/nckd-jxccl-odc/src/test/java/nckd/odc/homs/mservice/test/.gitkeep


+ 0 - 0
code/odc/nckd-jxccl-odc/src/test/java/nckd/odc/homs/plugin/test/.gitkeep


+ 0 - 0
code/odc/nckd-jxccl-odc/src/test/java/nckd/odc/homs/report/test/.gitkeep


+ 0 - 0
code/odc/nckd-jxccl-odc/src/test/java/nckd/odc/homs/webapi/test/.gitkeep


+ 0 - 0
code/odc/nckd-jxccl-odc/src/test/resources/.gitkeep


+ 202 - 0
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/business/importtaskguide/ImportTaskGuideExportService.java

@@ -0,0 +1,202 @@
+package nckd.jxccl.sit.hcsi.business.importtaskguide;
+
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.resource.ResManager;
+import kd.bos.form.FormShowParameter;
+import kd.bos.form.IFormView;
+import kd.bos.logging.Log;
+import kd.bos.logging.LogFactory;
+import kd.bos.orm.query.QFilter;
+import kd.swc.hsas.business.cal.export.SWCExportDataHelper;
+import kd.swc.hsas.business.cal.service.CalResultCoverImportService;
+import kd.swc.hsbp.common.enums.DataTypeEnum;
+import kd.swc.hsbp.common.enums.SWCShowType;
+import kd.swc.hsbp.common.util.SWCDateTimeUtils;
+import kd.swc.hsbp.common.util.SWCStringUtils;
+import nckd.jxccl.sit.hcsi.business.importtaskguide.utils.ImportTaskUtils;
+import nckd.jxccl.sit.hcsi.formplugin.web.tp.enums.SinsurPresetItemEnum;
+import org.apache.poi.hssf.util.HSSFColor;
+import org.apache.poi.ss.usermodel.CellStyle;
+import org.apache.poi.ss.usermodel.Comment;
+import org.apache.poi.ss.usermodel.Font;
+import org.apache.poi.ss.usermodel.HorizontalAlignment;
+import org.apache.poi.xssf.streaming.*;
+import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
+import org.apache.poi.xssf.usermodel.XSSFRichTextString;
+
+import java.text.MessageFormat;
+import java.util.*;
+
+/**
+ * Tyx 2025-10-21
+ * 导出Service,nckd_taskguideimport
+ */
+public class ImportTaskGuideExportService {
+
+    private static final Log logger = LogFactory.getLog(ImportTaskGuideExportService.class);
+    private static final int PAGE_SIZE = 500;
+    private static final String TPLERROR = "1";
+
+    /**
+     * 导入模板方法
+     * @param view
+     */
+    public void exportExcelTemplate(IFormView view) {
+        logger.info("-------- begin exportExcelTemplate --------");
+
+        try {
+            SXSSFWorkbook wb = new SXSSFWorkbook(500);
+            Throwable exp = null;
+            try {
+                FormShowParameter parameter = view.getFormShowParameter();
+                // 外部系统数据导入模板
+                Long sinsurTplId = (Long) parameter.getCustomParam("sinsurTplId");
+                // 导入任务ID
+                Long importTaskId = (Long) parameter.getCustomParam("importTaskId");
+                String dd = SWCDateTimeUtils.format(new Date(), "yyyyMMdd");
+                String exportFileName = MessageFormat.format(ResManager.loadKDString("外部系统数据导入任务_数据导入模板_{0}", "ImportTaskGuideExportService_1", "swc-hsas-business", new Object[0]), dd);
+                createImportTaskDataSheet(sinsurTplId, wb, importTaskId);
+                flushAllAndDownload(wb, exportFileName, view);
+            } catch (Throwable var18) {
+                exp = var18;
+                throw var18;
+            } finally {
+                if (wb != null) {
+                    if (exp != null) {
+                        try {
+                            wb.close();
+                        } catch (Throwable e1) {
+                            exp.addSuppressed(e1);
+                        }
+                    } else {
+                        wb.close();
+                    }
+                }
+
+            }
+        } catch (Exception e2) {
+            logger.error("ImportTaskGuideExportService  error : ", e2);
+            String str = ResManager.loadKDString("下载导入模板失败。", "ImportTaskGuideExportService_0", "swc-hsas-business", new Object[0]);
+            view.showErrorNotification(str);
+        }
+        logger.info("end exportExcelTemplate");
+    }
+
+    /**
+     * 创建Excel
+     * @param sinsurTplId
+     * @param wb
+     * @param importTaskId
+     */
+    private void createImportTaskDataSheet(Long sinsurTplId, SXSSFWorkbook wb, Long importTaskId) {
+        DynamicObject sinsurData = ImportTaskUtils.getSinsurTplData(sinsurTplId, "id,number,nckd_startline", (QFilter)null);
+        int startLine = sinsurData.getInt("nckd_startline");
+        String sheetName = ResManager.loadKDString("数据导入模板", "ImportTaskGuideExportService_2", "swc-hsas-business", new Object[0]);
+        SXSSFSheet sheet = wb.createSheet(sheetName);
+        sheet.setRandomAccessWindowSize(-1);
+        SXSSFDrawing drawingPatriarch = sheet.createDrawingPatriarch();
+        SXSSFRow headRow = sheet.createRow(startLine - 2);
+        CellStyle headDateStyle = CalResultCoverImportService.getColumnStyle(true, 0, 0, SWCShowType.DATE.getCode(), HorizontalAlignment.LEFT, sheet.getWorkbook(), HSSFColor.HSSFColorPredefined.GREY_25_PERCENT.getIndex(), true);
+        CellStyle headTextStyle = CalResultCoverImportService.getColumnStyle(true, 0, 0, SWCShowType.TEXT.getCode(), HorizontalAlignment.LEFT, sheet.getWorkbook(), HSSFColor.HSSFColorPredefined.GREY_25_PERCENT.getIndex(), true);
+        CellStyle headRequriedNumStyle = CalResultCoverImportService.getColumnStyle(true, 0, 0, SWCShowType.NUM.getCode(), HorizontalAlignment.LEFT, sheet.getWorkbook(), HSSFColor.HSSFColorPredefined.GREY_25_PERCENT.getIndex(), true);
+        Font font = sheet.getWorkbook().createFont();
+        CellStyle requrriedStyle = CalResultCoverImportService.getColumnStyle(true, 0, 0, SWCShowType.TEXT.getCode(), HorizontalAlignment.LEFT, sheet.getWorkbook(), HSSFColor.HSSFColorPredefined.GREY_25_PERCENT.getIndex(), true);
+        font.setColor((short)10);
+        requrriedStyle.setFont(font);
+        headRequriedNumStyle.setFont(font);
+        Map<Long, SinsurPresetItemEnum> itemEnumMap = SinsurPresetItemEnum.getSinsurPresetItemEnumMap();
+        List<Map<String, String>> columnHeadList = ImportTaskUtils.getColumnHeadList(sinsurTplId, importTaskId);
+        List<Integer> textIndexList = new ArrayList(columnHeadList.size());
+        Set<Integer> allIndexSet = new HashSet(columnHeadList.size());
+        SinsurPresetItemEnum presetItemEnum = null;
+        for (int i = 0; i < columnHeadList.size(); ++i) {
+            Map<String, String> columnHead = columnHeadList.get(i);
+            String columnIndexStr = (String)columnHead.get("columnIndex");
+            String dataTypeIdStr = (String)columnHead.get("datatypeid");
+            String name = (String)columnHead.get("name");
+            String itemType = (String)columnHead.get("itemType");
+            String comment = (String)columnHead.get("comment");
+            int columnIndex = Integer.parseInt(columnIndexStr);
+            if (allIndexSet.add(columnIndex) && !textIndexList.contains(columnIndex)) {
+                if (Long.parseLong(dataTypeIdStr) == DataTypeEnum.STRING.getDbId()) {
+                    textIndexList.add(columnIndex);
+                }
+                if ("0".equals(itemType)) {
+                    presetItemEnum = (SinsurPresetItemEnum)itemEnumMap.get(Long.valueOf((String)columnHead.get("id")));
+                    CellStyle style = this.getFixCellStyle(presetItemEnum, requrriedStyle, headDateStyle, headTextStyle, headRequriedNumStyle);
+                    this.createCell(comment, headRow, columnIndex, presetItemEnum.getImportColumnName(), presetItemEnum.isRequire(), style, this.getDataType(presetItemEnum), drawingPatriarch);
+                } else {
+                    this.createCell(comment, headRow, columnIndex, name, false, headTextStyle, dataTypeIdStr, drawingPatriarch);
+                }
+            }
+        }
+
+        Iterator<Integer> it = allIndexSet.iterator();
+        while(it.hasNext()) {
+            int index = (Integer)it.next();
+            int columnIndex = sheet.getColumnWidth(index);
+            sheet.setColumnWidth(index, columnIndex * 3);
+        }
+
+        this.batchSetDefaulColumnStyle(sheet, textIndexList, this.getTextCellStyle(sheet));
+    }
+
+    private CellStyle getFixCellStyle(SinsurPresetItemEnum presetItemEnum, CellStyle requrriedStyle, CellStyle headDateStyle, CellStyle headTextStyle, CellStyle headRequriedNumStyle) {
+        if (presetItemEnum.isRequire()) {
+            return presetItemEnum.getDataTypeId() == DataTypeEnum.NUMBERIC.getDbId() ? headRequriedNumStyle : requrriedStyle;
+        } else {
+            return presetItemEnum.getDataTypeId() == DataTypeEnum.DATE.getDbId() ? headDateStyle : headTextStyle;
+        }
+    }
+
+    private void createCell(String comment, SXSSFRow headRow, int cellIndex, String name, boolean isRequried, CellStyle cellStyle, String dataType, SXSSFDrawing drawingPatriarch) {
+        SXSSFCell cell = headRow.createCell(cellIndex);
+        String value = "";
+        if (isRequried) {
+            value = "*" + name;
+        } else {
+            value = name;
+        }
+        cell.setCellValue(value);
+        cell.setCellStyle(cellStyle);
+        if (dataType != null) {
+            cell.setCellComment(this.getComment(comment, drawingPatriarch, cell));
+        }
+    }
+
+    private Comment getComment(String commentStr, SXSSFDrawing drawingPatriarch, SXSSFCell cell) {
+        Comment comment = drawingPatriarch.createCellComment(new XSSFClientAnchor(cell.getColumnIndex(), cell.getRowIndex(), cell.getColumnIndex() + 1, cell.getRowIndex() + 2, cell.getColumnIndex(), cell.getRowIndex(), cell.getColumnIndex() + 1, cell.getRowIndex() + 2));
+        comment.setString(new XSSFRichTextString(commentStr));
+        return comment;
+    }
+
+    private void batchSetDefaulColumnStyle(SXSSFSheet sheet, List<Integer> indexList, CellStyle cellStyle) {
+        Iterator var4 = indexList.iterator();
+        while(var4.hasNext()) {
+            int index = (Integer)var4.next();
+            sheet.setDefaultColumnStyle(index, cellStyle);
+        }
+    }
+
+    private CellStyle getTextCellStyle(SXSSFSheet sheet) {
+        CellStyle textCellStyle = sheet.getWorkbook().createCellStyle();
+        textCellStyle.setDataFormat((short)49);
+        return textCellStyle;
+    }
+
+    private String getDataType(SinsurPresetItemEnum presetItemEnum) {
+        if (presetItemEnum.getDataTypeId() == DataTypeEnum.DATE.getDbId()) {
+            return SWCShowType.DATE.getCode();
+        } else {
+            return presetItemEnum.getDataTypeId() == DataTypeEnum.NUMBERIC.getDbId() ? SWCShowType.NUM.getCode() : SWCShowType.TEXT.getCode();
+        }
+    }
+
+    private void flushAllAndDownload(SXSSFWorkbook wb, String fileName, IFormView view) {
+        String url = SWCExportDataHelper.storeFile(wb, fileName);
+        if (SWCStringUtils.isNotEmpty(url)) {
+            view.download(url);
+        }
+    }
+
+}

+ 431 - 0
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/business/importtaskguide/ImportTaskGuideImportService.java

@@ -0,0 +1,431 @@
+package nckd.jxccl.sit.hcsi.business.importtaskguide;
+
+import com.google.common.collect.Lists;
+import java.math.BigDecimal;
+import kd.bos.context.RequestContext;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.dataentity.resource.ResManager;
+import kd.bos.db.tx.TX;
+import kd.bos.db.tx.TXHandle;
+import kd.bos.entity.EntityMetadataCache;
+import kd.bos.entity.EntityType;
+import kd.bos.entity.MainEntityType;
+import kd.bos.exception.KDBizException;
+import kd.bos.fileservice.FileService;
+import kd.bos.fileservice.FileServiceFactory;
+import kd.bos.impt.ExcelReader;
+import kd.bos.impt.SheetHandler;
+import kd.bos.logging.Log;
+import kd.bos.logging.LogFactory;
+import kd.bos.orm.query.QFilter;
+import kd.bos.threads.ThreadPools;
+import kd.hr.hbp.business.bgtask.HRBackgroundTaskHelper;
+import kd.swc.hsas.common.enums.PresetItemEnum;
+import kd.swc.hsbp.business.servicehelper.SWCDataServiceHelper;
+import kd.swc.hsbp.common.cache.ISWCAppCache;
+import kd.swc.hsbp.common.cache.SWCAppCache;
+import kd.swc.hsbp.common.util.SWCDateTimeUtils;
+import kd.swc.hsbp.common.util.SWCListUtils;
+import kd.swc.hsbp.common.util.SWCStringUtils;
+import nckd.jxccl.sit.hcsi.business.importtaskguide.utils.ImportTaskUtils;
+import nckd.jxccl.sit.hcsi.formplugin.web.tp.enums.SinsurPresetItemEnum;
+import org.apache.commons.lang.exception.ExceptionUtils;
+
+import java.io.InputStream;
+import java.text.MessageFormat;
+import java.util.*;
+
+public class ImportTaskGuideImportService {
+
+    private static final Log logger = LogFactory.getLog(ImportTaskGuideImportService.class);
+    private Long importTaskId;
+    private Long sinsurTplId;
+    private Long welfarepayerId;
+    private Long periodId;
+    private String url;
+    private static final long DATE_TYPE_ID = 1050L;
+    private static final long NUMBER_TYPE_ID = 1010L;
+    private static final long DECIMAL_TYPE_ID = 1020L;
+    private static final String DATE_FORMAT = "yyyy-MM-dd";
+
+    public ImportTaskGuideImportService(String url, Long importTaskId, Long sinsurTplId, Long periodId, Long welfarepayerId) {
+        this.url = url;
+        this.importTaskId = importTaskId;
+        this.sinsurTplId = sinsurTplId;
+        this.periodId = periodId;
+        this.welfarepayerId = welfarepayerId;
+    }
+
+    public Map<String, String> parseAndCheckExcelData(Long orgId, String pageId, String importTaskName) {
+        Map<String, String> resultMap = new HashMap(5);
+        List<Map<Integer, String>> dataHeadList = Lists.newArrayListWithCapacity(10);
+        List<Map<Integer, String>> dataRowList = Lists.newArrayListWithCapacity(10);
+        DynamicObject sinsurData = ImportTaskUtils.getSinsurTplData(sinsurTplId, "id,number,nckd_startline,nckd_endline", (QFilter)null);
+        logger.info("readExcelData begin");
+        this.readExcelData(dataHeadList, dataRowList, sinsurData.getInt("nckd_startline") - 2, sinsurData.getInt("nckd_endline") - 1);
+        logger.info("readExcelData end");
+        if (dataHeadList.size() == 0) {
+            throw new KDBizException(ResManager.loadKDString("没有找到对应的列标题。", "ImportTaskGuideImportService_0", "swc-hsas-business", new Object[0]));
+        } else if (dataRowList.size() == 0) {
+            resultMap.put("errorMsg", ResManager.loadKDString("未解析到有效数据,请录入数据后再试。", "ImportTaskGuideImportService_17", "swc-hsas-business", new Object[0]));
+            return resultMap;
+        } else {
+            Set<String> errDataList = new HashSet(16);
+            List<Map<String, String>> columnList = ImportTaskUtils.getColumnHeadList(this.sinsurTplId, this.importTaskId);
+            Map<Integer, SinsurPresetItemEnum> tplFixItemMap = this.getTplFixItemMap(columnList);
+            this.checkExcelTemplate(dataHeadList, errDataList, tplFixItemMap);
+            String cacheKey;
+            if (errDataList.size() > 0) {
+                cacheKey = ResManager.loadKDString("模板列名“{0}”不能删除。", "ImportTaskGuideImportService_1", "swc-hsas-business", new Object[0]);
+                String errorMsg = SWCListUtils.join(errDataList, "、");
+                throw new KDBizException(MessageFormat.format(cacheKey, errorMsg));
+            } else {
+                cacheKey = UUID.randomUUID().toString();
+                resultMap.put("totalCount", String.valueOf(dataRowList.size()));
+                resultMap.put("cacheKey", cacheKey);
+                Map<String, Object> params = new HashMap(16);
+                String name = ResManager.loadKDString("外部系统数据导入-%s", "ImportTaskGuideImportService_10", "swc-hsas-business", new Object[0]);
+                name = String.format(Locale.ROOT, name, importTaskName);
+                params.put("importTaskId", this.importTaskId);
+                params.put("verifyId", cacheKey);
+                params.put("totalCount", dataRowList.size());
+                params.put("startTime", SWCDateTimeUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
+                params.put("progressType", "22");
+                String bgTaskId = HRBackgroundTaskHelper.getInstance().createBaskgroundTask("swc_hsas_importtaskguide_import", name, true, pageId, params);
+                ISWCAppCache appCache = SWCAppCache.get(String.format(Locale.ROOT, "bggroud_taskid_%s", cacheKey));
+                appCache.put("bgTaskId", bgTaskId);
+                appCache.put("totalCount", dataRowList.size());
+                RequestContext ctx = RequestContext.get();
+                ThreadPools.executeOnce("IMPORTTASK_IMPORT_IN_POOL_ASYNC", () -> {
+                    RequestContext.copyAndSet(ctx);
+                    logger.info("parseAndCheckExcelData ,tranceId={}", ctx.getTraceId());
+                    this.importData(dataHeadList, dataRowList, sinsurData, cacheKey, null, orgId, tplFixItemMap);
+                });
+                return resultMap;
+            }
+        }
+    }
+
+    private void importData(List<Map<Integer, String>> dataHeadList, List<Map<Integer, String>> dataRowList, DynamicObject migrationTplData, String cacheKey, String writeTaskType, Long orgId, Map<Integer, SinsurPresetItemEnum> tplFixItemMap) {
+        logger.info("importData begin,importTaskId={}", this.importTaskId);
+        List<Map<String, String>> errDataList = new ArrayList(10);
+        ImportTaskGuideExportService service = new ImportTaskGuideExportService();
+        if (!this.isCancel(cacheKey)) {
+            boolean hasWorkStartDate = tplFixItemMap.containsKey(11);
+            Map<Integer, List<Map<String, String>>> columnIndexMap = this.getColumnIndexMap();
+            int defaultSize = 500;
+            List<List<Map<Integer, String>>> splitDataList = SWCListUtils.split(dataRowList, defaultSize);
+            int lineIndex = 0;
+            List<Map<Integer, String>> tempList = null;
+            int index = 0;
+
+            for(int size = splitDataList.size(); index < size; ++index) {
+                tempList = (List)splitDataList.get(index);
+                lineIndex = index * defaultSize;
+                this.checkImportData(tempList, errDataList, columnIndexMap, lineIndex, cacheKey, writeTaskType, orgId, hasWorkStartDate, false);
+            }
+
+            if (!this.isCancel(cacheKey)) {
+                if (errDataList.size() > 0) {
+                    // TODO String fileUrl = service.getImportErrorExcelFile(dataHeadList, dataRowList, errDataList, migrationTplData.getInt("startline") - 2, writeTaskType, columnIndexMap, hasWorkStartDate);
+                    // TODO kd.swc.hsas.business.importtaskguide.utils.ImportTaskUtils.updateImportDataProgress(0, 0, cacheKey, fileUrl);
+                }
+
+                logger.info("importData end,importTaskId={}", this.importTaskId);
+            }
+        }
+    }
+
+    private Boolean isCancel(String cacheKey) {
+        String key = String.format(Locale.ROOT, "import_cache_%s", cacheKey);
+        ISWCAppCache appCache = SWCAppCache.get(key);
+        Boolean isCancel = (Boolean)appCache.get(String.format(Locale.ROOT, "isCancel_%s", cacheKey), Boolean.class);
+        return isCancel != null && isCancel ? Boolean.TRUE : Boolean.FALSE;
+    }
+
+    // TODO 校验导入数据
+    private void checkImportData(List<Map<Integer, String>> dataRowList, List<Map<String, String>> allErrDataList, Map<Integer, List<Map<String, String>>> columnIndexMap, int lineIndex, String cacheKey, String writeTaskType, Long orgId, boolean hasWorkStartDate, boolean isMulTimeOnePeriod) {
+        Map<Integer, Map<Integer, Object>> passDataRowMap = new HashMap(16);
+        int lineIndexVer = lineIndex;
+        List<Map<String, String>> errDataList = new ArrayList(10);
+        int successCount = 0;
+        int failCount = 0;
+
+        try {
+            boolean isSuccess = true;
+            Iterator<Map<Integer, String>> it = dataRowList.iterator();
+            while(it.hasNext()) {
+                Map<Integer, Object> passRowMap = new HashMap(16);
+                Map<Integer, String> rowMap = (Map)it.next();
+                isSuccess = this.checkFieldRequriedForCommon(rowMap, errDataList, lineIndex, passRowMap);
+                if(!isSuccess) {
+                    ++lineIndex;
+                } else if (!this.checkItemValue(columnIndexMap, passRowMap, errDataList, lineIndex, rowMap)) {
+                    ++lineIndex;
+                } else {
+                    if(isSuccess) {
+                        passDataRowMap.put(lineIndex, passRowMap);
+                    }
+                    ++lineIndex;
+                }
+            }
+
+            if (!this.isCancel(cacheKey)) {
+                this.saveData(passDataRowMap, columnIndexMap);
+                successCount = passDataRowMap.size();
+                failCount = dataRowList.size() - successCount;
+                return;
+            }
+
+        } catch (Exception e) {
+            logger.error(e);
+            successCount = 0;
+            failCount = dataRowList.size();
+            errDataList.clear();
+            // TODO this.setErrorData(dataRowList.size(), lineIndexVer, errDataList, e.getMessage());
+            return;
+        } finally {
+            allErrDataList.addAll(errDataList);
+            kd.swc.hsas.business.importtaskguide.utils.ImportTaskUtils.updateImportDataProgress(successCount, failCount, cacheKey, (String)null);
+        }
+    }
+
+    private void saveData(Map<Integer, Map<Integer, Object>> passDataRowMap, Map<Integer, List<Map<String, String>>> columnIndexMap) {
+        if (passDataRowMap != null && passDataRowMap.size() != 0) {
+            DynamicObjectCollection result = new DynamicObjectCollection();
+            MainEntityType type = EntityMetadataCache.getDataEntityType("nckd_sinsurtempdata");
+            EntityType entryType = (EntityType)type.getAllEntities().get("entryentity");
+            DynamicObject temporary = null;
+            Map<Integer, Object> rowMap = null;
+            Iterator<Map.Entry<Integer, Map<Integer, Object>>> it = passDataRowMap.entrySet().iterator();
+            while(it.hasNext()) {
+                Map.Entry<Integer, Map<Integer, Object>> entry = (Map.Entry)it.next();
+                temporary = (DynamicObject)type.createInstance();
+                rowMap = (Map)entry.getValue();
+                temporary.set("nckd_datastatus", "0");
+                ImportTaskUtils.setTemporaryValueForCommon(temporary, rowMap);
+                temporary.set("nckd_importtask", this.importTaskId);
+                temporary.set("creator", RequestContext.get().getCurrUserId());
+                temporary.set("createtime", new Date());
+                temporary.set("modifier", RequestContext.get().getCurrUserId());
+                temporary.set("modifytime", new Date());
+                temporary.set("billstatus", "A");
+                temporary.set("entryentity", ImportTaskUtils.getItemEntryList(rowMap, columnIndexMap, entryType));
+                result.add(temporary);
+            }
+            SWCDataServiceHelper helper = new SWCDataServiceHelper("nckd_sinsurtempdata");
+            TXHandle txHandle = TX.requiresNew();
+
+            try {
+                helper.save(result);
+                helper.setEntityName("nckd_sinsurimptask");
+                DynamicObject importTask = helper.queryOne(this.importTaskId);
+                importTask.set("nckd_taskstatus", "1");
+                importTask.set("modifytime", new Date());
+                importTask.set("modifier", RequestContext.get().getCurrUserId());
+                importTask.set("nckd_count", importTask.getInt("nckd_count") + result.size());
+                helper.updateOne(importTask);
+            } catch (Exception var18) {
+                logger.error("save error,", var18);
+                txHandle.markRollback();
+                throw new KDBizException(ExceptionUtils.getFullStackTrace(var18));
+            } finally {
+                txHandle.close();
+            }
+        }
+    }
+
+    private boolean checkItemValue(Map<Integer, List<Map<String, String>>> columnIndexMap,
+                                   Map<Integer, Object> passRowMap,
+                                   List<Map<String, String>> errDataList,
+                                   int lineIndex,
+                                   Map<Integer, String> rowMap) {
+        boolean isPass = true;
+        String errorMsgTemplate = ResManager.loadKDString("{0}:数据格式填写错误。",
+                "ImportTaskGuideImportService_4", "swc-hsas-business", new Object[0]);
+
+        for (Map.Entry<Integer, List<Map<String, String>>> columnEntry : columnIndexMap.entrySet()) {
+            Integer columnIndex = columnEntry.getKey();
+            String itemValue = rowMap.get(columnIndex);
+
+            if (SWCStringUtils.isEmpty(itemValue)) {
+                continue;
+            }
+
+            for (Map<String, String> itemMap : columnEntry.getValue()) {
+                long dataTypeId = Long.parseLong(itemMap.get("datatypeid"));
+                String itemName = itemMap.get("name");
+
+                try {
+                    String processedValue = processValueByType(itemValue, dataTypeId);
+                    passRowMap.put(columnIndex, processedValue);
+                } catch (Exception e) {
+                    isPass = false;
+                    errDataList.add(assembleErrMap(lineIndex, false,
+                            MessageFormat.format(errorMsgTemplate, itemName)));
+                }
+            }
+        }
+        return isPass;
+    }
+
+    private String processValueByType(String value, long dataTypeId) throws Exception {
+        if (DATE_TYPE_ID == dataTypeId) {
+            return SWCDateTimeUtils.format(SWCDateTimeUtils.parseDate(value), DATE_FORMAT);
+        }
+
+        if (NUMBER_TYPE_ID == dataTypeId || DECIMAL_TYPE_ID == dataTypeId) {
+            return new BigDecimal(value).toPlainString();
+        }
+
+        return value;
+    }
+
+
+    private boolean checkFieldRequriedForCommon(Map<Integer, String> rowMap, List<Map<String, String>> errDataList, int lineIndex, Map<Integer, Object> passRowMap) {
+        String msg = ResManager.loadKDString("请填写“{0}”。", "ImportTaskGuideImportService_2", "swc-hsas-business", new Object[0]);
+        if (SWCStringUtils.isEmpty((String)rowMap.get(0))) {
+            errDataList.add(this.assembleErrMap(lineIndex, false, MessageFormat.format(msg, SinsurPresetItemEnum.CALPERIOD.getItemName())));
+            return false;
+        } else {
+            passRowMap.put(0, rowMap.get(0));
+            if (SWCStringUtils.isEmpty((String)rowMap.get(1))) {
+                errDataList.add(this.assembleErrMap(lineIndex, false, MessageFormat.format(msg, SinsurPresetItemEnum.EMP_IDCARD.getItemName())));
+                return false;
+            } else {
+                passRowMap.put(1, rowMap.get(1));
+                if (SWCStringUtils.isEmpty((String)rowMap.get(2))) {
+                    errDataList.add(this.assembleErrMap(lineIndex, false, MessageFormat.format(msg, SinsurPresetItemEnum.EMP_NAME.getItemName())));
+                    return false;
+                } else {
+                    passRowMap.put(2, rowMap.get(2));
+                    if (SWCStringUtils.isEmpty((String)rowMap.get(3))) {
+                        errDataList.add(this.assembleErrMap(lineIndex, false, MessageFormat.format(msg, SinsurPresetItemEnum.EMP_NUMBER.getItemName())));
+                        return false;
+                    } else {
+                        passRowMap.put(3, rowMap.get(3));
+                        return true;
+                    }
+                }
+            }
+        }
+    }
+
+    private Map<Integer, List<Map<String, String>>> getColumnIndexMap() {
+        List<Map<String, String>> columnHeadList = kd.swc.hsas.business.importtaskguide.utils.ImportTaskUtils.getColumnHeadList(this.sinsurTplId, this.importTaskId);
+        Map<Integer, List<Map<String, String>>> columnIndexMap = new HashMap(columnHeadList.size());
+        List<Map<String, String>> tempMapList = null;
+        Iterator var4 = columnHeadList.iterator();
+
+        while(var4.hasNext()) {
+            Map<String, String> obj = (Map)var4.next();
+            if (!"0".equals(obj.get("itemType"))) {
+                tempMapList = (List)columnIndexMap.get(Integer.valueOf((String)obj.get("columnIndex")));
+                if (tempMapList == null) {
+                    tempMapList = new ArrayList(10);
+                    columnIndexMap.put(Integer.valueOf((String)obj.get("columnIndex")), tempMapList);
+                }
+
+                ((List)tempMapList).add(obj);
+            }
+        }
+
+        return columnIndexMap;
+    }
+
+    private Map<String, String> assembleErrMap(int dataIndex, boolean isAll, String msg) {
+        Map<String, String> errMap = new HashMap(4);
+        errMap.put("errMsg", msg);
+        errMap.put("isAll", isAll ? "1" : "0");
+        errMap.put("dataIndex", String.valueOf(dataIndex));
+        return errMap;
+    }
+
+    private void checkExcelTemplate(List<Map<Integer, String>> dataHeadList, Set<String> errDataList, Map<Integer, SinsurPresetItemEnum> tplFixItemMap) {
+        Map<Integer, String> dataHeadMap = (Map)dataHeadList.get(0);
+        String excelName = null;
+        StringBuilder tplName = new StringBuilder();
+        Iterator var7 = tplFixItemMap.entrySet().iterator();
+        while(var7.hasNext()) {
+            Map.Entry<Integer, SinsurPresetItemEnum> entry = (Map.Entry)var7.next();
+            excelName = (String)dataHeadMap.get(entry.getKey());
+            if (SWCStringUtils.isEmpty(excelName)) {
+                errDataList.add(((SinsurPresetItemEnum)entry.getValue()).getImportColumnName());
+            } else {
+                tplName.setLength(0);
+                if (((SinsurPresetItemEnum)entry.getValue()).isRequire()) {
+                    tplName.append('*');
+                }
+                tplName.append(((SinsurPresetItemEnum)entry.getValue()).getImportColumnName());
+                if (!excelName.equals(tplName.toString())) {
+                    errDataList.add(((SinsurPresetItemEnum)entry.getValue()).getImportColumnName());
+                }
+            }
+        }
+    }
+
+    private Map<Integer, SinsurPresetItemEnum> getTplFixItemMap(List<Map<String, String>> columnList) {
+        Map<Integer, SinsurPresetItemEnum> map = new HashMap(16);
+        Map<Long, SinsurPresetItemEnum> presetItemEnumMap = SinsurPresetItemEnum.getSinsurPresetItemEnumMap();
+        SinsurPresetItemEnum tempItemEnum = null;
+        Iterator it = columnList.iterator();
+        while(it.hasNext()) {
+            Map<String, String> temp = (Map)it.next();
+            if ("0".equals(temp.get("itemType"))) {
+                Long itemId = Long.valueOf((String)temp.get("id"));
+                String columnIndexStr = (String)temp.get("columnIndex");
+                tempItemEnum = (SinsurPresetItemEnum)presetItemEnumMap.get(itemId);
+                map.put(Integer.valueOf(columnIndexStr), tempItemEnum);
+            }
+        }
+        return map;
+    }
+
+    /**
+     * 读excel数据
+     * @param dataHeadList
+     * @param dataRowList
+     * @param headIndex
+     * @param dataEndIndex
+     * @throws KDBizException
+     */
+    private void readExcelData(final List<Map<Integer, String>> dataHeadList, final List<Map<Integer, String>> dataRowList, final int headIndex, final int dataEndIndex) throws KDBizException {
+        FileService service = FileServiceFactory.getAttachmentFileService();
+        try {
+            InputStream in = service.getInputStream(this.url);
+            Throwable exp = null;
+            try {
+                (new ExcelReader()).read(in, new SheetHandler() {
+                    public void handleRow(SheetHandler.ParsedRow row) {
+                        if (row.getRowNum() == headIndex) {
+                            dataHeadList.add(row.getData());
+                        } else if (row.getRowNum() > headIndex && row.getRowNum() <= dataEndIndex && row.getData().size() > 0) {
+                            dataRowList.add(row.getData());
+                        }
+
+                    }
+                });
+            } catch (Throwable e) {
+                exp = e;
+                throw e;
+            } finally {
+                if (in != null) {
+                    if (exp != null) {
+                        try {
+                            in.close();
+                        } catch (Throwable e1) {
+                            exp.addSuppressed(e1);
+                        }
+                    } else {
+                        in.close();
+                    }
+                }
+            }
+        } catch (Throwable e2) {
+            logger.error("parse excel error,", e2);
+            throw new KDBizException(ExceptionUtils.getFullStackTrace(e2));
+        }
+    }
+
+}

+ 236 - 0
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/business/importtaskguide/utils/ImportTaskUtils.java

@@ -0,0 +1,236 @@
+package nckd.jxccl.sit.hcsi.business.importtaskguide.utils;
+
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.dataentity.serialization.SerializationUtils;
+import kd.bos.entity.EntityType;
+import kd.bos.orm.query.QFilter;
+import kd.swc.hsas.common.enums.PresetItemEnum;
+import kd.swc.hsbp.business.servicehelper.SWCDataServiceHelper;
+import kd.swc.hsbp.common.cache.ISWCAppCache;
+import kd.swc.hsbp.common.cache.SWCAppCache;
+import kd.swc.hsbp.common.util.SWCStringUtils;
+import nckd.jxccl.sit.hcsi.formplugin.web.tp.enums.SinsurPresetItemEnum;
+
+import java.util.*;
+
+public class ImportTaskUtils {
+
+    private static final String SINSURTPL_ENTITY = "nckd_sinsurtpl";
+    private static final String INSURANCEITEM_ENTITY = "sitbs_insuranceitem";
+
+
+    public static DynamicObject getSinsurTplData(Long sinsurTplId, String fields, QFilter qFilter) {
+        SWCDataServiceHelper helper = new SWCDataServiceHelper(SINSURTPL_ENTITY);
+        QFilter filter = new QFilter("id", "=", sinsurTplId);
+        if (qFilter != null) {
+            filter.and(qFilter);
+        }
+        return helper.queryOne(fields, new QFilter[]{filter});
+    }
+
+    private static DynamicObjectCollection getSinsurTplDataList(Long sinsurTplId) {
+        SWCDataServiceHelper helper = new SWCDataServiceHelper(SINSURTPL_ENTITY);
+        String fields = "nckd_sinsurtplentry.nckd_itemtype,nckd_sinsurtplentry.nckd_itemid,nckd_sinsurtplentry.nckd_matchcolumn,nckd_sinsurtplentry.nckd_comment";
+        QFilter qFilter = new QFilter("id", "=", sinsurTplId);
+        return helper.queryOriginalCollection(fields, new QFilter[]{qFilter}, "nckd_sinsurtplentry.seq asc");
+    }
+
+    public static List<Map<String, String>> getColumnHeadList(Long sinsurTplId, Long importTaskId) {
+        List<Map<String, String>> columnHeadList = new ArrayList(10);
+        if (sinsurTplId != null && sinsurTplId != 0L && importTaskId != null && importTaskId != 0L) {
+            String cacheKey = importTaskId + "_" + sinsurTplId;
+            ISWCAppCache appCache = SWCAppCache.get(cacheKey);
+            String json = (String)appCache.get("columnHeadList", String.class);
+            if (SWCStringUtils.isNotEmpty(json)) {
+                columnHeadList = (List) SerializationUtils.fromJsonString(json, List.class);
+                return columnHeadList;
+            }
+        }
+        DynamicObjectCollection list = getSinsurTplDataList(sinsurTplId);
+        if (list.size() == 0) {
+            return columnHeadList;
+        } else {
+            List<String> itemList = new ArrayList(10);
+            Map<String, Map<String, String>> itemMap = new HashMap(list.size());
+            Set<Long> fixSet = new HashSet(16);
+            Set<Long> iiItemSet = new HashSet(16);
+            Map<String, Integer> indexMap = new HashMap(16);
+            String keyStr = "";
+            Map<String, String> commentMap = new HashMap(list.size());
+            String comment = null;
+            Iterator columnIndex;
+            DynamicObject obj;
+            for(columnIndex = list.iterator(); columnIndex.hasNext(); commentMap.put(keyStr, comment)) {
+                obj = (DynamicObject)columnIndex.next();
+                String itemType = obj.getString("nckd_sinsurtplentry.nckd_itemtype");
+                Long itemId = obj.getLong("nckd_sinsurtplentry.nckd_itemid");
+                comment = obj.getString("nckd_sinsurtplentry.nckd_comment");
+                if ("0".equals(itemType)) {
+                    keyStr = "fix" + itemId;
+                    itemList.add(keyStr);
+                    indexMap.put(keyStr, getExcelRowIndexByTitle(obj.getString("nckd_sinsurtplentry.nckd_matchcolumn")));
+                    fixSet.add(itemId);
+                }
+                else if ("1".equals(itemType)) {
+                    keyStr = "ii" + itemId;
+                    itemList.add(keyStr);
+                    indexMap.put(keyStr, getExcelRowIndexByTitle(obj.getString("nckd_sinsurtplentry.nckd_matchcolumn")));
+                    iiItemSet.add(itemId);
+                }
+            }
+            addFixValue(commentMap, fixSet, "fix", itemMap, "0");
+            addItemValue(commentMap, iiItemSet, "ii", itemMap, INSURANCEITEM_ENTITY, "1");
+            if (itemMap.size() == 0) {
+                return columnHeadList;
+            } else {
+                columnIndex = null;
+                obj = null;
+                Iterator it = itemList.iterator();
+                while(it.hasNext()) {
+                    String key = (String)it.next();
+                    Map<String, String> tempMap = (Map)itemMap.get(key);
+                    if (tempMap != null) {
+                        Integer index = (Integer)indexMap.get(key);
+                        tempMap.put("columnIndex", String.valueOf(index));
+                        columnHeadList.add(tempMap);
+                    }
+                }
+                if (sinsurTplId != null && sinsurTplId != 0L && importTaskId != null && importTaskId != 0L) {
+                    String cacheKey = importTaskId + "_" + sinsurTplId;
+                    ISWCAppCache appCache = SWCAppCache.get(cacheKey);
+                    appCache.put("columnHeadList", SerializationUtils.toJsonString(columnHeadList));
+                }
+                return columnHeadList;
+            }
+        }
+    }
+
+    /**
+     * 处理预置项目
+     * @param commentMap
+     * @param itemSet
+     * @param itemKey
+     * @param itemMap
+     * @param itemType
+     */
+    private static void addFixValue(Map<String, String> commentMap, Set<Long> itemSet, String itemKey, Map<String, Map<String, String>> itemMap, String itemType) {
+        if (itemSet.size() != 0) {
+            Map<Long, SinsurPresetItemEnum> map = SinsurPresetItemEnum.getSinsurPresetItemEnumMap();
+            SinsurPresetItemEnum itemEnum = null;
+            Map<String, String> tempMap = null;
+            Iterator it = itemSet.iterator();
+            while(it.hasNext()) {
+                Long itemId = (Long)it.next();
+                itemEnum = (SinsurPresetItemEnum)map.get(itemId);
+                tempMap = new HashMap(16);
+                tempMap.put("name", itemEnum.getItemName());
+                tempMap.put("datatypeid", String.valueOf(itemEnum.getDataTypeId()));
+                tempMap.put("id", String.valueOf(itemId));
+                tempMap.put("key", getFixColumnKeyByItemId(itemId.toString()));
+                tempMap.put("itemType", itemType);
+                tempMap.put("comment", commentMap.get(itemKey + itemId));
+                itemMap.put(itemKey + itemId, tempMap);
+            }
+        }
+    }
+
+    private static String getFixColumnKeyByItemId(String itemId) {
+        String columnKey = null;
+        switch (itemId) {
+            case "1":
+                columnKey = "period";
+                break;
+            case "2":
+                columnKey = "nckd_idcard";
+                break;
+            case "3":
+                columnKey = "nckd_empname";
+                break;
+            case "4":
+                columnKey = "nckd_empnumber";
+                break;
+        }
+
+        return columnKey;
+    }
+
+    private static void addItemValue(Map<String, String> commentMap, Set<Long> itemSet, String itemKey, Map<String, Map<String, String>> itemMap, String entityId, String itemType) {
+        if (itemSet.size() != 0) {
+            SWCDataServiceHelper helper = new SWCDataServiceHelper(entityId);
+            String fields = "id,datatype.id,name";
+            DynamicObjectCollection result = helper.queryOriginalCollection(fields, new QFilter[]{new QFilter("id", "in", itemSet)});
+            Map<String, String> tempMap = null;
+            Iterator var11 = result.iterator();
+
+            while(var11.hasNext()) {
+                DynamicObject obj = (DynamicObject)var11.next();
+                tempMap = new HashMap(16);
+                String keyStr = itemKey + obj.getLong("id");
+                tempMap.put("name", obj.getString("name"));
+                tempMap.put("datatypeid", String.valueOf(obj.getLong("datatype.id")));
+                tempMap.put("id", String.valueOf(obj.getLong("id")));
+                tempMap.put("key", keyStr);
+                tempMap.put("itemType", itemType);
+                tempMap.put("comment", commentMap.get(keyStr));
+                itemMap.put(keyStr, tempMap);
+            }
+
+        }
+    }
+
+
+    public static int getExcelRowIndexByTitle(String columnTitle) {
+        int length = columnTitle.length();
+        int num = 0;
+        for(int i = 0; i < length; ++i) {
+            num = num * 26 + columnTitle.charAt(i) - 65 + 1;
+        }
+        return num - 1;
+    }
+
+    public static void setTemporaryValueForCommon(DynamicObject temporary, Map<Integer, Object> rowMap) {
+        temporary.set("nckd_periodname", rowMap.get(0));
+        temporary.set("nckd_idcard", rowMap.get(1));
+        temporary.set("nckd_empname", rowMap.get(2));
+        temporary.set("nckd_empnumber", rowMap.get(3));
+    }
+
+    public static DynamicObjectCollection getItemEntryList(Map<Integer, Object> rowMap, Map<Integer, List<Map<String, String>>> columnIndexMap, EntityType entryType) {
+        DynamicObjectCollection itemEntryList = new DynamicObjectCollection();
+        int sequence = 0;
+        for (Map.Entry<Integer, List<Map<String, String>>> entry : columnIndexMap.entrySet()) {
+            Object itemValue = rowMap.get(entry.getKey());
+            if (itemValue == null) {
+                continue;
+            }
+            for (Map<String, String> itemMap : entry.getValue()) {
+                try {
+                    DynamicObject item = (DynamicObject) entryType.createInstance();
+
+                    item.set("nckd_itemvalue", itemValue);
+                    item.set("nckd_itemtype", itemMap.get("itemType"));
+                    item.set("nckd_itemname", itemMap.get("name"));
+                    item.set("seq", sequence);
+
+                    String id = itemMap.get("id");
+                    if (id != null) {
+                        item.set("nckd_itemid", Long.valueOf(id));
+                    }
+
+                    String datatypeId = itemMap.get("datatypeid");
+                    if (datatypeId != null) {
+                        item.set("nckd_datatype", Long.valueOf(datatypeId));
+                    }
+                    sequence++;
+                    itemEntryList.add(item);
+                } catch (Exception e) {
+                    // 记录错误日志,但继续处理其他条目
+                    System.err.println("Error processing item: " + e.getMessage());
+                }
+            }
+        }
+        return itemEntryList;
+    }
+
+}

+ 7 - 0
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/common/constant/SitConstant.java

@@ -0,0 +1,7 @@
+package nckd.jxccl.sit.hcsi.common.constant;
+
+import kd.hr.hbp.business.servicehelper.HRBaseServiceHelper;
+
+public class SitConstant {
+    public static final HRBaseServiceHelper SINSURFILE_HELPER = new HRBaseServiceHelper("hcsi_sinsurfile");
+}

+ 45 - 0
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/formplugin/web/file/attach/FileSIBasePluginEx.java

@@ -0,0 +1,45 @@
+package nckd.jxccl.sit.hcsi.formplugin.web.file.attach;
+
+import com.kingdee.util.StringUtils;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.entity.datamodel.IDataModel;
+import kd.bos.entity.operate.result.OperationResult;
+import kd.bos.form.events.AfterDoOperationEventArgs;
+import kd.bos.form.plugin.AbstractFormPlugin;
+import kd.bos.servicehelper.operation.SaveServiceHelper;
+import kd.sdk.plugin.Plugin;
+import nckd.jxccl.sit.hcsi.common.constant.SitConstant;
+
+/**
+ * Tyx 2025-10-14
+ * 社保基数设置动态表单插件:【nckd_hcsi_filesibase_ext】
+ *
+ */
+public class FileSIBasePluginEx extends AbstractFormPlugin implements Plugin {
+    @Override
+    public void afterDoOperation(AfterDoOperationEventArgs afterDoOperationEventArgs) {
+        super.afterDoOperation(afterDoOperationEventArgs);
+        String operateKey = afterDoOperationEventArgs.getOperateKey();
+        OperationResult operationResult = afterDoOperationEventArgs.getOperationResult();
+        switch (operateKey) {
+            case "donothing_save":
+                if (operationResult == null || operationResult.isSuccess()) {
+                    IDataModel model = this.getModel();
+                    DynamicObjectCollection entryCols = model.getDataEntity().getDynamicObjectCollection("entryentity");
+                    // 保存社保基数成功之后,把对应字段反写到档案头上,并刷新父页面
+                    Long fileSinSurStringId = (Long)this.getView().getFormShowParameter().getCustomParam("sinsurfile");
+                    if (fileSinSurStringId != null) {
+                        DynamicObject fileDyn = SitConstant.SINSURFILE_HELPER.loadOne(fileSinSurStringId);
+                        for(DynamicObject entry : entryCols) {
+                            String key = entry.getString("welfaretype.nckd_sinsurfilefields");
+                            if(!StringUtils.isEmpty(key)) {
+                                fileDyn.set(key, entry.getLong("nckd_sinsurdimension.id"));
+                            }
+                        }
+                        SaveServiceHelper.update(fileDyn);
+                    }
+                }
+        }
+    }
+}

+ 138 - 0
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/formplugin/web/tp/SinsurTempDataListPlugin.java

@@ -0,0 +1,138 @@
+package nckd.jxccl.sit.hcsi.formplugin.web.tp;
+
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.resource.ResManager;
+import kd.bos.form.CloseCallBack;
+import kd.bos.form.FormShowParameter;
+import kd.bos.form.ShowType;
+import kd.bos.form.events.BeforeDoOperationEventArgs;
+import kd.bos.form.events.ClosedCallBackEvent;
+import kd.bos.form.operate.FormOperate;
+import kd.bos.list.plugin.AbstractListPlugin;
+import kd.bos.orm.query.QFilter;
+import kd.sdk.plugin.Plugin;
+import kd.swc.hsbp.business.servicehelper.SWCDataServiceHelper;
+import kd.swc.hsbp.common.util.SWCDateTimeUtils;
+import kd.swc.hsbp.common.util.SWCStringUtils;
+
+import java.util.Date;
+import java.util.Map;
+
+/**
+ * Tyx 2025-10-21
+ * 外部数据中间表数据列表插件 nckd_sinsurtempdata
+ */
+public class SinsurTempDataListPlugin extends AbstractListPlugin implements Plugin {
+
+    @Override
+    public void beforeDoOperation(BeforeDoOperationEventArgs args) {
+        super.beforeDoOperation(args);
+        Long importTaskId = (Long)this.getView().getFormShowParameter().getCustomParam("importTaskId");
+        String creatorId = (String)this.getView().getFormShowParameter().getCustomParam("creator");
+        FormOperate formOperate = (FormOperate)args.getSource();
+        String opKey = formOperate.getOperateKey();
+        switch (opKey) {
+            case "donothing_import":
+                this.opeanImportStartPage();
+                break;
+        }
+    }
+
+    /**
+     * 打开选择导入模板界面
+     */
+    private void opeanImportStartPage() {
+        if (!this.checkTaskStatus(false, true)) {
+            FormShowParameter formShowParameter = new FormShowParameter();
+            formShowParameter.setShowTitle(false);
+            formShowParameter.setFormId("nckd_taskguideimport");
+            formShowParameter.getOpenStyle().setShowType(ShowType.Modal);
+            formShowParameter.setCustomParam("importTaskName", this.getView().getFormShowParameter().getCustomParam("importTaskName"));
+            formShowParameter.setCustomParam("sinsurTplId", this.getView().getFormShowParameter().getCustomParam("sinsurTplId"));
+            formShowParameter.setCustomParam("importTaskId", this.getView().getFormShowParameter().getCustomParam("importTaskId"));
+            formShowParameter.setCustomParam("periodId", this.getView().getFormShowParameter().getCustomParam("periodId"));
+            formShowParameter.setCustomParam("welfarepayerId", this.getView().getFormShowParameter().getCustomParam("welfarepayerId"));
+            formShowParameter.setCustomParam("orgId", this.getView().getFormShowParameter().getCustomParam("orgId"));
+            formShowParameter.setCloseCallBack(new CloseCallBack(this, "importData"));
+            this.getView().showForm(formShowParameter);
+        }
+    }
+
+    private boolean checkTaskStatus(boolean checkIsRunning, boolean checkIsClosed) {
+        Long importTaskId = (Long)this.getView().getFormShowParameter().getCustomParam("importTaskId");
+        SWCDataServiceHelper helper = new SWCDataServiceHelper("nckd_sinsurimptask");
+        DynamicObject importTask = helper.queryOriginalOne("id,nckd_taskstatus", new QFilter[]{new QFilter("id", "=", importTaskId)});
+        String taskStatus = importTask.getString("nckd_taskstatus");
+        String msg = null;
+        if (checkIsRunning) {
+            if (SWCStringUtils.equals(taskStatus, "4")) {
+                msg = ResManager.loadKDString("当前任务后台执行校验中,请稍后再试。", "ImportTaskGuideOpereateBillList_13", "swc-hsas-formplugin", new Object[0]);
+            } else if (SWCStringUtils.equals(taskStatus, "3")) {
+                msg = ResManager.loadKDString("当前任务后台执行预处理中,请稍后再试。", "ImportTaskGuideOpereateBillList_14", "swc-hsas-formplugin", new Object[0]);
+            } else if (SWCStringUtils.equals(taskStatus, "6")) {
+                msg = ResManager.loadKDString("当前任务后台执行反写中,请稍后再试。", "ImportTaskGuideOpereateBillList_15", "swc-hsas-formplugin", new Object[0]);
+            } else if (SWCStringUtils.equals(taskStatus, "5")) {
+                msg = ResManager.loadKDString("当前任务后台执行写入中,请稍后再试。", "ImportTaskGuideOpereateBillList_16", "swc-hsas-formplugin", new Object[0]);
+            } else if (SWCStringUtils.equals(taskStatus, "9")) {
+                msg = ResManager.loadKDString("当前任务后台执行清除中间表数据中,请稍后再试。", "ImportTaskGuideOpereateBillList_36", "swc-hsas-formplugin", new Object[0]);
+            }
+
+            if (msg != null) {
+                this.getView().showTipNotification(msg);
+                return true;
+            }
+        }
+
+        if (!checkIsClosed || !SWCStringUtils.equals(taskStatus, "7") && !SWCStringUtils.equals(taskStatus, "8")) {
+            return false;
+        } else {
+            msg = ResManager.loadKDString("任务已关闭,无法操作。", "ImportTaskGuideOpereateBillList_35", "swc-hsas-formplugin", new Object[0]);
+            this.getView().showErrorNotification(msg);
+            return true;
+        }
+    }
+
+    @Override
+    public void closedCallBack(ClosedCallBackEvent closedCallBackEvent) {
+        super.closedCallBack(closedCallBackEvent);
+        String actionId = closedCallBackEvent.getActionId();
+        if ("importData".equals(actionId)) {
+            Map<String, Object> returnData = (Map)closedCallBackEvent.getReturnData();
+            if (returnData == null) {
+                return;
+            }
+            if ((Boolean)returnData.get("isOk")) {
+                int totalCount = Integer.parseInt(returnData.get("totalCount").toString());
+                Long importTaskId = (Long)returnData.get("importTaskId");
+                String cacheKey = (String)returnData.get("cacheKey");
+                String caption = ResManager.loadKDString("导入看板", "ImportTaskGuideOpereateBillList_33", "swc-hsas-formplugin", new Object[0]);
+                this.openProgressPage(totalCount, importTaskId, "22", "importingData", caption, cacheKey);
+            }
+        }
+        else if ("importingData".equals(actionId)) {
+            this.getView().invokeOperation("refresh");
+        } else if (!"checkprogress".equals(actionId) && !"dataPreDeal".equals(actionId)) {
+            if ("donothing_writein".equals(actionId)) {
+                this.getView().invokeOperation("refresh");
+            } else if ("donothing_unwritein".equals(actionId)) {
+                this.getView().invokeOperation("refresh");
+            }
+        } else {
+            this.getView().invokeOperation("refresh");
+        }
+    }
+
+    private void openProgressPage(int totalCount, Long importTaskId, String progressType, String closeCalBackId, String caption, String verifyId) {
+        FormShowParameter formShowParameter = new FormShowParameter();
+        formShowParameter.setFormId("hsas_datacheckprogress");
+        formShowParameter.getOpenStyle().setShowType(ShowType.Modal);
+        formShowParameter.setCaption(caption);
+        formShowParameter.setCustomParam("importTaskId", importTaskId);
+        formShowParameter.setCustomParam("totalCount", totalCount);
+        formShowParameter.setCustomParam("verifyId", verifyId);
+        formShowParameter.setCustomParam("startTime", SWCDateTimeUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
+        formShowParameter.setCustomParam("progressType", progressType);
+        formShowParameter.setCloseCallBack(new CloseCallBack(this, closeCalBackId));
+        this.getView().showForm(formShowParameter);
+    }
+}

+ 422 - 0
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/formplugin/web/tp/SinsurTemplateEdit.java

@@ -0,0 +1,422 @@
+package nckd.jxccl.sit.hcsi.formplugin.web.tp;
+
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.dataentity.resource.ResManager;
+import kd.bos.entity.datamodel.AbstractFormDataModel;
+import kd.bos.entity.datamodel.IDataModel;
+import kd.bos.entity.datamodel.TableValueSetter;
+import kd.bos.entity.datamodel.events.PropertyChangedArgs;
+import kd.bos.form.*;
+import kd.bos.form.control.EntryGrid;
+import kd.bos.form.events.BeforeDoOperationEventArgs;
+import kd.bos.form.events.ClosedCallBackEvent;
+import kd.bos.form.events.MessageBoxClosedEvent;
+import kd.bos.form.operate.FormOperate;
+import kd.bos.form.plugin.AbstractFormPlugin;
+import kd.bos.orm.util.CollectionUtils;
+import kd.sdk.plugin.Plugin;
+import kd.swc.hsas.common.enums.PresetItemEnum;
+import kd.swc.hsbp.common.util.SWCStringUtils;
+import nckd.jxccl.sit.hcsi.formplugin.web.tp.enums.SinsurPresetItemEnum;
+import nckd.jxccl.sit.hcsi.formplugin.web.tp.helper.SinsurTemplateHelper;
+
+import java.util.*;
+
+/**
+ * Tyx 2025-10-16
+ * 外部系统数据导入模板表单插件 : nckd_sinsurtpl
+ */
+public class SinsurTemplateEdit extends AbstractFormPlugin implements Plugin {
+
+    public SinsurTemplateEdit() {
+        
+    }
+
+    @Override
+    public void afterCreateNewData(EventObject e) {
+        super.afterCreateNewData(e);
+        // 添加预置数据:
+        createPresetItemData();
+        //this.getModel().setValue("number", "1");
+    }
+
+    @Override
+    public void afterBindData(EventObject e) {
+        super.afterBindData(e);
+        this.loadMatchRelationInfo();
+    }
+
+
+    public void beforeDoOperation(BeforeDoOperationEventArgs args) {
+        super.beforeDoOperation(args);
+        FormOperate formOperate = (FormOperate)args.getSource();
+        String opKey = formOperate.getOperateKey();
+        int[] selectRowIndexs = ((EntryGrid)this.getControl("nckd_sinsurtplentry")).getSelectRows();
+        int[] rowIndexs;
+        switch (opKey) {
+            case "donothing_addmaprelation":
+                this.openAddMatchRelationPage();
+                break;
+            case "donothing_deleteentry":
+                if (selectRowIndexs.length == 0) {
+                    this.getView().showTipNotification(ResManager.loadKDString("请选择要执行的数据。", "MigrationTemplateEdit_4", "swc-hsas-formplugin", new Object[0]));
+                } else {
+                    rowIndexs = this.getChangeableRowIndexs(selectRowIndexs);
+                    if (rowIndexs.length < selectRowIndexs.length) {
+                        this.getView().showTipNotification(ResManager.loadKDString("预置字段不可删除。", "MigrationTemplateEdit_0", "swc-hsas-formplugin", new Object[0]));
+                    }
+
+                    this.deleteEntry(rowIndexs);
+                }
+                break;
+            case "donothing_moveup":
+                if (selectRowIndexs.length == 0) {
+                    this.getView().showTipNotification(ResManager.loadKDString("请选中一行再进行操作。", "MigrationTemplateEdit_3", "swc-hsas-formplugin", new Object[0]));
+                } else {
+                    rowIndexs = this.getChangeableRowIndexs(selectRowIndexs);
+                    this.moveUpEntry(rowIndexs);
+                }
+                break;
+            case "donothing_movedown":
+                if (selectRowIndexs.length == 0) {
+                    this.getView().showTipNotification(ResManager.loadKDString("请选中一行再进行操作。", "MigrationTemplateEdit_3", "swc-hsas-formplugin", new Object[0]));
+                } else {
+                    rowIndexs = this.getChangeableRowIndexs(selectRowIndexs);
+                    this.moveDownEntry(rowIndexs);
+                }
+                break;
+            case "save":
+                ((FormOperate)args.getSource()).getOption().setVariableValue("save", Boolean.TRUE.toString());
+                break;
+            case "submit":
+                ((FormOperate)args.getSource()).getOption().setVariableValue("save", Boolean.TRUE.toString());
+                ((FormOperate)args.getSource()).getOption().setVariableValue("isList", Boolean.FALSE.toString());
+        }
+
+    }
+
+    public void propertyChanged(PropertyChangedArgs e) {
+        switch (e.getProperty().getName()) {
+            case "org":
+                this.clearUnPresetItemData();
+                this.createPresetItemData();
+                this.getView().updateView("nckd_sinsurtplentry");
+                break;
+//            case "nckd_startline":
+//                this.createPresetItemData();
+//                this.getView().updateView("nckd_sinsurtplentry");
+        }
+
+    }
+
+    public void closedCallBack(ClosedCallBackEvent evt) {
+        super.closedCallBack(evt);
+        switch (evt.getActionId()) {
+            case "donothing_addmaprelation":
+                this.addMatchRelationCloseEvent((DynamicObjectCollection)evt.getReturnData());
+            default:
+        }
+    }
+
+    public void confirmCallBack(MessageBoxClosedEvent messageBoxClosedEvent) {
+        super.confirmCallBack(messageBoxClosedEvent);
+        switch (messageBoxClosedEvent.getCallBackId()) {
+            case "write_task_type_change":
+                if (MessageBoxResult.Yes.equals(messageBoxClosedEvent.getResult())) {
+                    this.getPageCache().remove("write_task_type_change");
+                    this.changePresetItemData();
+                } else {
+                    this.getModel().setValue("writetasktype", this.getPageCache().get("write_task_type_change_old"));
+                }
+
+                this.getPageCache().remove("write_task_type_change_old");
+            default:
+        }
+    }
+
+    private void clearUnPresetItemData() {
+        int row = this.getModel().getEntryEntity("nckd_sinsurtplentry").getRowCount();
+        int[] allRowIndex = new int[row];
+
+        for(int index = 0; index < row; allRowIndex[index] = index++) {
+
+        }
+
+        this.deleteEntry(allRowIndex);
+    }
+    private TableValueSetter createTableValueSetter() {
+        TableValueSetter setter = new TableValueSetter(new String[0]);
+        setter.addField("nckd_matchcolumn", new Object[0]);
+        setter.addField("nckd_itemtype", new Object[0]);
+        setter.addField("nckd_itemid", new Object[0]);
+        setter.addField("nckd_salaryitem", new Object[0]);
+        setter.addField("nckd_bizitem", new Object[0]);
+        setter.addField("nckd_supportitem", new Object[0]);
+        setter.addField("nckd_fetchitem", new Object[0]);
+        setter.addField("nckd_itemnumber", new Object[0]);
+        setter.addField("nckd_itemname", new Object[0]);
+        setter.addField("nckd_datatype", new Object[0]);
+        setter.addField("nckd_comment", new Object[0]);
+        setter.addField("nckd_uniquecode", new Object[0]);
+        return setter;
+    }
+
+    private int[] getChangeableRowIndexs(int[] selectRowIndexs) {
+        int presetDataSize = this.getPresetDataSize();
+        List<Integer> selectRowIndexList = new ArrayList(selectRowIndexs.length);
+        int[] var4 = selectRowIndexs;
+        int var5 = selectRowIndexs.length;
+
+        for(int var6 = 0; var6 < var5; ++var6) {
+            int index = var4[var6];
+            if (index >= presetDataSize) {
+                selectRowIndexList.add(index);
+            }
+        }
+
+        selectRowIndexs = new int[selectRowIndexList.size()];
+
+        for(int index = 0; index < selectRowIndexList.size(); ++index) {
+            selectRowIndexs[index] = (Integer)selectRowIndexList.get(index);
+        }
+
+        return selectRowIndexs;
+    }
+
+    private void deleteEntry(int[] rowIndexs) {
+        if (rowIndexs.length != 0) {
+            this.getModel().deleteEntryRows("nckd_sinsurtplentry", rowIndexs);
+        }
+    }
+
+    private void moveUpEntry(int[] rowIndexs) {
+        if (rowIndexs.length != 0) {
+            int presetDataSize = this.getPresetDataSize();
+            if (rowIndexs[0] == presetDataSize) {
+                int continueIndex;
+                for(continueIndex = 0; continueIndex + 1 < rowIndexs.length && rowIndexs[continueIndex + 1] == rowIndexs[continueIndex] + 1; ++continueIndex) {
+                }
+
+                List<Integer> filterIndexList = new ArrayList(rowIndexs.length);
+
+                int index;
+                for(index = continueIndex + 1; index < rowIndexs.length; ++index) {
+                    filterIndexList.add(rowIndexs[index]);
+                }
+
+                rowIndexs = new int[filterIndexList.size()];
+
+                for(index = 0; index < filterIndexList.size(); ++index) {
+                    rowIndexs[index] = (Integer)filterIndexList.get(index);
+                }
+            }
+
+            if (rowIndexs.length != 0) {
+                this.getModel().moveEntryRowsUp("nckd_sinsurtplentry", rowIndexs);
+            }
+        }
+    }
+
+    private void moveDownEntry(int[] rowIndexs) {
+        if (rowIndexs.length != 0) {
+            this.getModel().moveEntryRowsDown("nckd_sinsurtplentry", rowIndexs);
+        }
+    }
+
+    private void openAddMatchRelationPage() {
+        if (this.getModel().getValue("org") == null) {
+            this.getView().showTipNotification(ResManager.loadKDString("请先选择社保公积金管理组织后,再添加映射关系。", "MigrationTemplateEdit_1", "swc-hsas-formplugin", new Object[0]));
+        } else {
+            FormShowParameter showParameter = new FormShowParameter();
+            showParameter.setFormId("nckd_sititemselect");
+            //showParameter.setFormId("hsas_calitemselect");
+            showParameter.getOpenStyle().setShowType(ShowType.Modal);
+            showParameter.setParentPageId(this.getView().getPageId());
+            showParameter.setCaption(ResManager.loadKDString("添加项目", "MigrationTemplateEdit_2", "swc-hsas-formplugin", new Object[0]));
+            showParameter.setCloseCallBack(new CloseCallBack(this, "donothing_addmaprelation"));
+            this.getView().showForm(showParameter);
+        }
+    }
+
+    public void addMatchRelationCloseEvent(DynamicObjectCollection itemDatas) {
+        if (itemDatas != null && itemDatas.size() != 0) {
+            int presetDataSize = this.getPresetDataSize();
+            DynamicObjectCollection entryDatas = this.getModel().getEntryEntity("nckd_sinsurtplentry");
+            Map<Long, Map<String, Object>> existItemDataMap = new HashMap(entryDatas.size() - presetDataSize);
+            int[] deleteRowIndex = new int[entryDatas.size() - presetDataSize];
+
+            for(int index = presetDataSize; index < entryDatas.size(); deleteRowIndex[index - presetDataSize] = index++) {
+                DynamicObject entryData = (DynamicObject)entryDatas.get(index);
+                Map<String, Object> existItemData = new HashMap(2);
+                existItemData.put("nckd_matchcolumn", entryData.getString("nckd_matchcolumn"));
+                existItemData.put("nckd_comment", entryData.getString("nckd_comment"));
+                existItemDataMap.put(entryData.getLong("nckd_itemid"), existItemData);
+            }
+
+            if (deleteRowIndex.length != 0) {
+                this.getModel().deleteEntryRows("nckd_sinsurtplentry", deleteRowIndex);
+            }
+
+            Map<String, Map<String, Object>> itemParamMap = SinsurTemplateHelper.analyzeItemDatas(itemDatas, existItemDataMap);
+            AbstractFormDataModel model = (AbstractFormDataModel)this.getModel();
+            model.beginInit();
+            TableValueSetter tableValueSetter = this.createTableValueSetter();
+            Iterator it = itemDatas.iterator();
+
+            while(it.hasNext()) {
+                DynamicObject dataObj = (DynamicObject)it.next();
+                String unicode = dataObj.getString("nckd_itemnumber");
+                Map<String, Object> itemParam = (Map)itemParamMap.get(unicode);
+                if (itemParam != null) {
+                    Map<String, Object> existItemData = (Map)existItemDataMap.get(itemParam.get("id"));
+                    String common;
+                    String matchColumn;
+                    if (existItemData != null) {
+                        common = (String)existItemData.get("nckd_comment");
+                        matchColumn = (String)existItemData.get("nckd_matchcolumn");
+                    } else {
+                        common = (String)itemParam.get("nckd_comment");
+                        matchColumn = "";
+                    }
+
+                    String itemType = (String)itemParam.get("itemType");
+                    Long itemId = (Long)itemParam.get("id");
+                    if ("1".equals(itemType)) {
+                        tableValueSetter.addRow(new Object[]{matchColumn, itemParam.get("itemType"), itemId, itemId, 0L, 0L, 0L, dataObj.get("nckd_itemnumber"), dataObj.get("nckd_itemname"), itemParam.get("dataTypeId"), common, unicode});
+                    } else if ("2".equals(itemType)) {
+                        tableValueSetter.addRow(new Object[]{matchColumn, itemParam.get("itemType"), itemId, 0L, 0L, itemId, 0L, dataObj.get("nckd_itemnumber"), dataObj.get("nckd_itemname"), itemParam.get("dataTypeId"), common, unicode});
+                    } else if ("4".equals(itemType)) {
+                        tableValueSetter.addRow(new Object[]{matchColumn, itemParam.get("itemType"), itemId, 0L, 0L, 0L, itemId, dataObj.get("nckd_itemnumber"), dataObj.get("nckd_itemname"), itemParam.get("dataTypeId"), common, unicode});
+                    } else if ("3".equals(itemType)) {
+                        tableValueSetter.addRow(new Object[]{matchColumn, itemParam.get("itemType"), itemId, 0L, itemId, 0L, 0L, dataObj.get("nckd_itemnumber"), dataObj.get("nckd_itemname"), itemParam.get("dataTypeId"), common, unicode});
+                    }
+                }
+            }
+
+            model.batchCreateNewEntryRow("nckd_sinsurtplentry", tableValueSetter);
+            model.endInit();
+            this.getView().updateView("nckd_sinsurtplentry");
+        }
+    }
+
+    private void loadMatchRelationInfo() {
+        DynamicObjectCollection entryDatas = this.getModel().getEntryEntity("nckd_sinsurtplentry");
+        int presetDataSize = this.getPresetDataSize();
+        if (!CollectionUtils.isEmpty(entryDatas)) {
+            Map<String, Map<String, Object>> itemParamMap = SinsurTemplateHelper.analyzeMatchItem(entryDatas);
+            IDataModel model = this.getModel();
+
+            int index;
+            DynamicObject entry;
+            for(index = 0; index < presetDataSize; ++index) {
+                entry = (DynamicObject)entryDatas.get(index);
+                Long itemId = entry.getLong("nckd_itemid");
+                PresetItemEnum presetItemEnum = SinsurTemplateHelper.getPresetItemEnum(itemId);
+                if (presetItemEnum != null) {
+                    model.setValue("nckd_itemnumber", '-', index);
+                    model.setValue("nckd_itemnumber", presetItemEnum.getItemName(), index);
+                    model.setValue("nckd_itemnumber", "", index);
+                }
+            }
+
+            for(index = presetDataSize; index < entryDatas.size(); ++index) {
+                entry = (DynamicObject)entryDatas.get(index);
+                String itemType = entry.getString("nckd_itemtype");
+                Long itemId = entry.getLong("nckd_itemid");
+                Map<String, Object> itemParam = (Map)itemParamMap.get(itemType + '-' + itemId);
+                if (itemParam != null) {
+                    model.setValue("nckd_itemnumber", itemParam.get("nckd_itemnumber"), index);
+                    model.setValue("nckd_itemnumber", itemParam.get("nckd_itemnumber"), index);
+                    model.setValue("nckd_itemnumber", itemParam.get("nckd_itemnumber"), index);
+                }
+            }
+
+            this.getView().updateView("nckd_sinsurtplentry");
+            this.getModel().setDataChanged(false);
+        }
+    }
+
+    private int getPresetDataSize() {
+        DynamicObjectCollection entryDatas = this.getModel().getEntryEntity("nckd_sinsurtplentry");
+
+        int index;
+        for(index = 0; index < entryDatas.size(); ++index) {
+            DynamicObject entry = (DynamicObject)entryDatas.get(index);
+            if (!SWCStringUtils.equals(entry.getString("nckd_itemtype"), "0")) {
+                break;
+            }
+        }
+
+        return index;
+    }
+
+    private void createPresetItemData() {
+        AbstractFormDataModel model = (AbstractFormDataModel) this.getModel();
+        model.beginInit();
+        TableValueSetter tableValueSetter = this.createTableValueSetter();
+        List<SinsurPresetItemEnum> presetItemEnumsList = SinsurTemplateHelper.getPresetItemEnumList();
+        if (!CollectionUtils.isEmpty(presetItemEnumsList)) {
+            for(SinsurPresetItemEnum presetItemEnum : presetItemEnumsList) {
+                tableValueSetter.addRow(new Object[]{presetItemEnum.getMatchColumn(), "0", presetItemEnum.getItemId(), 0L, 0L, 0L, 0L, '-', presetItemEnum.getItemName(), presetItemEnum.getDataTypeId(), presetItemEnum.getComment().getLocaleString(), ""});
+            }
+        }
+        model.batchCreateNewEntryRow("nckd_sinsurtplentry", tableValueSetter);
+        model.endInit();
+        this.getView().updateView("nckd_sinsurtplentry");
+    }
+
+    private void changePresetItemData() {
+//        DynamicObjectCollection entryDatas = this.getModel().getEntryEntity("nckd_sinsurtplentry");
+//        Iterator<DynamicObject> iterator = entryDatas.iterator();
+//
+//        while(iterator.hasNext()) {
+//            DynamicObject next = (DynamicObject)iterator.next();
+//            if (SWCStringUtils.equals(next.getString("nckd_itemtype"), "0")) {
+//                iterator.remove();
+//            }
+//        }
+//
+//        List<DynamicObject> entryList = new ArrayList(entryDatas.size());
+//        entryList.addAll(entryDatas);
+//        this.getModel().deleteEntryData("nckd_sinsurtplentry");
+//        AbstractFormDataModel model = (AbstractFormDataModel)this.getModel();
+//        DynamicObject data = model.getDataEntity();
+//        model.beginInit();
+//        TableValueSetter tableValueSetter = this.createTableValueSetter();
+//        List<PresetItemEnum> presetItemEnumsList = SinsurTemplateHelper.getPresetItemEnumList(data.getString("writetasktype"), data.getBoolean("ismultimeoneperiod"));
+//        if (!CollectionUtils.isEmpty(presetItemEnumsList)) {
+//            Iterator it = presetItemEnumsList.iterator();
+//
+//            while(it.hasNext()) {
+//                PresetItemEnum presetItemEnum = (PresetItemEnum)it.next();
+//                tableValueSetter.addRow(new Object[]{presetItemEnum.getMatchColumn(), "0", presetItemEnum.getItemId(), 0L, 0L, 0L, 0L, '-', presetItemEnum.getItemName(), presetItemEnum.getDataTypeId(), presetItemEnum.getComment().getLocaleString(), ""});
+//            }
+//
+//            it = entryList.iterator();
+//
+//            while(it.hasNext()) {
+//                DynamicObject entryData = (DynamicObject)it.next();
+//                tableValueSetter.addRow(new Object[]{
+//                        entryData.getString("nckd_matchcolumn"),
+//                        entryData.getString("nckd_itemtype"),
+//                        entryData.getLong("nckd_itemid"),
+//                        entryData.getLong("nckd_salaryitem.id"),
+//                        entryData.getLong("nckd_bizitem.id"),
+//                        entryData.getLong("nckd_supportitem.id"),
+//                        entryData.getLong("nckd_fetchitem.id"),
+//                        entryData.getString("nckd_itemnumber"),
+//                        entryData.getString("nckd_itemname"),
+//                        entryData.getLong("nckd_datatype.id"),
+//                        entryData.getString("nckd_comment"),
+//                        entryData.getString("nckd_uniquecode")
+//                });
+//            }
+//
+//            model.batchCreateNewEntryRow("nckd_sinsurtplentry", tableValueSetter);
+//            model.endInit();
+//            this.getView().updateView("nckd_sinsurtplentry");
+//        }
+    }
+    
+}

+ 487 - 0
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/formplugin/web/tp/SitItemSelectAddItemPlugin.java

@@ -0,0 +1,487 @@
+package nckd.jxccl.sit.hcsi.formplugin.web.tp;
+
+import com.kingdee.util.StringUtils;
+import kd.bos.base.AbstractBasePlugIn;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.dataentity.resource.ResManager;
+import kd.bos.dataentity.serialization.SerializationUtils;
+import kd.bos.entity.datamodel.AbstractFormDataModel;
+import kd.bos.entity.datamodel.IDataModel;
+import kd.bos.entity.datamodel.TableValueSetter;
+import kd.bos.entity.tree.TreeNode;
+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.Control;
+import kd.bos.form.control.EntryGrid;
+import kd.bos.form.control.TreeView;
+import kd.bos.form.events.AfterDoOperationEventArgs;
+import kd.bos.form.events.BeforeDoOperationEventArgs;
+import kd.bos.form.events.ClosedCallBackEvent;
+import kd.bos.form.operate.FormOperate;
+import kd.bos.util.CollectionUtils;
+import kd.swc.hsas.business.formula.helper.FormulaDataServiceHelper;
+import kd.swc.hsas.business.formula.helper.FormulaItemOrFuncTreeHelper;
+import kd.swc.hsbp.common.cache.SWCPageCache;
+import kd.swc.hsbp.common.util.SWCObjectUtils;
+import kd.swc.hsbp.common.util.SWCStringUtils;
+import nckd.jxccl.sit.hcsi.formplugin.web.tp.helper.SitItemSelectAddItemServiceHelper;
+
+import java.util.*;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+/**
+ * Tyx 2025-10-17
+ * 结果表内容设置绑定插件 nckd_sititemselect
+ */
+public class SitItemSelectAddItemPlugin extends AbstractBasePlugIn {
+    private static final String BUTTON_CANCEL = "nckd_btncancel";
+    private static final String BUTTON_SAVE = "nckd_btnsave";
+    private static final String ENTRY_SELECT = "nckd_itemselectentry";
+    private static final String TREE_VIEW = "nckd_treeviewap";
+    private static final String FORM_MOVE_TO = "hsas_calitemmoveto";
+    private static final String ITEM_TYPE_II = "II";
+
+    private static final Map<String, String> ITEM_TYPE_MAPPING = new HashMap();
+    private static final Map<String, String> ITEM_CATEGORY_MAPPING =  new HashMap();
+    static {
+        ITEM_TYPE_MAPPING.put("1", ITEM_TYPE_II);
+        ITEM_CATEGORY_MAPPING.put(ITEM_TYPE_II, ITEM_TYPE_II);
+    }
+
+    @Override
+    public void registerListener(EventObject e) {
+        super.registerListener(e);
+        this.addClickListeners(BUTTON_CANCEL, BUTTON_SAVE);
+    }
+
+    @Override
+    public void beforeBindData(EventObject e) {
+        super.beforeBindData(e);
+        long orgId = getOrgId();
+        loadMainPageData();
+        SitItemSelectAddItemServiceHelper helper = new SitItemSelectAddItemServiceHelper();
+        Map<String, Map<String, Map<String, Object>>> dataMap = helper.getAllItemData(orgId);
+        initItemTree(dataMap);
+    }
+
+    private long getOrgId() {
+        return ((DynamicObject)this.getView().getParentView().getModel().getValue("org")).getLong("id");
+    }
+
+    private boolean isNeedAccItem() {
+        IFormView parentView = this.getView().getParentView();
+        return parentView == null || !SWCStringUtils.equals(parentView.getEntityId(), "hsas_migrationtpl");
+    }
+
+    @Override
+    public void beforeDoOperation(BeforeDoOperationEventArgs args) {
+        super.beforeDoOperation(args);
+        FormOperate formOperate = (FormOperate)args.getSource();
+        if ("do_moveto".equals(formOperate.getOperateKey())) {
+            openMoveToPage(args);
+        }
+    }
+
+    @Override
+    public void afterDoOperation(AfterDoOperationEventArgs args) {
+        super.afterDoOperation(args);
+        switch (args.getOperateKey()) {
+            case "do_addcolumn":
+                addColumn();
+                break;
+            case "do_removecolumn":
+                removeColumn();
+        }
+    }
+
+    @Override
+    public void click(EventObject evt) {
+        super.click(evt);
+        Control source = (Control)evt.getSource();
+        switch (source.getKey()) {
+            case BUTTON_CANCEL:
+                this.getView().close();
+                break;
+            case BUTTON_SAVE:
+                btnOkClickEvent();
+        }
+    }
+
+    @Override
+    public void closedCallBack(ClosedCallBackEvent evt) {
+        if ("movetoclosed".equals(evt.getActionId())) {
+            moveToClosedEvent(evt);
+        }
+    }
+
+    private void checkSelectedTreeNode(TreeView treeView, List<TreeNode> nodeList) {
+        DynamicObjectCollection selectDatas = this.getView().getModel().getEntryEntity("nckd_itemselectentry");
+        Set<String> uniqueCodeSet = selectDatas.stream()
+                .map(selectData -> selectData.getString("nckd_treenodeid"))
+                .collect(Collectors.toSet());
+
+        List<TreeNode> checkNodeList = FormulaItemOrFuncTreeHelper.getCheckTreeNodeList(nodeList, uniqueCodeSet);
+        if (CollectionUtils.isNotEmpty(checkNodeList)) {
+            treeView.checkNodes(checkNodeList);
+        }
+    }
+
+    public void loadMainPageData() {
+        loadMainPageDataFromMigrationTempate();
+    }
+
+    private boolean isMigrationTemplate() {
+        return SWCStringUtils.equals(this.getView().getParentView().getEntityId(), "hsas_migrationtpl");
+    }
+
+    private void loadMainPageDataFromResultList() {
+        IFormView parentView = this.getView().getParentView();
+        DynamicObjectCollection resultContentDatas = parentView.getModel().getEntryEntity("resultlist");
+        if (CollectionUtils.isEmpty(resultContentDatas)) {
+            return;
+        }
+
+        IDataModel model = this.getModel();
+        for (DynamicObject dataObj : resultContentDatas) {
+            int detailIndex = model.createNewEntryRow(ENTRY_SELECT);
+            String itemCategory = normalizeItemCategory((String)dataObj.get("itemcategory"));
+
+            populateEntryData(model, dataObj, itemCategory, detailIndex);
+        }
+        this.getView().updateView(ENTRY_SELECT);
+    }
+
+    private String normalizeItemCategory(String itemCategory) {
+        return ITEM_CATEGORY_MAPPING.getOrDefault(itemCategory, itemCategory);
+    }
+
+    private void loadMainPageDataFromMigrationTempate() {
+        DynamicObjectCollection matchRelationDatas = this.getView().getParentView().getModel()
+                .getEntryEntity("nckd_sinsurtplentry");
+        if (CollectionUtils.isEmpty(matchRelationDatas)) {
+            return;
+        }
+
+        IDataModel model = this.getModel();
+        for (DynamicObject matchRelationData : matchRelationDatas) {
+            String itemType = matchRelationData.getString("nckd_itemtype");
+            String itemCategory = ITEM_TYPE_MAPPING.get(itemType);
+
+            if (itemCategory != null) {
+                int detailIndex = model.createNewEntryRow(ENTRY_SELECT);
+                populateEntryData(model, matchRelationData, itemCategory, detailIndex);
+            }
+        }
+        this.getView().updateView(ENTRY_SELECT);
+    }
+
+    private void populateEntryData(IDataModel model, DynamicObject sourceData, String itemCategory, int detailIndex) {
+        model.setValue("nckd_itemnumber", sourceData.getString("nckd_itemnumber"), detailIndex);
+        model.setValue("nckd_itemcategory", itemCategory, detailIndex);
+        model.setValue("nckd_itemname", sourceData.getString("nckd_itemname"), detailIndex);
+        model.setValue("nckd_itemunicodeid", sourceData.getString("nckd_uniquecode"), detailIndex);
+        model.setValue("nckd_treenodeid", sourceData.getString("nckd_itemid"), detailIndex);
+    }
+
+    public void btnOkClickEvent() {
+        DynamicObjectCollection entryDatas = this.getModel().getEntryEntity(ENTRY_SELECT);
+        if (CollectionUtils.isEmpty(entryDatas)) {
+            this.getView().showTipNotification(ResManager.loadKDString("请先添加项目。", "CalResultTplAddItemPlugin_4", "swc-hsas-formplugin", new Object[0]));
+            return;
+        }
+        this.getView().returnDataToParent(entryDatas);
+        this.getView().close();
+    }
+
+    public void moveToClosedEvent(ClosedCallBackEvent evt) {
+        Map<String, Object> returnData = (Map)evt.getReturnData();
+        if (SWCObjectUtils.isEmpty(returnData) || !"ok".equals(returnData.get("clickStatus"))) {
+            return;
+        }
+
+        EntryGrid entryGrid = (EntryGrid)this.getView().getControl(ENTRY_SELECT);
+        int[] rows = entryGrid.getSelectRows();
+        int oldRow = rows[0];
+        int newRow = (Integer)returnData.get("rownumber") - 1;
+
+        IDataModel model = this.getModel();
+        DynamicObjectCollection datas = model.getEntryEntity(ENTRY_SELECT);
+        newRow = Math.min(newRow, datas.size() - 1);
+
+        if (oldRow != newRow) {
+            DynamicObject oldObj = (DynamicObject)datas.get(oldRow);
+            model.deleteEntryRow(ENTRY_SELECT, oldRow);
+            model.createNewEntryRow(ENTRY_SELECT, newRow, oldObj);
+            entryGrid.selectRows(newRow, true);
+        }
+    }
+
+    private void initItemTree(Map<String, Map<String, Map<String, Object>>> dataMap) {
+        TreeView treeView = (TreeView)this.getView().getControl(TREE_VIEW);
+        List<TreeNode> nodeList = buildTreeNodeList(dataMap);
+
+        treeView.deleteAllNodes();
+        treeView.addNodes(nodeList);
+
+        updatePageCache(nodeList, dataMap);
+        checkSelectedTreeNode(treeView, nodeList);
+    }
+
+    private List<TreeNode> buildTreeNodeList(Map<String, Map<String, Map<String, Object>>> dataMap) {
+        List<TreeNode> list = new ArrayList<>();
+        list.addAll(SitItemSelectAddItemServiceHelper.loadInsuranceItemChildNode(null, false, dataMap));
+        return list;
+    }
+
+    private void updatePageCache(List<TreeNode> nodeList, Map<String, Map<String, Map<String, Object>>> dataMap) {
+        SWCPageCache pageCache = new SWCPageCache(this.getView());
+        Map<String, TreeNode> treeNodeMap = nodeList.stream()
+                .collect(Collectors.toMap(TreeNode::getId, Function.identity()));
+
+        pageCache.put("tree", SerializationUtils.serializeToBase64(treeNodeMap));
+        pageCache.put("allItemData", dataMap);
+        pageCache.put("simpleAllItemData", rebuildData(dataMap));
+    }
+
+    private Map<String, Map<String, String>> rebuildData(Map<String, Map<String, Map<String, Object>>> dataMap) {
+        if (dataMap != null && dataMap.size() != 0) {
+            return Collections.emptyMap();
+        }
+
+        return dataMap.entrySet().stream()
+                .collect(Collectors.toMap(
+                        Map.Entry::getKey,
+                        entry -> entry.getValue().entrySet().stream()
+                                .collect(Collectors.toMap(
+                                        Map.Entry::getKey,
+                                        innerEntry -> (String)innerEntry.getValue().get("uniquecode")
+                                ))
+                ));
+    }
+
+
+    public void addColumn() {
+        TreeView treeView = (TreeView)this.getView().getControl(TREE_VIEW);
+        List<String> selectNodeIds = treeView.getTreeState().getCheckedNodeIds();
+        if (CollectionUtils.isEmpty(selectNodeIds)) {
+            this.getView().showTipNotification(ResManager.loadKDString("请先选中数据。", "CalResultTplAddItemPlugin_0", "swc-hsas-formplugin", new Object[0]));
+            return;
+        }
+
+        SWCPageCache pageCache = new SWCPageCache(this.getView());
+        Map<String, TreeNode> nodeMap = getNodeMapFromCache(pageCache);
+        Map<String, Map<String, Map<String, Object>>> dataMap = (Map)pageCache.get("allItemData", Map.class);
+
+        AbstractFormDataModel model = (AbstractFormDataModel)this.getModel();
+        model.beginInit();
+
+        try {
+            TableValueSetter vs = createTableValueSetter();
+            List<TreeNode> checkNodeList = new ArrayList<>(selectNodeIds.size());
+
+            for (String selectNodeId : selectNodeIds) {
+                TreeNode treeNode = getTreeNodeByTreeId(nodeMap, selectNodeId);
+//                TreeNode treeNode = nodeMap.get(selectNodeId);
+                if (!isValidNode(treeNode, selectNodeId)) {
+                    continue;
+                }
+
+                String itemCategory = getItemCategory(treeNode);
+                String itemNum = getItemNumber(dataMap, itemCategory, treeNode.getText(), treeNode);
+                String itemUnicodeId = getItemUnicodeId(treeNode.getId(), treeNode.getText());
+
+                vs.addRow(new Object[]{itemCategory, itemNum, treeNode.getText(), itemUnicodeId, treeNode.getId()});
+                checkNodeList.add(treeNode);
+            }
+
+            model.batchCreateNewEntryRow(ENTRY_SELECT, vs);
+            this.getView().updateView(ENTRY_SELECT);
+
+            if (CollectionUtils.isNotEmpty(checkNodeList)) {
+                treeView.checkNodes(checkNodeList);
+            }
+        } finally {
+            model.endInit();
+        }
+    }
+
+    private Map<String, TreeNode> getNodeMapFromCache(SWCPageCache pageCache) {
+        String cacheTreeNodeStr = (String)pageCache.get("tree", String.class);
+        return (Map)SerializationUtils.deSerializeFromBase64(cacheTreeNodeStr);
+    }
+
+    private TableValueSetter createTableValueSetter() {
+        TableValueSetter vs = new TableValueSetter(new String[0]);
+        vs.addField("nckd_itemcategory", new Object[0]);
+        vs.addField("nckd_itemnumber", new Object[0]);
+        vs.addField("nckd_itemname", new Object[0]);
+        vs.addField("nckd_itemunicodeid", new Object[0]);
+        vs.addField("nckd_treenodeid", new Object[0]);
+        return vs;
+    }
+
+    private boolean isValidNode(TreeNode treeNode, String selectNodeId) {
+        if (treeNode == null || SWCStringUtils.isEmpty(treeNode.getId())) {
+            return false;
+        }
+
+        String treeNodeId = treeNode.getId();
+        if (treeNodeId.equals("0_@_BS") || treeNodeId.equals("1_@_BS")) {
+            return false;
+        }
+
+        return !isExistTreeNode(selectNodeId);
+    }
+
+    private String getItemCategory(TreeNode treeNode) {
+//        String treeNodeId = treeNode.getId();
+//        String itemCategory = treeNodeId.substring(0, treeNodeId.indexOf('_'));
+//        String itemCategory = ITEM_TYPE_II;
+        return normalizeItemCategory(ITEM_TYPE_II);
+    }
+
+    private void removeCheckNode(int[] rows) {
+        DynamicObjectCollection selectDatas = this.getView().getModel().getEntryEntity(ENTRY_SELECT);
+        SWCPageCache pageCache = new SWCPageCache(this.getView());
+        Map<String, TreeNode> nodeMap = getNodeMapFromCache(pageCache);
+
+        List<String> removeCheckNodeList = Arrays.stream(rows)
+                .mapToObj(index -> {
+                    DynamicObject selectData = (DynamicObject)selectDatas.get(index);
+                    return nodeMap.get(selectData.getString("nckd_itemunicodeid"));
+                })
+                .filter(Objects::nonNull)
+                .map(TreeNode::getId)
+                .collect(Collectors.toList());
+
+        TreeView treeView = (TreeView)this.getView().getControl(TREE_VIEW);
+        treeView.uncheckNodes(removeCheckNodeList);
+    }
+
+    private String getItemNumber(Map<String, Map<String, Map<String, Object>>> dataMap, String itemCategory, String treeNodeName, TreeNode treeNode) {
+        String mapKey = getItemMapKey(itemCategory, treeNode);
+        Map<String, Map<String, Object>> itemMap = (Map)dataMap.get(mapKey);
+
+        if (itemMap == null) {
+            return "";
+        }
+
+        Map<String, Object> nameMap = itemMap.get(treeNodeName);
+        if (nameMap != null && nameMap.size() != 0) {
+            String number = (String)nameMap.get("number");
+            return SWCStringUtils.isEmpty(number) ? "" : number;
+        }
+        else {
+            return "";
+        }
+    }
+
+    private String getItemMapKey(String itemCategory, TreeNode treeNode) {
+        switch (itemCategory) {
+            case ITEM_TYPE_II:
+                return "insuranceitemkey";
+            default:
+                return "";
+        }
+    }
+
+    public boolean isExistTreeNode(String selectTreeNodeId) {
+        DynamicObjectCollection itemDatas = this.getModel().getEntryEntity(ENTRY_SELECT);
+        return itemDatas.stream()
+                .anyMatch(itemData -> SWCStringUtils.equals(
+                        itemData.getString("nckd_treenodeid"),
+                        selectTreeNodeId
+                ));
+    }
+
+    public String getItemUnicodeId(String treeNodeId, String treeNodeName) {
+        SWCPageCache pageCache = new SWCPageCache(this.getView());
+        Map<String, Map<String, String>> dataMap = (Map)pageCache.get("simpleAllItemData", Map.class);
+        if (SWCObjectUtils.isEmpty(dataMap)) {
+            return "";
+        }
+
+        return dataMap.values().stream()
+                .map(itemData -> itemData.get(treeNodeName))
+                .filter(uniqueCode -> SWCStringUtils.equals(uniqueCode, treeNodeId))
+                .findFirst()
+                .orElse("");
+    }
+
+    public TreeNode getTreeNodeByTreeId(Map<String, TreeNode> nodeMap, String treeId) {
+        if (nodeMap == null || StringUtils.isEmpty(treeId)) {
+            return null;
+        }
+
+        for (Map.Entry<String, TreeNode> entry : nodeMap.entrySet()) {
+            TreeNode node = entry.getValue();
+            TreeNode result = getSubTreeNode(treeId, node);
+            if (result != null) {
+                return result;
+            }
+        }
+        return null;
+    }
+
+    private TreeNode getSubTreeNode(String treeId, TreeNode node) {
+        if (node == null) {
+            return null;
+        }
+        // 检查当前节点
+        if (treeId.equals(node.getId())) {
+            return node;
+        }
+        // 递归检查子节点
+        if (node.getChildren() != null) {
+            for (TreeNode child : node.getChildren()) {
+                TreeNode result = getSubTreeNode(treeId, child);
+                if (result != null) {
+                    return result;
+                }
+            }
+        }
+        return null;
+    }
+
+    public void removeColumn() {
+        EntryGrid entryGrid = (EntryGrid)this.getView().getControl(ENTRY_SELECT);
+        int[] rows = entryGrid.getSelectRows();
+
+        if (rows == null || rows.length == 0) {
+            this.getView().showTipNotification(ResManager.loadKDString("请选中一行再进行操作。", "CalResultTplAddItemPlugin_1", "swc-hsas-formplugin", new Object[0]));
+            return;
+        }
+
+        removeCheckNode(rows);
+        this.getModel().deleteEntryRows(ENTRY_SELECT, rows);
+    }
+
+    public void openMoveToPage(BeforeDoOperationEventArgs args) {
+        EntryGrid entryGrid = (EntryGrid)this.getView().getControl(ENTRY_SELECT);
+        int[] rows = entryGrid.getSelectRows();
+
+        if (rows == null || rows.length == 0) {
+            this.getView().showTipNotification(ResManager.loadKDString("请选择要执行的数据。", "CalResultTplAddItemPlugin_2", "swc-hsas-formplugin", new Object[0]));
+            args.setCancel(true);
+            return;
+        }
+
+        if (rows.length != 1) {
+            this.getView().showTipNotification(ResManager.loadKDString("只能选择一条记录。", "CalResultTplAddItemPlugin_3", "swc-hsas-formplugin", new Object[0]));
+            args.setCancel(true);
+            return;
+        }
+
+        FormShowParameter showParameter = new FormShowParameter();
+        showParameter.setFormId(FORM_MOVE_TO);
+        showParameter.getOpenStyle().setShowType(ShowType.Modal);
+        showParameter.setParentPageId(this.getView().getPageId());
+        showParameter.setCaption(ResManager.loadKDString("移动到", "CalResultTplAddItemPlugin_5", "swc-hsas-formplugin", new Object[0]));
+        showParameter.setCloseCallBack(new CloseCallBack(this, "movetoclosed"));
+        this.getView().showForm(showParameter);
+    }
+}

+ 122 - 0
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/formplugin/web/tp/SitItemSelectItemEntryPlugin.java

@@ -0,0 +1,122 @@
+package nckd.jxccl.sit.hcsi.formplugin.web.tp;
+
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.dataentity.resource.ResManager;
+import kd.bos.form.control.EntryGrid;
+import kd.bos.form.control.Search;
+import kd.bos.form.control.events.SearchEnterEvent;
+import kd.bos.form.control.events.SearchEnterListener;
+import kd.bos.form.plugin.AbstractFormPlugin;
+import kd.sdk.plugin.Plugin;
+import kd.swc.hsbp.common.util.SWCObjectUtils;
+import kd.swc.hsbp.common.util.SWCStringUtils;
+
+import java.util.ArrayList;
+import java.util.EventObject;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Tyx 2025-10-17
+ * 结果表内容选择右表搜索插件 nckd_sititemselect
+ */
+public class SitItemSelectItemEntryPlugin extends AbstractFormPlugin implements SearchEnterListener {
+
+    public void registerListener(EventObject e) {
+        super.registerListener(e);
+        Search search = (Search)this.getView().getControl("columnsearchap");
+        search.addEnterListener(this);
+    }
+
+
+    @Override
+    public void search(SearchEnterEvent searchEnterEvent) {
+        String searchText = searchEnterEvent.getText();
+        if (SWCStringUtils.isEmpty(searchText)) {
+            return;
+        }
+
+        DynamicObjectCollection entryDatas = this.getModel().getEntryEntity("itemselectentry");
+        if (SWCObjectUtils.isEmpty(entryDatas)) {
+            return;
+        }
+
+        EntryGrid grid = (EntryGrid) this.getView().getControl("itemselectentry");
+        int[] selectRows = grid.getSelectRows();
+        List<Integer> matchLine = this.getMatchColumn(entryDatas, searchText);
+
+        if (matchLine.isEmpty()) {
+            this.getView().showTipNotification(ResManager.loadKDString("搜索已完成,未找到搜索项。",
+                    "CalResultTplItemTreePlugin_0", "swc-hsas-formplugin", new Object[0]));
+            return;
+        }
+
+        if (selectRows.length <= 1) {
+            handleSingleSelection(grid, selectRows, matchLine);
+        } else {
+            grid.selectRows(matchLine.get(0), true);
+        }
+    }
+
+    private void handleSingleSelection(EntryGrid grid, int[] selectRows, List<Integer> matchLine) {
+        if (matchLine.size() == 1) {
+            grid.selectRows(matchLine.get(0), true);
+            return;
+        }
+
+        if (selectRows.length == 0 || !isMatch(selectRows, matchLine)) {
+            grid.selectRows(matchLine.get(0), true);
+            return;
+        }
+
+        int currentRow = selectRows[0];
+        int firstMatch = matchLine.get(0);
+        int lastMatch = matchLine.get(matchLine.size() - 1);
+
+        if (currentRow == firstMatch) {
+            grid.selectRows(matchLine.get(1), true);
+        } else if (currentRow == lastMatch) {
+            grid.selectRows(firstMatch, true);
+        } else {
+            selectNextMatch(grid, currentRow, matchLine);
+        }
+    }
+
+    private void selectNextMatch(EntryGrid grid, int currentRow, List<Integer> matchLine) {
+        for (int i = 0; i < matchLine.size(); i++) {
+            if (matchLine.get(i) == currentRow) {
+                grid.selectRows(matchLine.get(i + 1), true);
+                break;
+            }
+        }
+    }
+
+    public boolean isMatch(int[] selectRows, List<Integer> matchLine) {
+        if (selectRows == null || selectRows.length == 0) {
+            return false;
+        }
+        return matchLine.contains(selectRows[0]);
+    }
+
+    public boolean isMatch(int i, List<Integer> matchLine) {
+        return matchLine.contains(i);
+    }
+
+    public List<Integer> getMatchColumn(DynamicObjectCollection entryDatas, String searchText) {
+        List<Integer> matchLine = new ArrayList(10);
+        int size = entryDatas.size();
+
+        for(int i = 0; i < size; ++i) {
+            DynamicObject dataObj = (DynamicObject)entryDatas.get(i);
+            String itemName = dataObj.getString("itemname");
+            String itemNumber = dataObj.getString("itemnumber");
+            if (itemName.contains(searchText) || itemNumber.contains(searchText)) {
+                matchLine.add(i);
+            }
+        }
+
+        return matchLine;
+    }
+
+}

+ 240 - 0
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/formplugin/web/tp/SitItemSelectTreePlugin.java

@@ -0,0 +1,240 @@
+package nckd.jxccl.sit.hcsi.formplugin.web.tp;
+
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.dataentity.resource.ResManager;
+import kd.bos.dataentity.utils.ObjectUtils;
+import kd.bos.entity.tree.TreeNode;
+import kd.bos.form.control.Search;
+import kd.bos.form.control.TreeView;
+import kd.bos.form.control.events.SearchEnterEvent;
+import kd.bos.form.control.events.SearchEnterListener;
+import kd.bos.form.plugin.AbstractFormPlugin;
+import kd.swc.hsas.business.formula.helper.FormulaDataServiceHelper;
+import kd.swc.hsas.business.formula.helper.FormulaItemOrFuncTreeHelper;
+import kd.swc.hsbp.business.servicehelper.SWCSalaryParameterServiceHelper;
+import kd.swc.hsbp.common.cache.SWCPageCache;
+import kd.swc.hsbp.common.constants.WtcInteCfgConstants;
+import kd.swc.hsbp.common.util.SWCStringUtils;
+import org.apache.commons.collections4.CollectionUtils;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+public class SitItemSelectTreePlugin extends AbstractFormPlugin implements SearchEnterListener {
+    private static final String SEARCH_CONTROL = "nckd_treesearchap";
+    private static final String TREE_VIEW = "nckd_treeviewap";
+    private static final String ENTRY_SELECT = "nckd_itemselectentry";
+    private static final String CACHE_ALL_ITEM_DATA = "allItemData";
+    private static final String ITEM_TYPE_SL = "SL";
+    private static final String ITEM_TYPE_SP = "SP";
+    private static final String ITEM_TYPE_BS = "BS";
+    private static final String PREFIX_SEPARATOR = "_@_";
+    private static final String SALARY_ITEM_KEY = "salaryitemkey";
+    private static final String SP_ITEM_KEY = "spitemkey";
+
+    @Override
+    public void registerListener(EventObject e) {
+        super.registerListener(e);
+        Search search = (Search)this.getView().getControl(SEARCH_CONTROL);
+        search.addEnterListener(this);
+    }
+
+    @Override
+    public void search(@NotNull SearchEnterEvent event) {
+        String searchText = event.getText();
+        boolean isExpend = SWCStringUtils.isNotEmpty(searchText);
+
+        SWCPageCache pageCache = new SWCPageCache(this.getView());
+        Map<String, Map<String, Map<String, Object>>> dataMap =
+                (Map)pageCache.get(CACHE_ALL_ITEM_DATA, Map.class);
+
+        List<TreeNode> nodeItemList = loadSLItemChildNode(searchText, isExpend, dataMap);
+
+        if (CollectionUtils.isEmpty(nodeItemList)) {
+            showSearchCompleteNotification();
+            return;
+        }
+
+        updateTreeView(nodeItemList);
+    }
+
+    private void showSearchCompleteNotification() {
+        this.getView().showTipNotification(ResManager.loadKDString(
+                "搜索已完成,未找到搜索项。",
+                "CalResultTplItemTreePlugin_0",
+                "swc-hsas-formplugin",
+                new Object[0]
+        ));
+    }
+
+    private void updateTreeView(List<TreeNode> nodeItemList) {
+        TreeView treeView = (TreeView)this.getView().getControl(TREE_VIEW);
+        treeView.deleteAllNodes();
+        treeView.addNodes(nodeItemList);
+        checkSelectedTreeNode(treeView, nodeItemList);
+    }
+
+    private void checkSelectedTreeNode(TreeView treeView, List<TreeNode> nodeList) {
+        DynamicObjectCollection selectDatas = this.getView().getModel().getEntryEntity(ENTRY_SELECT);
+        Set<String> uniqueCodeSet = selectDatas.stream()
+                .map(selectData -> selectData.getString("itemunicodeid"))
+                .collect(Collectors.toSet());
+
+        List<TreeNode> checkNodeList = FormulaItemOrFuncTreeHelper.getCheckTreeNodeList(nodeList, uniqueCodeSet);
+        if (CollectionUtils.isNotEmpty(checkNodeList)) {
+            treeView.checkNodes(checkNodeList);
+        }
+    }
+
+    private List<TreeNode> loadSLItemChildNode(String name, boolean isExpend,
+                                               Map<String, Map<String, Map<String, Object>>> dataMap) {
+        List<Map<String, Object>> salaryItemList = getSalaryItemList(name, dataMap);
+        if (CollectionUtils.isEmpty(salaryItemList)) {
+            return Collections.emptyList();
+        }
+
+        Map<String, TreeNode> itemTypeNodeMap = new LinkedHashMap<>(salaryItemList.size());
+        Map<String, List<TreeNode>> salaryItemNodeMap = new HashMap<>(16);
+
+        salaryItemList.forEach(item -> {
+            String itemTypeNum = (String)item.get("salaryitemtype_number");
+            String itemTypeName = (String)item.get("salaryitemtype_name");
+
+            // 创建子节点
+            TreeNode childNode = new TreeNode(
+                    itemTypeNum + PREFIX_SEPARATOR + ITEM_TYPE_SL,
+                    String.valueOf(item.get("uniquecode")),
+                    (String)item.get("name")
+            );
+            salaryItemNodeMap.computeIfAbsent(itemTypeNum, k -> new ArrayList<>(10)).add(childNode);
+
+            // 创建类型节点
+            itemTypeNodeMap.computeIfAbsent(itemTypeNum, k -> {
+                TreeNode typeNode = new TreeNode(ITEM_TYPE_SL,
+                        itemTypeNum + PREFIX_SEPARATOR + ITEM_TYPE_SL,
+                        itemTypeName);
+                typeNode.setExpend(isExpend);
+                typeNode.setIsOpened(isExpend);
+                return typeNode;
+            });
+        });
+
+        return buildSalaryItemTree(itemTypeNodeMap, salaryItemNodeMap, isExpend);
+    }
+
+    private List<Map<String, Object>> getSalaryItemList(String name,
+                                                        Map<String, Map<String, Map<String, Object>>> dataMap) {
+        return SWCStringUtils.isEmpty(name)
+                ? FormulaDataServiceHelper.mapToList(dataMap.get(SALARY_ITEM_KEY))
+                : findItemByName(name, SALARY_ITEM_KEY, dataMap);
+    }
+
+    private List<TreeNode> buildSalaryItemTree(Map<String, TreeNode> itemTypeNodeMap,
+                                               Map<String, List<TreeNode>> salaryItemNodeMap, boolean isExpend) {
+        List<TreeNode> treeNodeList = itemTypeNodeMap.entrySet().stream()
+                .map(entry -> {
+                    TreeNode typeNode = entry.getValue();
+                    typeNode.setChildren(salaryItemNodeMap.get(entry.getKey()));
+                    return typeNode;
+                })
+                .collect(Collectors.toList());
+
+        if (CollectionUtils.isEmpty(treeNodeList)) {
+            return Collections.emptyList();
+        }
+
+        TreeNode itemRoot = new TreeNode("", ITEM_TYPE_SL,
+                ResManager.loadKDString("薪酬项目-SL", "FormulaItemOrFuncTreeHelper_1",
+                        "swc-hsas-business", new Object[0]));
+        itemRoot.setChildren(treeNodeList);
+        itemRoot.setExpend(isExpend);
+        itemRoot.setIsOpened(isExpend);
+
+        return Collections.singletonList(itemRoot);
+    }
+
+    private static boolean isEnableWtcInte() {
+        Map<String, Object> paramMap = SWCSalaryParameterServiceHelper.getSalaryParam("wtcinte");
+        if (paramMap == null) {
+            return false;
+        }
+
+        Boolean wtcinte = (Boolean)paramMap.get("enableWtcInte");
+        Integer scheme = (Integer)paramMap.getOrDefault("scheme",
+                WtcInteCfgConstants.FIELD_SCHEME_THREE);
+
+        return wtcinte != null && wtcinte &&
+                (WtcInteCfgConstants.FIELD_SCHEME_ONE.equals(scheme) ||
+                        WtcInteCfgConstants.FIELD_SCHEME_TWO.equals(scheme));
+    }
+
+    private static void getTreeNodeList(Map<String, List<TreeNode>> bsNodeMap,
+                                        Map<String, TreeNode> bsTypeNodeMap, String bizTypNumber,
+                                        Map<String, Object> bsItem, String prefixKey) {
+        TreeNode bsNode = new TreeNode(
+                bizTypNumber + PREFIX_SEPARATOR + ITEM_TYPE_BS,
+                String.valueOf(bsItem.get("uniquecode")),
+                (String)bsItem.get("name")
+        );
+
+        bsNodeMap.computeIfAbsent(bizTypNumber, k -> new ArrayList<>(10)).add(bsNode);
+
+        bsTypeNodeMap.computeIfAbsent(bizTypNumber, k ->
+                new TreeNode(prefixKey + ITEM_TYPE_BS,
+                        bizTypNumber + PREFIX_SEPARATOR + ITEM_TYPE_BS,
+                        (String)bsItem.get("bizTypeName")
+                )
+        );
+    }
+
+    private List<TreeNode> loadSPTreeNodeList(String name, boolean isExpend,
+                                              Map<String, Map<String, Map<String, Object>>> dataMap) {
+        List<Map<String, Object>> result = SWCStringUtils.isEmpty(name)
+                ? FormulaDataServiceHelper.mapToList(dataMap.get(SP_ITEM_KEY))
+                : findItemByName(name, SP_ITEM_KEY, dataMap);
+
+        if (CollectionUtils.isEmpty(result)) {
+            return Collections.emptyList();
+        }
+
+        List<TreeNode> treeNodeList = result.stream()
+                .map(spItem -> new TreeNode(
+                        PREFIX_SEPARATOR + ITEM_TYPE_SP,
+                        String.valueOf(spItem.get("uniquecode")),
+                        (String)spItem.get("name")
+                ))
+                .collect(Collectors.toList());
+
+        TreeNode node = new TreeNode("", PREFIX_SEPARATOR + ITEM_TYPE_SP,
+                ResManager.loadKDString("支持项目-SP", "FormulaItemOrFuncTreeHelper_5",
+                        "swc-hsas-business", new Object[0]));
+        node.setChildren(treeNodeList);
+        node.setExpend(isExpend);
+        node.setIsOpened(isExpend);
+
+        return Collections.singletonList(node);
+    }
+
+    private List<Map<String, Object>> findItemByName(String name, String itemName,
+                                                     Map<String, Map<String, Map<String, Object>>> dataMap) {
+        Map<String, Map<String, Object>> result = dataMap.get(itemName);
+        if (result == null) {
+            return Collections.emptyList();
+        }
+
+        return result.entrySet().stream()
+                .filter(entry -> {
+                    Map<String, Object> itemMap = entry.getValue();
+                    if (itemMap == null && itemMap.size() == 0) {
+                        return entry.getKey().contains(name);
+                    }
+
+                    String number = (String)itemMap.get("number");
+                    return SWCStringUtils.isNotEmpty(number) &&
+                            (number.contains(name) || entry.getKey().contains(name));
+                })
+                .map(Map.Entry::getValue)
+                .collect(Collectors.toList());
+    }
+}

+ 77 - 0
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/formplugin/web/tp/basedata/SinsurImpTaskListPlugin.java

@@ -0,0 +1,77 @@
+package nckd.jxccl.sit.hcsi.formplugin.web.tp.basedata;
+
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.resource.ResManager;
+import kd.bos.entity.datamodel.ListSelectedRow;
+import kd.bos.form.FormShowParameter;
+import kd.bos.form.ShowType;
+import kd.bos.form.events.HyperLinkClickArgs;
+import kd.bos.list.IListView;
+import kd.bos.list.ListShowParameter;
+import kd.bos.list.plugin.AbstractListPlugin;
+import kd.sdk.plugin.Plugin;
+import kd.swc.hsbp.business.servicehelper.SWCDataServiceHelper;
+import kd.swc.hsbp.common.util.SWCStringUtils;
+
+import java.text.MessageFormat;
+
+/**
+ * Tyx 2025-10-21
+ * 外部数据导入任务列表插件 nckd_sinsurimptask
+ */
+public class SinsurImpTaskListPlugin extends AbstractListPlugin implements Plugin {
+
+    /**
+     * 点击任务名称跳转到导入中间表:nckd_taskimpguide
+     * @param args
+     */
+    public void billListHyperLinkClick(HyperLinkClickArgs args) {
+        ListShowParameter listShowParameter = (ListShowParameter)this.getView().getFormShowParameter();
+        if (!listShowParameter.isLookUp()) {
+            String fieldName = args.getHyperLinkClickEvent().getFieldName();
+            if (SWCStringUtils.equals("name", fieldName)) {
+                args.setCancel(true);
+                IListView listView = (IListView)this.getView();
+                ListSelectedRow selectRow = listView.getCurrentSelectedRowInfo();
+                Long importTaskId = (Long)selectRow.getPrimaryKeyValue();
+                this.openTempDataPage(importTaskId);
+            }
+
+        }
+    }
+
+    /**
+     * 处理跳转参数并打开页面
+     * @param importTaskId
+     */
+    private void openTempDataPage(Long importTaskId) {
+        SWCDataServiceHelper helper = new SWCDataServiceHelper("nckd_sinsurimptask");
+        DynamicObject data = helper.queryOne("id,name,nckd_org.id,nckd_welfarepayer.id,nckd_period.id,creator.id,nckd_sinsurtpl.id,nckd_taskstatus", importTaskId);
+        String msg;
+        if (data == null) {
+            msg = ResManager.loadKDString("数据已不存在。", "ImportTaskList_0", "swc-hsas-formplugin", new Object[0]);
+            this.getView().showErrorNotification(msg);
+        } else if (SWCStringUtils.equals("8", data.getString("nckd_taskstatus"))) {
+            msg = ResManager.loadKDString("所选任务已清除中间表数据,无法查看。", "ImportTaskList_4", "swc-hsas-formplugin", new Object[0]);
+            this.getView().showErrorNotification(msg);
+        } else {
+            FormShowParameter parameter = new FormShowParameter();
+            parameter.getOpenStyle().setShowType(ShowType.MainNewTabPage);
+            parameter.setFormId("nckd_taskimpguide");
+            String caption = MessageFormat.format(ResManager.loadKDString("外部数据导入任务 - {0}", "ImportTaskList_1", "swc-hsas-formplugin", new Object[0]), data.getString("name"));
+            parameter.setCaption(caption);
+            parameter.setCustomParam("importTaskId", importTaskId);
+            parameter.setCustomParam("importTaskName", data.getString("name"));
+            parameter.setCustomParam("welfarepayerId", data.getLong("nckd_welfarepayer.id"));
+            parameter.setCustomParam("periodId", data.getLong("nckd_period.id"));
+            parameter.setCustomParam("sinsurTplId", data.getLong("nckd_sinsurtpl.id"));
+            parameter.setCustomParam("orgId", String.valueOf(data.getLong("nckd_org.id")));
+            parameter.setCustomParam("creator", String.valueOf(data.getLong("creator.id")));
+            String pageId = this.getView().getMainView() == null ? this.getView().getPageId() : this.getView().getMainView().getPageId();
+            pageId = pageId + '_' + importTaskId;
+            parameter.setPageId(pageId);
+            this.getView().showForm(parameter);
+        }
+    }
+
+}

+ 128 - 0
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/formplugin/web/tp/basedata/TaskGuideImportFormPlugin.java

@@ -0,0 +1,128 @@
+package nckd.jxccl.sit.hcsi.formplugin.web.tp.basedata;
+
+import com.google.common.collect.Maps;
+import kd.bos.dataentity.resource.ResManager;
+import kd.bos.dataentity.utils.StringUtils;
+import kd.bos.entity.datamodel.IDataModel;
+import kd.bos.form.FormShowParameter;
+import kd.bos.form.IFormView;
+import kd.bos.form.MessageTypes;
+import kd.bos.form.control.Control;
+import kd.bos.form.control.Image;
+import kd.bos.form.control.Label;
+import kd.bos.form.control.events.UploadEvent;
+import kd.bos.form.control.events.UploadListener;
+import kd.bos.form.plugin.AbstractFormPlugin;
+import kd.bos.url.UrlService;
+import kd.sdk.plugin.Plugin;
+import kd.swc.hsbp.business.servicehelper.SWCPermissionServiceHelper;
+import kd.swc.hsbp.common.constants.ImportConstants;
+import kd.swc.hsbp.common.util.SWCStringUtils;
+import nckd.jxccl.sit.hcsi.business.importtaskguide.ImportTaskGuideExportService;
+import nckd.jxccl.sit.hcsi.business.importtaskguide.ImportTaskGuideImportService;
+
+import java.util.EventObject;
+import java.util.Map;
+
+/**
+ * 动态表单插件
+ */
+public class TaskGuideImportFormPlugin extends AbstractFormPlugin implements UploadListener {
+
+    private static final String KEY_BTN_OK = "btnok";
+    private static final String KEY_BTN_DOWNLOAD = "btndownload";
+    private static final String KEY_BTN_RESETFILE = "btnresetfile";
+    private static final String KEY_BTN_UPLOAD = "btnupload";
+
+    public TaskGuideImportFormPlugin() {}
+
+    @Override
+    public void initialize() {
+        this.addClickListeners(new String[]{KEY_BTN_OK, KEY_BTN_DOWNLOAD, KEY_BTN_RESETFILE});
+        Image label = (Image)this.getControl(KEY_BTN_UPLOAD);
+        label.addUploadListener(this);
+    }
+
+    @Override
+    public void afterCreateNewData(EventObject e) {
+        this.getView().setVisible(Boolean.FALSE, new String[]{"filepanel"});
+        this.getView().setEnable(Boolean.FALSE, new String[]{"keyfields"});
+        Label title = (Label)this.getControl("title");
+        title.setText(ResManager.loadKDString("导入任务", "TaskGuideImportViewPlugin_0", "swc-hsas-formplugin", new Object[0]));
+    }
+
+    @Override
+    public void click(EventObject evt) {
+        switch (((Control)evt.getSource()).getKey()) {
+            case KEY_BTN_OK:
+                this.importData();
+                break;
+            case KEY_BTN_DOWNLOAD:
+                ImportTaskGuideExportService exportService = new ImportTaskGuideExportService();
+                exportService.exportExcelTemplate(this.getView());
+                break;
+            case KEY_BTN_RESETFILE:
+                this.resetFileInfo();
+        }
+    }
+
+    public void upload(UploadEvent evt) {
+        Object[] urls = evt.getUrls();
+        if (urls.length > 0) {
+            IFormView view = this.getView();
+            String url = (String)urls[0];
+            view.setVisible(Boolean.TRUE, new String[]{"filepanel"});
+            view.setVisible(Boolean.FALSE, new String[]{"uploadpanel"});
+            IDataModel model = this.getModel();
+            model.setValue("filename", url.substring(url.lastIndexOf(47) + 1));
+            String fullUrl = UrlService.getAttachmentFullUrl(url);
+            model.setValue("filepath", url);
+            model.setValue("fullpath", fullUrl);
+        }
+    }
+
+    private void resetFileInfo() {
+        this.getModel().setValue("filename", "");
+        this.getModel().setValue("filepath", "");
+        this.getView().setVisible(Boolean.FALSE, new String[]{"filepanel"});
+        this.getView().setVisible(Boolean.TRUE, new String[]{"uploadpanel"});
+    }
+
+    private void importData() {
+        String url = this.getModel().getDataEntity().getString("filepath");
+        if (StringUtils.isBlank(url)) {
+            this.getView().showErrorNotification(ResManager.loadKDString("请先上传数据文件后操作。", "HSASCalTableImportStartPlugin_1", "swc-hsas-formplugin", new Object[0]));
+        } else {
+            FormShowParameter params = this.getView().getFormShowParameter();
+            Long importTaskId = (Long)params.getCustomParam("importTaskId");
+            Long sinsurTplId = (Long)params.getCustomParam("sinsurTplId");
+            Long welfarepayerId = params.getCustomParam("welfarepayerId");
+            Long periodId = params.getCustomParam("periodId");
+            Long orgId = Long.valueOf(params.getCustomParam("orgId").toString());
+            String importTaskName = (String)params.getCustomParam("importTaskName");
+            String pageId = this.getView().getParentView().getPageId();
+            ImportTaskGuideImportService importService = new ImportTaskGuideImportService(url, importTaskId, sinsurTplId, periodId, welfarepayerId);
+
+            try {
+                Map<String, String> result = importService.parseAndCheckExcelData(orgId, pageId, importTaskName);
+                String errorMsg = (String)result.get("errorMsg");
+                if (!SWCStringUtils.isEmpty(errorMsg)) {
+                    this.getView().showErrorNotification(errorMsg);
+                    return;
+                }
+
+                Map<String, Object> returnData = Maps.newHashMapWithExpectedSize(16);
+                returnData.put("isOk", Boolean.TRUE);
+                returnData.put("totalCount", result.get("totalCount"));
+                returnData.put("cacheKey", result.get("cacheKey"));
+                returnData.put("importTaskId", importTaskId);
+                returnData.put("sinsurTplId", sinsurTplId);
+                this.getView().returnDataToParent(returnData);
+                this.getView().close();
+            } catch (Exception e) {
+                this.getView().showMessage(ImportConstants.IMPORT_TEMPLATE_ERROR(), e.getMessage(), MessageTypes.Default);
+            }
+
+        }
+    }
+}

+ 73 - 0
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/formplugin/web/tp/enums/SinsurPresetItemEnum.java

@@ -0,0 +1,73 @@
+package nckd.jxccl.sit.hcsi.formplugin.web.tp.enums;
+
+import kd.swc.hsas.common.enums.PresetItemEnum;
+import kd.swc.hsbp.common.entity.SWCI18NParam;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public enum SinsurPresetItemEnum {
+    CALPERIOD("A", 1L, new SWCI18NParam("期间", "PresetItemEnum_4", "swc-hsas-common"), 1030L, new SWCI18NParam("必填项,体现缴纳期间,格式:202501", "PresetItemEnum_13", "swc-hsas-common"), new SWCI18NParam("期间编码", "PresetItemEnum_28", "swc-hsas-common"), true),
+    EMP_IDCARD("B", 2L, new SWCI18NParam("员工身份证", "PresetItemEnum_6", "swc-hsas-common"), 1030L, new SWCI18NParam("必填项,用于确认社保人员", "PresetItemEnum_15", "swc-hsas-common"), new SWCI18NParam("员工身份证", "PresetItemEnum_6", "swc-hsas-common"), true),
+    EMP_NAME("C", 3L, new SWCI18NParam("员工姓名", "PresetItemEnum_6", "swc-hsas-common"), 1030L, new SWCI18NParam("非必填项", "PresetItemEnum_15", "swc-hsas-common"), new SWCI18NParam("员工姓名", "PresetItemEnum_6", "swc-hsas-common"), false),
+    EMP_NUMBER("D", 4L, new SWCI18NParam("工号", "PresetItemEnum_6", "swc-hsas-common"), 1030L, new SWCI18NParam("非必填项", "PresetItemEnum_15", "swc-hsas-common"), new SWCI18NParam("工号", "PresetItemEnum_6", "swc-hsas-common"), false);
+
+    private String matchColumn;
+    private Long itemId;
+    private SWCI18NParam itemName;
+    private Long dataTypeId;
+    private SWCI18NParam comment;
+    private SWCI18NParam importColumnName;
+    private boolean isRequire;
+
+    private SinsurPresetItemEnum(String matchColumn, Long itemId, SWCI18NParam itemName, Long dataTypeId, SWCI18NParam comment, SWCI18NParam importColumnName, boolean isRequire) {
+        this.matchColumn = matchColumn;
+        this.itemId = itemId;
+        this.itemName = itemName;
+        this.dataTypeId = dataTypeId;
+        this.comment = comment;
+        this.importColumnName = importColumnName;
+        this.isRequire = isRequire;
+    }
+
+    public String getMatchColumn() {
+        return this.matchColumn;
+    }
+
+    public Long getItemId() {
+        return this.itemId;
+    }
+
+    public String getItemName() {
+        return this.itemName.loadKDString();
+    }
+
+    public SWCI18NParam getComment() {
+        return this.comment;
+    }
+
+    public Long getDataTypeId() {
+        return this.dataTypeId;
+    }
+
+    public String getImportColumnName() {
+        return this.importColumnName.loadKDString();
+    }
+
+    public boolean isRequire() {
+        return this.isRequire;
+    }
+
+    public static Map<Long, SinsurPresetItemEnum> getSinsurPresetItemEnumMap() {
+        Map<Long, SinsurPresetItemEnum> map = new HashMap(16);
+        SinsurPresetItemEnum[] values = values();
+        int count = values.length;
+
+        for(int i = 0; i < count; ++i) {
+            SinsurPresetItemEnum obj = values[i];
+            map.put(obj.getItemId(), obj);
+        }
+        return map;
+    }
+
+}

+ 158 - 0
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/formplugin/web/tp/guide/TaskImpGuideListPlugin.java

@@ -0,0 +1,158 @@
+package nckd.jxccl.sit.hcsi.formplugin.web.tp.guide;
+
+import kd.bos.context.RequestContext;
+import kd.bos.dataentity.resource.ResManager;
+import kd.bos.dataentity.utils.ObjectUtils;
+import kd.bos.form.FormShowParameter;
+import kd.bos.form.ShowType;
+import kd.bos.form.container.Tab;
+import kd.bos.form.control.events.TabSelectEvent;
+import kd.bos.form.control.events.TabSelectListener;
+import kd.bos.form.events.BeforeClosedEvent;
+import kd.bos.form.operate.MutexHelper;
+import kd.bos.form.plugin.AbstractFormPlugin;
+import kd.bos.list.ListShowParameter;
+import kd.bos.list.plugin.AbstractListPlugin;
+import kd.bos.mutex.DataMutex;
+import kd.bos.orm.query.QFilter;
+import kd.sdk.plugin.Plugin;
+import kd.swc.hsbp.common.cache.ISWCAppCache;
+import kd.swc.hsbp.common.cache.SWCAppCache;
+import kd.swc.hsbp.common.cache.SWCPageCache;
+
+import java.io.IOException;
+import java.util.EventObject;
+import java.util.Map;
+
+/**
+ * Tyx 2025-10-21
+ * 外部数据导入向导界面插件 nckd_taskimpguide
+ */
+public class TaskImpGuideListPlugin extends AbstractListPlugin implements TabSelectListener {
+
+    @Override
+    public void registerListener(EventObject e) {
+        Tab tabSteps = (Tab)this.getControl("tabap");
+        tabSteps.addTabSelectListener(this);
+    }
+
+    public void beforeBindData(EventObject arg) {
+        this.applyMutexLock();
+        this.clearAppCache();
+        Tab tabSteps = (Tab)this.getControl("tabap");
+        tabSteps.activeTab("dataimport");
+    }
+
+    private void applyMutexLock() {
+        Long importTaskId = (Long)this.getView().getFormShowParameter().getCustomParam("importTaskId");
+        StringBuilder msg = new StringBuilder();
+        boolean require = MutexHelper.require("nckd_sinsurimptask", importTaskId, "modify", true, msg);
+        SWCPageCache cache = new SWCPageCache(this.getView());
+        if (require) {
+            cache.put("currentPageLocked", Boolean.TRUE);
+        } else {
+            cache.put("isLocked", Boolean.TRUE);
+            this.getView().showTipNotification(msg.toString());
+        }
+    }
+
+    @Override
+    public void tabSelected(TabSelectEvent tabSelectEvent) {
+        String tabKey = tabSelectEvent.getTabKey();
+        this.getPageCache().put("tabKey", tabKey);
+        switch (tabKey) {
+            case "dataimport":
+                this.loadChildrenPage("dataimport", "dataimportflex");
+                this.getPageCache().put("targetKey", "dataimportflex");
+                break;
+        }
+    }
+
+    private void loadChildrenPage(String tabKey, String targetKey) {
+        SWCPageCache pageCache = new SWCPageCache(this.getView());
+        Boolean isLocked = (Boolean)pageCache.get("isLocked", Boolean.class);
+        FormShowParameter parameter = this.getView().getFormShowParameter();
+        ListShowParameter showParameter = new ListShowParameter();
+        showParameter.getOpenStyle().setShowType(ShowType.InContainer);
+        showParameter.getOpenStyle().setTargetKey(targetKey);
+        showParameter.setBillFormId("nckd_sinsurtempdata");
+        showParameter.setFormId("bos_list");
+        showParameter.setLookUp(false);
+        showParameter.setShowTitle(false);
+        showParameter.setCustomParam("importTaskId", parameter.getCustomParam("importTaskId"));
+        showParameter.setCustomParam("importTaskName", parameter.getCustomParam("importTaskName"));
+        showParameter.setCustomParam("sinsurTplId", parameter.getCustomParam("sinsurTplId"));
+        showParameter.setCustomParam("periodId", parameter.getCustomParam("periodId"));
+        showParameter.setCustomParam("welfarepayerId", parameter.getCustomParam("welfarepayerId"));
+        showParameter.setCustomParam("orgId", parameter.getCustomParam("orgId"));
+        if (isLocked != null && isLocked) {
+            showParameter.setCustomParam("isLocked", Boolean.TRUE);
+        } else {
+            showParameter.setCustomParam("isLocked", Boolean.FALSE);
+        }
+
+        String title = null;
+        if ("dealandcheck".equals(tabKey)) {
+            title = ResManager.loadKDString("数据处理与校验", "ImportTaskGuideListPlugin_1", "swc-hsas-formplugin", new Object[0]);
+        } else if ("approveandwrite".equals(tabKey)) {
+            title = ResManager.loadKDString("审核并写入薪资结果", "ImportTaskGuideListPlugin_2", "swc-hsas-formplugin", new Object[0]);
+        } else {
+            title = ResManager.loadKDString("数据导入", "ImportTaskGuideListPlugin_0", "swc-hsas-formplugin", new Object[0]);
+        }
+
+        showParameter.setCaption(title);
+        showParameter.setCustomParam("creator", parameter.getCustomParam("creator"));
+        showParameter.setCustomParam("tabKey", tabKey);
+        showParameter.setCustomParam("verifyRecordId", this.getPageCache().get("verifyRecordId"));
+        this.getPageCache().put("verifyRecordId", (String)null);
+        showParameter.setSendToClient(true);
+        showParameter.getListFilterParameter().getQFilters().add(new QFilter("nckd_importtask", "=", parameter.getCustomParam("importTaskId")));
+        this.getView().showForm(showParameter);
+    }
+
+    public void pageRelease(EventObject e) {
+        String groupId = MutexHelper.getMutexGroupId("nckd_sinsurimptask", "modify");
+        Long importTaskId = (Long)this.getView().getFormShowParameter().getCustomParam("importTaskId");
+        DataMutex dataMutex = null;
+        try {
+            dataMutex = DataMutex.create();
+            Map<String, String> mutex = dataMutex.getLockInfo(String.valueOf(importTaskId), groupId, "nckd_sinsurimptask");
+            if (null != mutex && !mutex.isEmpty()) {
+                String lockOwner = (String)mutex.get("GLOBALSESSION");
+                String currentOwner = RequestContext.get().getGlobalSessionId();
+                if (ObjectUtils.nullSafeEquals(lockOwner, currentOwner)) {
+                    SWCPageCache cache = new SWCPageCache(this.getView());
+                    Boolean isCurrentPageLocked = (Boolean)cache.get("currentPageLocked", Boolean.class);
+                    if (isCurrentPageLocked == null) {
+                        return;
+                    }
+                    MutexHelper.release("nckd_sinsurimptask", "modify", String.valueOf(importTaskId));
+                    return;
+                }
+                return;
+            }
+        } finally {
+            if (dataMutex != null) {
+                try {
+                    dataMutex.close();
+                } catch (IOException e1) {
+                }
+            }
+
+        }
+
+    }
+
+    @Override
+    public void beforeClosed(BeforeClosedEvent e) {
+        super.beforeClosed(e);
+        this.clearAppCache();
+    }
+
+    private void clearAppCache() {
+        FormShowParameter parameter = this.getView().getFormShowParameter();
+        String cacheKey = parameter.getCustomParam("importTaskId") + "_" + parameter.getCustomParam("sinsurTplId");
+        ISWCAppCache appCache = SWCAppCache.get(cacheKey);
+        appCache.remove("columnHeadList");
+    }
+}

+ 158 - 0
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/formplugin/web/tp/helper/SinsurTemplateHelper.java

@@ -0,0 +1,158 @@
+package nckd.jxccl.sit.hcsi.formplugin.web.tp.helper;
+
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.dataentity.resource.ResManager;
+import kd.bos.orm.query.QFilter;
+import kd.bos.orm.util.CollectionUtils;
+import kd.swc.hsas.common.enums.PresetItemEnum;
+import kd.swc.hsbp.business.servicehelper.SWCDataServiceHelper;
+import kd.swc.hsbp.business.servicehelper.SWCPermissionServiceHelper;
+import kd.swc.hsbp.common.util.SWCStringUtils;
+import nckd.jxccl.sit.hcsi.formplugin.web.tp.enums.SinsurPresetItemEnum;
+
+import java.util.*;
+
+public class SinsurTemplateHelper {
+    private static List<SinsurPresetItemEnum> sinsurPresetItemEnumList = new ArrayList(12);
+    private static Map<Long, PresetItemEnum> commonAndAddPresetItemEnumMap = new HashMap(4);
+    private static Map<Long, PresetItemEnum> hisDataPresetItemEnumMap = new HashMap(12);
+    private static Map<Long, PresetItemEnum> hisDataForMulTimeItemEnumMap = new HashMap(13);
+
+    public static Map<String, Map<String, Object>> analyzeItemDatas(DynamicObjectCollection itemDatas, Map<Long, Map<String, Object>> existItemDataMap) {
+        List<String> IIUnicodeList = new ArrayList(itemDatas.size());
+        for (DynamicObject itemData : itemDatas) {
+            String itemCategory = itemData.getString("nckd_itemcategory");
+            String uniCode = itemData.getString("nckd_itemnumber");
+            if (SWCStringUtils.equals("II", itemCategory)) {
+                IIUnicodeList.add(uniCode);
+            }
+        }
+        Map<String, Map<String, Object>> itemParamMap = new HashMap(itemDatas.size());
+        itemParamMap.putAll(getItemParamMap("number", IIUnicodeList, "1", "sitbs_insuranceitem", existItemDataMap, (Long) null));
+        return itemParamMap;
+    }
+
+    public static Map<String, Map<String, Object>> getItemParamMap(String key, List<String> keyList, String itemType, String entityName, Map<Long, Map<String, Object>> existItemDataMap, Long orgId) {
+        if (CollectionUtils.isEmpty(keyList)) {
+            return new HashMap(0);
+        } else {
+            if (existItemDataMap == null) {
+                existItemDataMap = new HashMap(0);
+            }
+            Map<String, Map<String, Object>> itemParamMap = new HashMap(keyList.size());
+            SWCDataServiceHelper helper = new SWCDataServiceHelper(entityName);
+            String fields = "id,number,name,datatype.id";
+
+            QFilter filter = new QFilter(key, "in", keyList);
+            filter.and(new QFilter("enable", "=", "1"));
+            if (orgId != null) {
+                QFilter useOrgFilter = SWCPermissionServiceHelper.getBaseDataFilter(entityName, orgId);
+                filter.and(useOrgFilter);
+            }
+            DynamicObjectCollection items = helper.queryOriginalCollection(fields, new QFilter[]{filter});
+
+            for(DynamicObject item : items) {
+                Long itemId = item.getLong("id");
+                Long dataTypeId = item.getLong("datatype.id");
+                Map<String, Object> itemParam = new HashMap(6);
+                Map<String, Object> existItemData = (Map)((Map)existItemDataMap).get(itemId);
+                itemParam.put("id", itemId);
+                itemParam.put("dataTypeId", dataTypeId);
+                itemParam.put("itemType", itemType);
+                itemParam.put("itemname", item.getString("name"));
+                itemParam.put("entityName", entityName);
+
+                fillExistComment(entityName, item, existItemData, itemParam);
+                itemParamMap.put(item.getString(key), itemParam);
+            }
+
+            return itemParamMap;
+        }
+    }
+
+    private static void fillExistComment(String entityName, DynamicObject item, Map<String, Object> existItemData, Map<String, Object> itemParam) {
+        String itemCurrency;
+        String existComment;
+        if (existItemData != null && existItemData.size() > 0) {
+            itemCurrency = (String)existItemData.get("comment");
+            itemParam.put("matchcolumn", existItemData.get("matchcolumn"));
+            if (SWCStringUtils.isNotEmpty(itemCurrency)) {
+                itemParam.put("comment", itemCurrency);
+            }
+        } else if (SWCStringUtils.equals("hsbs_salaryitem", entityName)) {
+            itemCurrency = item.getString("outputcurrency.name");
+            if (SWCStringUtils.isNotEmpty(itemCurrency)) {
+                existComment = ResManager.loadKDString("币种:{0}", "MigrationTemplateHelper_0", "swc-hsas-business", new Object[]{itemCurrency});
+                itemParam.put("comment", existComment);
+            }
+        }
+    }
+
+    public static Map<String, Map<String, Object>> analyzeMatchItem(DynamicObjectCollection entryDatas) {
+        if (CollectionUtils.isEmpty(entryDatas)) {
+            return new HashMap(0);
+        } else {
+            List<Long> SLItemIdList = new ArrayList(entryDatas.size());
+            List<Long> SPItemIdList = new ArrayList(entryDatas.size());
+            List<Long> BSItemIdList = new ArrayList(entryDatas.size());
+            List<Long> FTItemIdList = new ArrayList(entryDatas.size());
+            Iterator var5 = entryDatas.iterator();
+
+            while(var5.hasNext()) {
+                DynamicObject entry = (DynamicObject)var5.next();
+                String itemType = entry.getString("nckd_itemtype");
+                Long itemId = entry.getLong("nckd_itemid");
+                if (SWCStringUtils.equals("1", itemType)) {
+                    SLItemIdList.add(itemId);
+                } else if (SWCStringUtils.equals("2", itemType)) {
+                    SPItemIdList.add(itemId);
+                } else if (SWCStringUtils.equals("3", itemType)) {
+                    BSItemIdList.add(itemId);
+                } else if (SWCStringUtils.equals("4", itemType)) {
+                    FTItemIdList.add(itemId);
+                }
+            }
+
+            Map<String, Map<String, Object>> itemParamMap = new HashMap(entryDatas.size());
+            //itemParamMap.putAll(getItemParamMap(SLItemIdList, "1", "hsbs_salaryitem", (Long)null, false));
+            //itemParamMap.putAll(getItemParamMap(SPItemIdList, "2", "hsbs_supportitem", (Long)null, false));
+            //itemParamMap.putAll(getItemParamMap(BSItemIdList, "3", "hsbs_bizitem", (Long)null, false));
+            //itemParamMap.putAll(getItemParamMap(FTItemIdList, "4", "hsbs_fetchitem", (Long)null, false));
+            return itemParamMap;
+        }
+    }
+
+    public static PresetItemEnum getPresetItemEnum(Long itemId) {
+        PresetItemEnum presetItemEnum = (PresetItemEnum)commonAndAddPresetItemEnumMap.get(itemId);
+        if (presetItemEnum == null) {
+            presetItemEnum = (PresetItemEnum)hisDataPresetItemEnumMap.get(itemId);
+        }
+
+        if (presetItemEnum == null) {
+            presetItemEnum = (PresetItemEnum)hisDataForMulTimeItemEnumMap.get(itemId);
+        }
+
+        return presetItemEnum;
+    }
+
+    public static List<SinsurPresetItemEnum> getPresetItemEnumList(String writeTaskType) {
+        return getPresetItemEnumList();
+    }
+
+    public static List<SinsurPresetItemEnum> getPresetItemEnumList() {
+        return sinsurPresetItemEnumList;
+    }
+
+    static {
+        sinsurPresetItemEnumList.add(SinsurPresetItemEnum.CALPERIOD);
+        sinsurPresetItemEnumList.add(SinsurPresetItemEnum.EMP_IDCARD);
+        sinsurPresetItemEnumList.add(SinsurPresetItemEnum.EMP_NAME);
+        sinsurPresetItemEnumList.add(SinsurPresetItemEnum.EMP_NUMBER);
+    }
+
+
+
+}
+
+

+ 186 - 0
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/formplugin/web/tp/helper/SitItemSelectAddItemServiceHelper.java

@@ -0,0 +1,186 @@
+package nckd.jxccl.sit.hcsi.formplugin.web.tp.helper;
+
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.dataentity.resource.ResManager;
+import kd.bos.entity.tree.TreeNode;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
+import kd.bos.util.CollectionUtils;
+import kd.swc.hsas.business.formula.helper.FormulaDataServiceHelper;
+import kd.swc.hsbp.business.servicehelper.SWCDataServiceHelper;
+import kd.swc.hsbp.business.servicehelper.SWCPermissionServiceHelper;
+import kd.swc.hsbp.common.util.SWCStringUtils;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+public class SitItemSelectAddItemServiceHelper {
+
+    private static final String INSURANCEITEM_ENTITY = "sitbs_insuranceitem";
+    private static final String QUERY_FIELDS = "id,number,name,group.name,group.number,group.id";
+    private static final String DEFAULT_ORDER = "number asc";
+
+    private static final String INSURANCEITEM_KEY = "insuranceitemkey";
+    private static final String ITEM_TYPE_II = "II";
+    private static final String PREFIX_SEPARATOR = "_@_";
+
+    /**
+     * 获取所有需要展示的项目,目前就险种
+     * @param orgId
+     * @return
+     */
+    public Map<String, Map<String, Map<String, Object>>> getAllItemData(long orgId) {
+        Map<String, Map<String, Map<String, Object>>> dataMap = new HashMap(4);
+        Map<String, Map<String, Object>> insuranceItemMap = this.getInsuranceItemList(false, (QFilter)null, (QFilter)null, orgId);
+        dataMap.put("insuranceitemkey", insuranceItemMap);
+        return dataMap;
+    }
+
+    private Map<String, Map<String, Object>> getInsuranceItemList(boolean isProrationFormula, QFilter countryQFilter, QFilter calBlockQFilter, long orgId) {
+        if (isProrationFormula) {
+            return Collections.emptyMap();
+        }
+        List<QFilter> qFilters = buildFilters(countryQFilter, calBlockQFilter, orgId);
+        DynamicObjectCollection result = queryInsuranceItems(qFilters);
+        return result.stream()
+                .collect(Collectors.toMap(
+                        item -> item.getString("name"),
+                        this::convertToItemMap,
+                        (existing, replacement) -> existing,
+                        LinkedHashMap::new
+                ));
+    }
+
+    private List<QFilter> buildFilters(QFilter countryQFilter, QFilter calBlockQFilter, long orgId) {
+        List<QFilter> filters = new ArrayList<>();
+        Optional.ofNullable(countryQFilter).ifPresent(filters::add);
+        Optional.ofNullable(calBlockQFilter).ifPresent(filters::add);
+        QFilter baseFilter = new QFilter("enable", "=", "1")
+                .and(new QFilter("status", "=", "C"))
+                .and(new QFilter("insurancetypeattr.number", QCP.not_in, new String[]{"1007_S","1008_S","1013_S","1014_S"}));
+        filters.add(baseFilter);
+        filters.add(SWCPermissionServiceHelper.getBaseDataFilter(INSURANCEITEM_ENTITY, orgId));
+        return filters;
+    }
+
+    private DynamicObjectCollection queryInsuranceItems(List<QFilter> filters) {
+        SWCDataServiceHelper helper = new SWCDataServiceHelper(INSURANCEITEM_ENTITY);
+        return helper.queryOriginalCollection(
+                QUERY_FIELDS,
+                filters.toArray(new QFilter[0]),
+                DEFAULT_ORDER
+        );
+    }
+
+    private Map<String, Object> convertToItemMap(DynamicObject item) {
+        Map<String, Object> itemMap = new HashMap<>(3);
+        itemMap.put("id", item.getLong("id"));
+        itemMap.put("number", item.getString("number"));
+        itemMap.put("name", item.getString("name"));
+        itemMap.put("group_name", item.getString("group.name"));
+        itemMap.put("group_number", item.getString("group.number"));
+        itemMap.put("group_id", item.getString("group.id"));
+        return itemMap;
+    }
+
+    /**
+     * 构建险种项目树结构
+     * 顶层ID : II
+     * 险种分类节点ID:险种编码 + _@_
+     * 险种项目子节点ID:险种项目ID
+     * @param name
+     * @param isExpend
+     * @param dataMap
+     * @return
+     */
+    public static List<TreeNode> loadInsuranceItemChildNode(String name, boolean isExpend,
+                                                     Map<String, Map<String, Map<String, Object>>> dataMap) {
+        // 所有险种项目
+        List<Map<String, Object>> insuranceItemList = getInsuranceItemList(name, dataMap);
+        List<TreeNode> tree = createRootNode(isExpend);
+        if (CollectionUtils.isEmpty(insuranceItemList)) {
+            return tree;
+        }
+
+        // 最后返回树:
+        List<TreeNode> totalNodeList = new ArrayList<>(insuranceItemList.size() + 1);
+
+        // 构建根节点:
+        TreeNode itemRoot = new TreeNode("", ITEM_TYPE_II,
+                ResManager.loadKDString("险种项目-II", "FormulaItemOrFuncTreeHelper_1",
+                        "swc-hsas-business", new Object[0]));
+        itemRoot.setExpend(isExpend);
+        itemRoot.setIsOpened(isExpend);
+        totalNodeList.add(itemRoot);
+
+        // 构建子节点:
+        if (!CollectionUtils.isEmpty(insuranceItemList)) {
+            Map<String, TreeNode> itemTypeNodeMap = new LinkedHashMap(insuranceItemList.size());
+            Map<String, List<TreeNode>> insuranceItemNodeMap = new HashMap(16);
+            List<TreeNode> treeNodeList = null;
+            String itemTypeNum = null;
+            for (Map<String, Object> map : insuranceItemList) {
+                itemTypeNum = (String)map.get("group_number");
+                String itemTypeName = (String)map.get("group_name");
+                treeNodeList = (List)insuranceItemNodeMap.get(itemTypeNum);
+                if (treeNodeList == null) {
+                    treeNodeList = new ArrayList(10);
+                    insuranceItemNodeMap.put(itemTypeNum, treeNodeList);
+                }
+                ((List)treeNodeList).add(new TreeNode(itemTypeNum + PREFIX_SEPARATOR, String.valueOf(map.get("id")), (String)map.get("name")));
+                if (!itemTypeNodeMap.containsKey(itemTypeNum)) {
+                    TreeNode itemTreeNode = new TreeNode(ITEM_TYPE_II, itemTypeNum + PREFIX_SEPARATOR, itemTypeName);
+                    itemTreeNode.setExpend(isExpend);
+                    itemTreeNode.setIsOpened(isExpend);
+                    itemTypeNodeMap.put(itemTypeNum, itemTreeNode);
+                }
+            }
+            treeNodeList = new ArrayList(itemTypeNodeMap.size());
+            Iterator it = itemTypeNodeMap.entrySet().iterator();
+            while (it.hasNext()) {
+                Map.Entry<String, TreeNode> entry = (Map.Entry)it.next();
+                TreeNode typeNode = (TreeNode)entry.getValue();
+                typeNode.setChildren((List)insuranceItemNodeMap.get(entry.getKey()));
+                treeNodeList.add(typeNode);
+            }
+            itemRoot.setChildren(treeNodeList);
+            return totalNodeList;
+        }
+        else {
+            return totalNodeList;
+        }
+//
+//
+//
+//        insuranceItemList.forEach(item ->  {
+//            TreeNode itemNode = new TreeNode(ITEM_TYPE_II, ITEM_TYPE_II + "_" + item.get("id").toString(),
+//                    item.get("name").toString());
+//            treeNodeList.add(itemNode);
+//        });
+//
+//        return treeNodeList;
+    }
+
+    private static List<Map<String, Object>> getInsuranceItemList(String name,
+                                                               Map<String, Map<String, Map<String, Object>>> dataMap) {
+        return SWCStringUtils.isEmpty(name)
+                ? FormulaDataServiceHelper.mapToList(dataMap.get(INSURANCEITEM_KEY))
+                : FormulaDataServiceHelper.findItemByName(name, INSURANCEITEM_KEY, dataMap);
+    }
+
+    private static List<TreeNode> createRootNode(boolean isExpend) {
+        return createRootNode(isExpend, Collections.emptyList());
+    }
+
+    private static List<TreeNode> createRootNode(boolean isExpend, List<TreeNode> children) {
+        TreeNode itemRoot = new TreeNode("", ITEM_TYPE_II,
+                ResManager.loadKDString("险种项目-II", "FormulaItemOrFuncTreeHelper_1",
+                        "swc-hsas-business", new Object[0]));
+        itemRoot.setExpend(isExpend);
+        itemRoot.setIsOpened(isExpend);
+        itemRoot.setChildren(children);
+        return Collections.singletonList(itemRoot);
+    }
+
+}

+ 110 - 0
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/rptdata/DetailCompareReportDataPlugin.java

@@ -0,0 +1,110 @@
+package nckd.jxccl.sit.hcsi.rptdata;
+
+import kd.bos.algo.DataSet;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.entity.report.AbstractReportListDataPlugin;
+import kd.bos.entity.report.FilterInfo;
+import kd.bos.entity.report.ReportQueryParam;
+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.sdk.plugin.Plugin;
+import nckd.jxccl.sit.hcsi.utils.ReportUtils;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * Tyx 2025-10-22
+ * 社保明细差异对比表取数插件 nckd_detailcomparerpt
+ */
+public class DetailCompareReportDataPlugin extends AbstractReportListDataPlugin implements Plugin {
+
+    private static final Log logger = LogFactory.getLog(DetailCompareReportDataPlugin.class);
+    private static final String SINSURTASK = "hcsi_sinsurtask";
+    private static final String CALPERSON = "hcsi_calperson";
+    private static final String SINSURIMPTASK = "nckd_sinsurimptask";
+    private static final String SINSURTEMPDATA = "nckd_sinsurtempdata";
+
+
+    /**
+     * 查询数据:
+     * 1、先根据期间+参保单位获取到社保计算任务 【hcsi_sinsurtask】
+     * 2、根据社保计算任务获取到计算人员及明细 【hcsi_calperson】
+     * 3、根据期间+参保单位获取到外部系统导入任务和外部系统中间表数据 【nckd_sinsurimptask】和【nckd_sinsurtempdata】
+     * @param reportQueryParam
+     * @param o
+     * @return
+     * @throws Throwable
+     */
+    @Override
+    public DataSet query(ReportQueryParam reportQueryParam, Object o) throws Throwable {
+        logger.info("-------- begin query data --------");
+        // 社保计算任务过滤条件
+        QFilter taskFilter = buildTaskFilter(reportQueryParam);
+        // 查找社保计算任务
+        DynamicObjectCollection taskCols = queryDynamicObjectCollection(taskFilter, SINSURTASK, "id");
+        // 获取所有计算任务Id
+        List<Long> taskIds = taskCols.stream().map(obj -> obj.getLong("id")).collect(Collectors.toList());
+        // 根据计算任务Id+险种获取到计算结果明细数据
+        DataSet calPersonDataSet = queryCalPersonDetail(reportQueryParam, taskIds);
+        // 按照个人和单位分组汇总 type = 1为个人,type = 2为单位
+
+        return null;
+    }
+
+    public DataSet queryDataSet(ReportQueryParam reportQueryParam, QFilter filter, String entityName, String selectFields) {
+        HRBaseServiceHelper helper = new HRBaseServiceHelper(entityName);
+        DataSet dataSet = helper.queryDataSet("AttendanceRateReportQuery-Sbsent", selectFields, new QFilter[]{filter});
+        return dataSet;
+    }
+
+    public DynamicObjectCollection queryDynamicObjectCollection(QFilter filter, String entityName, String selectFields) {
+        HRBaseServiceHelper helper = new HRBaseServiceHelper(entityName);
+        DynamicObjectCollection cols = helper.queryOriginalCollection(selectFields, new QFilter[]{filter});
+        return cols;
+    }
+
+    /**
+     * 查询计算详情
+     * @param reportQueryParam
+     * @param taskIds
+     */
+    public DataSet queryCalPersonDetail(ReportQueryParam reportQueryParam, List<Long> taskIds) {
+        FilterInfo filterInfo = reportQueryParam.getFilter();
+        // 险种
+        DynamicObjectCollection welfareTypeCols = (DynamicObjectCollection)filterInfo.getFilterItem("nckd_welfaretype").getValue();
+        List<Long> welfareTypeIds = welfareTypeCols.stream().map(obj -> obj.getLong("id")).collect(Collectors.toList());
+        return ReportUtils.queryCalPersonDetail(welfareTypeIds, taskIds);
+    }
+
+    /**
+     * 分组汇总人员明细
+     *
+     * @param calPersonDataSet
+     * @return
+     */
+    public DataSet groupCalPersonDetail (DataSet calPersonDataSet) {
+        //calPersonDataSet.groupBy(new String[]{"welfarepayer","welfaretypeid","empnumber","empname","empidcard","type"}).sum
+        return calPersonDataSet;
+    }
+
+    /**
+     * 构建查询条件
+     * @param reportQueryParam
+     * @return
+     */
+    private QFilter buildTaskFilter(ReportQueryParam reportQueryParam) {
+        FilterInfo filterInfo = reportQueryParam.getFilter();
+        // 社保期间
+        DynamicObject period = (DynamicObject)filterInfo.getFilterItem("nckd_period").getValue();
+        // 参保单位
+        DynamicObject welfarepayer = (DynamicObject)filterInfo.getFilterItem("nckd_welfarepayer").getValue();
+        QFilter filter = new QFilter("sinsurperiod.id", QCP.equals, period.getPkValue());
+        filter.and("welfarepayer.id", QCP.equals, welfarepayer.getPkValue());
+        return filter;
+    }
+}

+ 58 - 0
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/utils/ReportUtils.java

@@ -0,0 +1,58 @@
+package nckd.jxccl.sit.hcsi.utils;
+
+import kd.bos.algo.DataSet;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
+import kd.hr.hbp.business.servicehelper.HRBaseServiceHelper;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class ReportUtils {
+
+    private static final String CALPERSON_ENTITY = "hcsi_calperson";
+    private static final String INSURANCEITEM_ENTITY = "sitbs_insuranceitem";
+    //参保单位,险种,工号,姓名,证件号,单位缴费金额 = 单位固定+单位缴费+单位补缴,个人缴费金额=个人固定+个人缴费+个人补缴
+    private static String CALPERSON_FIELDS = "welfarepayer.id as welfarepayer,entryentity.insuranceitem.group.id as welfaretypeid,"
+            +"empnumberdb as empnumber,namedb as empname,percre.number as empidcard,entryentity.famountvalue as value,"
+            +"case when entryentity.insuranceitem.insurancetypeattr.number in ('1005_S','1009_S','1011_S') then '1'"
+            +"     when entryentity.insuranceitem.insurancetypeattr.number in ('1006_S','1010_S','1012_S') then '2' end as type";
+    private static final String[] INSURANCEPROP = new String[]{"1005_S","1006_S","1009_S","1010_S","1011_S","1012_S"};
+
+
+    public ReportUtils() {
+
+    }
+    /**
+     * 获取人员计算详情数据
+     * @param welfareTypeIds
+     * @param taskIds
+     */
+    public static DataSet queryCalPersonDetail(List<Long> welfareTypeIds, List<Long> taskIds) {
+        List<Long> itemIds = queryInsuranceItem(welfareTypeIds);
+        QFilter filter = new QFilter("sinsurtask.id", QCP.in, taskIds);
+        filter.and("entryentity.insuranceitem.id", QCP.in, itemIds);
+        HRBaseServiceHelper helper = new HRBaseServiceHelper(CALPERSON_ENTITY);
+        CALPERSON_FIELDS = "welfarepayer.id as welfarepayer,entryentity.insuranceitem.group.id as welfaretypeid,"
+                +"empnumberdb as empnumber,namedb as empname,percre.number as empidcard,entryentity.amountvalue as value,"
+                +"case when entryentity.insuranceitem.insurancetypeattr.number in ('1005_S','1009_S','1011_S') then '1'"
+                +"     when entryentity.insuranceitem.insurancetypeattr.number in ('1006_S','1010_S','1012_S') then '2' end as type";
+        return helper.queryDataSet("DetailComReport", CALPERSON_FIELDS, new QFilter[]{filter});
+    }
+
+    /**
+     * 根据险种ID获取险种项目
+     * @param welfareTypeIds
+     * @return
+     */
+    public static List<Long> queryInsuranceItem(List<Long> welfareTypeIds) {
+        HRBaseServiceHelper helper = new HRBaseServiceHelper(INSURANCEITEM_ENTITY);
+        QFilter filter = new QFilter("group.id", QCP.in, welfareTypeIds);
+        filter.and("insurancetypeattr.number", QCP.in, INSURANCEPROP);
+        DynamicObjectCollection cols = helper.queryOriginalCollection("id", new QFilter[]{filter});
+        List<Long> itemIds = cols.stream().map(obj -> obj.getLong("id")).collect(Collectors.toList());
+        return itemIds;
+    }
+
+}

+ 498 - 0
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/init/plugin/other/DelayedRetirementDateCalcTask.java

@@ -0,0 +1,498 @@
+package nckd.jxccl.swc.init.plugin.other;
+
+import kd.bos.context.RequestContext;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.exception.KDException;
+import kd.bos.logging.Log;
+import kd.bos.logging.LogFactory;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
+import kd.bos.schedule.executor.AbstractTask;
+import kd.bos.servicehelper.BusinessDataServiceHelper;
+import kd.bos.servicehelper.QueryServiceHelper;
+import kd.bos.servicehelper.operation.SaveServiceHelper;
+import kd.bos.util.StringUtils;
+import kd.sdk.plugin.Plugin;
+
+
+import java.time.Instant;
+import java.time.LocalDate;
+import java.time.Period;
+import java.time.ZoneId;
+import java.time.temporal.ChronoUnit;
+import java.util.*;
+import java.util.stream.Collectors;
+
+
+/**
+ * 后台任务插件
+ * author: turborao
+ * date: 2025/10/20
+ * note: 延迟退休业务:对即将退休的人员,发出预警消息(预警信息要在原法定退休日期前3个月发给HR,
+ * 并且在员工最终确认生效的退休日期提前3个月再次预警)(HR),
+ * 业务人员收到消息,发送业务通知,告诉员工,原法定退休日期、新法定退休日期、
+ * 员工确认一个最终生效的时间(这些仅为业务人员的线下业务,不作为系统流程),
+ * 系统记录日期结果。延迟退休的算法可以根据中国人力资源和社会保障部的规定进行计算
+ */
+public class DelayedRetirementDateCalcTask  extends AbstractTask implements Plugin {
+    private static Log logger = LogFactory.getLog(DelayedRetirementDateCalcTask.class);
+
+    @Override
+    public void execute(RequestContext requestContext, Map<String, Object> map) throws KDException {
+
+        logger.info("延迟退休  开始执行任务");
+        /**
+         * 先计算员工社保档案(hcsi_sinsurfile)单据中延迟退休时间
+         */
+        int count = calcRetirementDate();
+        logger.info("延迟退休计算完成,本次更新数量:{};", count);
+        /**
+         * 然后将前三个月预警(法定退休日期)的退休员工保存到退休人员信息(nckd_retirewarning)单据中
+         */
+        int count1 = saveRetireWarning();
+        logger.info("延迟退休预警信息保存完成,本次更新数量:{};", count1);
+
+        logger.info("延迟退休  任务执行完成");
+    }
+
+    @Override
+    public boolean isSupportReSchedule() {
+        return true;
+    }
+
+    /**
+     * 将前三个月预警(法定退休日期)的退休员工保存到退休人员信息(nckd_retirewarning)单据中
+     * @return
+     * @throws KDException
+     */
+    public int saveRetireWarning() throws KDException {
+        // 假设你有一个 Date 对象
+        Date currentDate = new Date(); // 当前日期
+        // 将 Date 转换为 Instant 并减去8天
+        Instant ninetyDaysAgoInstant = currentDate.toInstant().plus(90, ChronoUnit.DAYS);
+        // 将 Instant 转换回 Date
+        Date ninetyDaysAgoDate = Date.from(ninetyDaysAgoInstant);
+        //取员工档案
+        String billKey = "hcsi_sinsurfile";
+        QFilter filter1 = new QFilter("iscurrentversion", QCP.equals, true); // 启用
+        QFilter filter2 = new QFilter("datastatus", QCP.equals, "1"); // 启用
+        QFilter filter3 = new QFilter("nckd_legaldate", QCP.large_equals, currentDate);
+        QFilter filter4 = new QFilter("nckd_legaldate", QCP.less_equals, ninetyDaysAgoDate);
+
+        String selectFields="id,employee.id,employee.number,employee.name,certificatenumber,nckd_recorddate,nckd_legaldate,nckd_newlegaldate";
+        DynamicObject[] recordDyn = BusinessDataServiceHelper.load(billKey, selectFields, new QFilter[]{filter1.and(filter2).and(filter3).and(filter4)});
+
+        Map<Long, DynamicObject> employeeFileMaps = Arrays.stream(recordDyn).collect(
+                Collectors.toMap(
+                        obj -> obj.getLong("employee.id"),
+                        obj -> obj,
+                        (k1, k2) -> k1
+                )
+        );
+        //将Map转换为List
+        List<Long> employeeIDs = employeeFileMaps.keySet().stream().collect(Collectors.toList());
+
+        ///查询 公司信息
+        QFilter filter7 = new QFilter("iscurrentdata", QCP.equals, true); // 启用
+        //QFilter filter8 = new QFilter("datastatus", QCP.equals, "1"); // 启用
+        QFilter filter9 = new QFilter("employee.id", QCP.in, employeeIDs);
+
+        String selectFields1 = "id,employee.id,company.id";
+        DynamicObjectCollection empposorgreDyns = QueryServiceHelper.query("hrpi_empposorgrel", selectFields1, new QFilter[]{filter7 ,filter9});
+
+        Map<Long, DynamicObject> empposorgreMap = (Map)empposorgreDyns.stream().collect(Collectors.toMap((obj) -> {
+            return obj.getLong("employee.id");
+        }, (obj) -> {
+            return obj;
+        }, (k1, k2) -> {
+            return k1;
+        }));
+
+
+        // 查人员基础信息中的生日和身份证号
+
+        QFilter filter12 = new QFilter("credentialstype.id", QCP.equals, 1010L); // 启用
+        QFilter filter13 = new QFilter("employee.id", QCP.in, employeeIDs);
+        String selectFields2="id,employee.id,number,birthday";
+        DynamicObjectCollection personDyns = QueryServiceHelper.query("hrpi_percre", selectFields2,new QFilter[]{ filter12, filter13});
+
+        Map<Long, DynamicObject> personMap = (Map)personDyns.stream().collect(Collectors.toMap((obj) -> {
+            return obj.getLong("employee.id");
+        }, (obj) -> {
+            return obj;
+        }, (k1, k2) -> {
+            return k1;
+        }));
+
+        // 查人员基础信息中的员工用工关系状态
+        QFilter filter21 = new QFilter("iscurrentdata", QCP.equals, true); // 启用
+        QFilter filter22 = new QFilter("ishired", QCP.equals, "1"); // 是否在职
+        QFilter filter23 = new QFilter("employee.id", QCP.in, employeeIDs);
+
+        String selectFields3="id,employee.id,laborrelstatus.id";
+        DynamicObjectCollection empentrelDyns = QueryServiceHelper.query("hrpi_empentrel", selectFields3,new QFilter[]{filter21, filter22, filter23});
+
+        Map<Long, DynamicObject> empentrelMap = (Map)empentrelDyns.stream().collect(Collectors.toMap((obj) -> {
+            return obj.getLong("employee.id");
+        }, (obj) -> {
+            return obj;
+        }, (k1, k2) -> {
+            return k1;
+        }));
+
+        //查退休人员信息数据
+        QFilter qFilter = new QFilter("nckd_person.id", QCP.in, employeeIDs);
+        List<Object> listIDs = QueryServiceHelper.queryPrimaryKeys("nckd_retirewarning",new QFilter[]{qFilter}, null, Integer.MAX_VALUE);
+        DynamicObject retirewarnDyn =  BusinessDataServiceHelper.newDynamicObject("nckd_retirewarning");
+        DynamicObject[] retirewarnDyns = BusinessDataServiceHelper.load(listIDs.toArray(),retirewarnDyn.getDynamicObjectType());
+
+        Map<Long, DynamicObject> retirewarnMap =
+                Arrays.stream(retirewarnDyns)
+                        .collect(Collectors.toMap(
+                                detail -> detail.getLong("nckd_person.id"),
+                                detail -> detail, // 整个 DynamicObject 作为 value
+                                (existing, replacement) -> existing // 保留前面的值
+                        ));
+
+        //在职员工ID  将Map转换为List
+        List<Long> employeeHiredIDs = empentrelMap.keySet().stream().collect(Collectors.toList());
+
+
+        ArrayList<DynamicObject> retirewarnDynList = new ArrayList<>();
+
+        for (Long employeeID : employeeHiredIDs) {
+            DynamicObject dyn = retirewarnMap.get(employeeID);
+            DynamicObject employeeFileDyn = employeeFileMaps.get(employeeID);
+            if(dyn ==  null){
+                dyn = BusinessDataServiceHelper.newDynamicObject("nckd_retirewarning");
+                dyn.set("billno", employeeFileDyn.getString("employee.number"));
+                //员工
+                dyn.set("nckd_person",employeeID);
+                dyn.set("billstatus", "A");
+            }
+            if(employeeFileDyn != null) {
+                Date startDate = employeeFileDyn.getDate("nckd_recorddate");
+                Date legaldate = employeeFileDyn.getDate("nckd_legaldate");
+                Date newlegaldate = employeeFileDyn.getDate("nckd_newlegaldate");
+                dyn.set("nckd_recorddate", employeeFileDyn.getDate("nckd_recorddate"));
+
+
+                if(legaldate != null) {
+                    dyn.set("nckd_legaldate", legaldate);
+                    String oldYear = caclOldYear(startDate, legaldate);
+                    dyn.set("nckd_legalage", oldYear);
+                }
+                if(newlegaldate != null){
+                    dyn.set("nckd_newlegaldate", newlegaldate);
+                    String newOldYear = caclOldYear(startDate, newlegaldate);
+                    dyn.set("nckd_newlegalage", newOldYear);
+                }
+            }
+            DynamicObject employeeDyn = personMap.get(employeeID);
+            if(employeeDyn != null) {
+                Date birthday =  employeeDyn.getDate("birthday");
+                if(birthday != null) {
+                    dyn.set("nckd_birthday", birthday);
+                }
+                dyn.set("nckd_idcard", employeeDyn.getString("number"));
+            }
+            DynamicObject empposorgreDyn = empposorgreMap.get(employeeID);
+            if(empposorgreDyn != null) {
+                dyn.set("nckd_company",empposorgreDyn.getLong("company.id"));
+            }
+            DynamicObject empentreDyn = empentrelMap.get(employeeID);
+            if(empentreDyn != null) {
+                dyn.set("nckd_laborreltype",empentreDyn.getLong("laborrelstatus.id"));
+            }
+
+            retirewarnDynList.add(dyn);
+
+        }
+
+        int length = 0;
+        if(retirewarnDynList.size() != 0) {
+            //保存
+            Object[] update = SaveServiceHelper.save(retirewarnDynList.toArray(new DynamicObject[0]));
+            length = update.length;
+
+        }
+        return length;
+
+    }
+
+    /**
+     * 计算延迟退休时间
+     * @throws KDException
+     */
+    public int calcRetirementDate() throws KDException {
+        // 假设你有一个 Date 对象
+        Date currentDate = new Date(); // 当前日期
+        // 将 Date 转换为 Instant 并减去8天
+        Instant threeDaysAgoInstant = currentDate.toInstant().minus(8, ChronoUnit.DAYS);
+        // 将 Instant 转换回 Date
+        Date threeDaysAgoDate = Date.from(threeDaysAgoInstant);
+        //取员工档案
+        String billKey = "hcsi_sinsurfile";
+        QFilter filter1 = new QFilter("iscurrentversion", QCP.equals, true); // 启用
+        QFilter filter2 = new QFilter("datastatus", QCP.equals, "1"); // 启用
+        QFilter filter5 = new QFilter("modifytime", QCP.large_equals, threeDaysAgoDate);
+
+        String selectFields="id,employee.id,employee.number,nckd_recorddate,nckd_legaldate,nckd_newlegaldate";
+        DynamicObject[] datas = BusinessDataServiceHelper.load(billKey, selectFields, new QFilter[]{filter1.and(filter2).and(filter5)});
+
+        Map<Long, DynamicObject> employeeFileMaps = Arrays.stream(datas).collect(
+                Collectors.toMap(
+                        obj -> obj.getLong("employee.id"),
+                        obj -> obj,
+                        (k1, k2) -> k1
+                )
+        );
+        //将Map转换为List
+        List<Long> employeeIDs = employeeFileMaps.keySet().stream().collect(Collectors.toList());
+
+        ///查询 干部信息
+        QFilter filter7 = new QFilter("iscurrentdata", QCP.equals, true); // 启用
+        //QFilter filter8 = new QFilter("datastatus", QCP.equals, "1"); // 启用
+        QFilter filter9 = new QFilter("employee.id", QCP.in, employeeIDs);
+
+        String selectFields1 = "id,employee.id,employee.number,position.nckd_jobseq.number";
+        DynamicObjectCollection empposorgreDyns = QueryServiceHelper.query("hrpi_empposorgrel", selectFields1, new QFilter[]{filter7 ,filter9});
+
+        Map<Long, DynamicObject> empposorgreMap = (Map)empposorgreDyns.stream().collect(Collectors.toMap((obj) -> {
+            return obj.getLong("employee.id");
+        }, (obj) -> {
+            return obj;
+        }, (k1, k2) -> {
+            return k1;
+        }));
+
+        QFilter filter11 = new QFilter("iscurrentversion", QCP.equals, true); // 启用
+        QFilter filter12 = new QFilter("datastatus", QCP.equals, "1"); // 启用
+        QFilter filter13 = new QFilter("id", QCP.in, employeeIDs);
+        // 查人员基础信息中的性别
+        String selectFields2="id,number,name,birthday,gender.masterid";
+        DynamicObjectCollection personDyns = QueryServiceHelper.query("hrpi_employee", selectFields2,new QFilter[]{filter11, filter12, filter13});
+
+        Map<Long, DynamicObject> personMap = (Map)personDyns.stream().collect(Collectors.toMap((obj) -> {
+            return obj.getLong("id");
+        }, (obj) -> {
+            return obj;
+        }, (k1, k2) -> {
+            return k1;
+        }));
+
+        ArrayList<DynamicObject> perList = new ArrayList<>();
+        for (DynamicObject data : datas) {
+            int jobType = 2;
+            int gender = 0;
+            Long personId = data.getLong("employee.id");
+            DynamicObject person  = personMap.get(personId);
+            Long genderID = person.getLong("gender.masterid");
+            Date birthday = person.getDate("birthday");
+            if(genderID == 1020L){
+                gender = 2;
+            }else if (genderID == 1010L){
+                gender = 1;
+            }
+            if (gender == 2) {
+                //职位序列 为技能序列(03)的为工人,其他为管理干部
+                DynamicObject empposorgre = empposorgreMap.get(personId);
+                if(empposorgre!= null) {
+                    String jobSeq = empposorgre.getString("position.nckd_jobseq.number");
+                    if (!StringUtils.isEmpty(jobSeq)) {
+                        if (jobSeq.equals("03")) {
+                            jobType = 2;
+                        } else {
+                            jobType = 1;
+                        }
+                    }
+                }
+            }
+            Date personBirthday = data.getDate("nckd_recorddate");
+            if(personBirthday == null){
+                personBirthday = birthday;
+                data.set("nckd_recorddate", birthday);
+            }
+            if(personBirthday != null && gender != 0 ){
+
+                LocalDate originalRetirementDate = retirementCalculator(personBirthday,gender,jobType);
+                Date originalRetirementDate1 = Date.from(originalRetirementDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
+                if(originalRetirementDate1 != null) {
+                    data.set("nckd_legaldate", originalRetirementDate1);
+                }
+
+                LocalDate delayedRetirementDate = delayedRetirementCalculator(personBirthday,gender,jobType);
+                if(delayedRetirementDate != null ) {
+                    Date delayedRetirementDate1 = Date.from(delayedRetirementDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
+                    data.set("nckd_newlegaldate", delayedRetirementDate1);
+                }else{
+                    if(originalRetirementDate1 != null) {
+                        data.set("nckd_newlegaldate", originalRetirementDate1);
+                    }
+                }
+                perList.add(data);
+            }
+
+        }
+
+        int length = 0;
+        if(perList.size() != 0) {
+            //保存
+            Object[] update = SaveServiceHelper.save(perList.toArray(new DynamicObject[0]));
+            length = update.length;
+
+        }
+        return length;
+    }
+
+
+    /**
+     * 根据用户的出生日期、性别和职业类型来计算法定退休日期
+     *
+     * @param birthdate 用户的出生日期
+     * @param gender 用户的性别,1表示男性,2表示女性
+     * @param jobType 用户的职业类型,1表示55岁退休的职业,2表示50岁退休的职业
+     * @return 用户的法定退休日期,如果输入性别无效则返回null
+     */
+    public LocalDate retirementCalculator(Date birthdate, int gender, int jobType ){
+        // 获取用户的出生日期
+        LocalDate localDate = birthdate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
+
+        // 获取年份、月份、日
+        int birthYear = localDate.getYear();
+        int birthMonth = localDate.getMonthValue();
+        int birthDay = localDate.getDayOfMonth();
+
+        LocalDate birthDate = LocalDate.of(birthYear, birthMonth, birthDay);
+        LocalDate originalRetirementDate;
+        int initialRetirementAge;
+
+        if (gender == 1) { // 男性
+            initialRetirementAge = 60;
+        } else if (gender == 2) { // 女性
+            if (jobType == 1) {
+                initialRetirementAge = 55;
+            } else {
+                initialRetirementAge = 50;
+            }
+        } else {
+            return null;
+        }
+        // 计算法定退休日期
+        originalRetirementDate = birthDate.plusYears(initialRetirementAge);
+        return originalRetirementDate;
+    }
+
+    /**
+     * 根据用户的出生日期、性别和职业类型来计算延迟退休日期
+     *
+     * @param birthdate 出生日期
+     * @param gender 性别,1表示男性,2表示女性
+     * @param jobType 职业类型,1表示55岁退休的职业,2表示50岁退休的职业
+     * @return 预计的延迟退休日期
+     */
+    public LocalDate delayedRetirementCalculator (Date birthdate,int gender,int jobType ) {
+
+        // 获取用户的出生日期
+        LocalDate localDate = birthdate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
+        // 获取年份、月份、日
+        int birthYear = localDate.getYear();
+        int birthMonth = localDate.getMonthValue();
+        int birthDay = localDate.getDayOfMonth();
+
+        //int gender = 2;
+        //System.out.println("性别为:女55");
+
+        LocalDate birthDate = LocalDate.of(birthYear, birthMonth, birthDay);
+        LocalDate startDate = LocalDate.of(2025, 1, 1);
+        LocalDate originalRetirementDate;
+        int initialRetirementAge;
+        int maxDelayMonths = 0;
+
+        if (gender == 1) { // 男性
+            if (birthYear >= 1965) {
+                initialRetirementAge = 60;
+                maxDelayMonths = 36; // 最多延迟36个月至63周岁
+            }else{
+                return null;
+            }
+        } else if (gender == 2) { // 女性
+            if (jobType == 1) {
+                if (birthYear >= 1970) {
+                    initialRetirementAge = 55;
+                    maxDelayMonths = 36; // 最多延迟36个月至58周岁
+                }else{
+                    return null;
+                }
+            } else {
+                if (birthYear >= 1975) {
+                    initialRetirementAge = 50;
+                    maxDelayMonths = 60; // 最多延迟60个月至55周岁
+                }else{
+                    return null;
+                }
+            }
+        } else {
+            return null;
+        }
+
+        // 计算法定退休日期
+        originalRetirementDate = birthDate.plusYears(initialRetirementAge);
+
+        // 手动计算两个日期之间的月份数差异
+        long monthsBetween = (originalRetirementDate.getYear() - startDate.getYear()) * 12L
+                + originalRetirementDate.getMonthValue() - startDate.getMonthValue();
+
+        int delayedMonths;
+        if (gender == 1 || (gender == 2 && jobType == 1)) {
+            delayedMonths = (int)Math.floor(monthsBetween / 4.0) + 1;
+        } else {
+            delayedMonths = (int)Math.floor(monthsBetween / 2.0) + 1;
+        }
+
+        // 应用最大延迟月数限制
+        if(delayedMonths > maxDelayMonths) {
+            delayedMonths = maxDelayMonths;
+        }
+
+        // 计算延迟后的退休日期
+        LocalDate retirementDate = originalRetirementDate.plusMonths(delayedMonths);
+
+        return retirementDate;
+
+    }
+    /**
+     * 涉及特殊工种的计算
+     * 若员工在特殊工种累计任职时长超过该特殊工种规定的可提前退休标准,可在规定的退休年龄基础上提前5年退休。
+     * 若涉及到多段特殊工种任职,须进行折算统计,举例如下:某员工涉及三段特殊工种任职,分别是3年,6年,1年,
+     * 对应特殊工种可天退休标准为8、9、10,则3/8+6/9+1/10=1.141666667,结果大于1,符合条件,反之就不符合。
+     * /
+
+    /**
+     * 计算年龄
+     * @param startDate
+     * @param endDate
+     * @return  示例:"60岁6个月"
+     */
+
+    public String caclOldYear(Date startDate, Date endDate) {
+
+        LocalDate startLocalDate = startDate.toInstant()
+                .atZone(ZoneId.systemDefault())
+                .toLocalDate();
+
+        LocalDate endLocalDate = endDate.toInstant()
+                .atZone(ZoneId.systemDefault())
+                .toLocalDate();
+
+        // 计算时间差
+        Period period = Period.between(startLocalDate, endLocalDate);
+
+        int years = period.getYears();
+        int months = period.getMonths();
+
+        String result = years + "岁" + months + "个月";
+        return result;
+    }
+}

+ 14 - 0
code/wtc/nckd-jxccl-wtc/build.gradle

@@ -0,0 +1,14 @@
+/*
+ * This is a kingdee cosmic template project that is automatically generated by the Kingdee cosmic development assistant plugin. 
+ * If there are any issues during the use process, you can provide feedback to the kingdee developer community website.
+ * Website: https://developer.kingdee.com/developer?productLineId=29
+ * Author: liebin.zheng
+ * Generate Date: 2025-10-23 16:09:09
+ */
+
+dependencies {
+	api project(':nckd-jxccl-base-common')
+	api project(':nckd-jxccl-base-helper')
+} 
+
+

+ 0 - 0
code/wtc/nckd-jxccl-wtc/src/main/java/nckd/jxccl/wtc/init/business/.gitkeep


+ 22 - 0
code/wtc/nckd-jxccl-wtc/src/main/java/nckd/jxccl/wtc/init/common/AppflgConstant.java

@@ -0,0 +1,22 @@
+/**
+ * This is a kingdee cosmic template project that is automatically generated by the Kingdee cosmic development assistant plugin. 
+ * If there are any issues during the use process, you can provide feedback to the kingdee developer community website.
+ * Website: https://developer.kingdee.com/developer?productLineId=29
+ * Author: liebin.zheng
+ * Generate Date: 2025-10-23 16:09:09
+ */
+package nckd.jxccl.wtc.init.common;
+
+/**
+ * wtc云init应用-通用常量类<br>
+ * 代码中不能存在硬编码敏感信息,如账号、密码、http外链、ftp外链、邮箱等。<br>
+ * 标识或缓存的常量,需以"KEY_"、"FID_"、"ENTRY_"或"SUBENTRY_"作为变量的前缀。<br>
+ *
+ * @author nckd
+ * @date 2025-10-23 16:09:09
+ */
+public class AppflgConstant {
+	
+	public static final String KEY_APP_NAME = "wtc-init";
+
+}

+ 0 - 0
code/wtc/nckd-jxccl-wtc/src/main/java/nckd/jxccl/wtc/init/mservice/.gitkeep


+ 0 - 0
code/wtc/nckd-jxccl-wtc/src/main/java/nckd/jxccl/wtc/init/plugin/form/.gitkeep


+ 0 - 0
code/wtc/nckd-jxccl-wtc/src/main/java/nckd/jxccl/wtc/init/plugin/operate/.gitkeep


+ 0 - 0
code/wtc/nckd-jxccl-wtc/src/main/java/nckd/jxccl/wtc/init/plugin/other/.gitkeep


+ 0 - 0
code/wtc/nckd-jxccl-wtc/src/main/java/nckd/jxccl/wtc/init/plugin/report/.gitkeep


+ 0 - 0
code/wtc/nckd-jxccl-wtc/src/main/java/nckd/jxccl/wtc/init/plugin/workflow/.gitkeep


+ 0 - 0
code/wtc/nckd-jxccl-wtc/src/main/java/nckd/jxccl/wtc/init/webapi/.gitkeep


+ 90 - 0
code/wtc/nckd-jxccl-wtc/src/main/java/nckd/jxccl/wtc/wtabm/vaapply/VaApplyBillEditEx.java

@@ -0,0 +1,90 @@
+package nckd.jxccl.wtc.wtabm.vaapply;
+
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.entity.datamodel.IDataModel;
+import kd.bos.entity.datamodel.events.AfterDeleteRowEventArgs;
+import kd.bos.entity.datamodel.events.PropertyChangedArgs;
+import kd.bos.form.events.BeforeDoOperationEventArgs;
+import kd.bos.form.events.ClosedCallBackEvent;
+import kd.bos.form.operate.AbstractOperate;
+import kd.bos.logging.Log;
+import kd.bos.logging.LogFactory;
+import kd.hr.hbp.formplugin.web.HRCoreBaseBillEdit;
+import kd.wtc.wtbs.common.util.third.util.StringUtils;
+import nckd.jxccl.wtc.wtabm.web.common.util.WtcUtils;
+
+import java.util.Date;
+
+/**
+ * Tyx
+ * 2025-09-29
+ * 休假申请单扩展表单插件
+ */
+public class VaApplyBillEditEx extends HRCoreBaseBillEdit {
+
+    private static final Log log = LogFactory.getLog(VaApplyBillEditEx.class);
+
+    /**
+     * 获取历史休假明细信息,填充到单据上nckd_hisentryentity单据体上
+     * @param closedCallBackEvent
+     */
+    @Override
+    public void closedCallBack(ClosedCallBackEvent closedCallBackEvent) {
+        super.closedCallBack(closedCallBackEvent);
+        String actionId = closedCallBackEvent.getActionId();
+        IDataModel model = this.getModel();
+        DynamicObjectCollection cols = model.getEntryEntity("entryentity");
+        if (StringUtils.equalsAny(actionId, new CharSequence[]{"newentry", "editrow"})) {
+            DynamicObject entry = cols.get(0);
+            // 当前休假人员
+            Long employeeId = Long.valueOf(model.getValue("attfilebasef7.employee.id").toString());
+
+            // 休假开始日期
+            Date date = entry.getDate("entrystartdate");
+            // 休假类型编码
+
+            String typeNumber = entry.getString("entryvacationtype.number");
+
+            log.info("-------- 开始查询历史休假明细 empId:{}, typeNumber:{}", employeeId, typeNumber);
+            DynamicObjectCollection historyBillCols = WtcUtils.getHistoryVaApplyInfos(employeeId, date, typeNumber);
+            log.info("-------- 结束查询历史休假明细 条数:{}", historyBillCols.size());
+
+            for (DynamicObject historyDyn : historyBillCols) {
+                int row = model.createNewEntryRow("nckd_hisentryentity");
+                model.setValue("nckd_hisvaltype", historyDyn.getString("entryentity.entryvacationtype.name"), row);
+                model.setValue("nckd_hisstartdate", historyDyn.getDate("startdate"), row);
+                model.setValue("nckd_hisenddate", historyDyn.getDate("enddate"), row);
+                model.setValue("nckd_hisapplytime", historyDyn.getBigDecimal("applytime"), row);
+            }
+        }
+    }
+
+    @Override
+    public void beforeDoOperation(BeforeDoOperationEventArgs args) {
+        super.beforeDoOperation(args);
+        AbstractOperate op = (AbstractOperate)args.getSource();
+        String operateKey = op.getOperateKey();
+        if (StringUtils.equals(operateKey, "opaddnewpage")) {
+            args.setCancel(true);
+        }
+    }
+
+    @Override
+    public void propertyChanged(PropertyChangedArgs e) {
+        super.propertyChanged(e);
+    }
+
+    /**
+     * 删除行后清除历史休假明细单据体
+     * @param e
+     */
+    @Override
+    public void afterDeleteRow(AfterDeleteRowEventArgs e) {
+        super.afterDeleteRow(e);
+        if("entryentity".equals(e.getEntryProp().getName())) {
+            IDataModel model = this.getModel();
+            model.deleteEntryData("nckd_hisentryentity");
+        }
+    }
+}

+ 59 - 0
code/wtc/nckd-jxccl-wtc/src/main/java/nckd/jxccl/wtc/wtabm/vaapply/VaInfoEditEx.java

@@ -0,0 +1,59 @@
+package nckd.jxccl.wtc.wtabm.vaapply;
+
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.dataentity.utils.ObjectUtils;
+import kd.bos.entity.datamodel.IDataModel;
+import kd.bos.entity.datamodel.events.PropertyChangedArgs;
+import kd.bos.form.IFormView;
+import kd.bos.logging.Log;
+import kd.bos.logging.LogFactory;
+import kd.hr.hbp.formplugin.web.HRDataBaseEdit;
+import nckd.jxccl.wtc.wtabm.web.common.util.WtcUtils;
+
+import java.util.Date;
+
+/**
+ * Tyx 2025-10-13
+ *
+ * 休假信息_单人单类型【wtabm_vainfosingle】表单插件
+ */
+public class VaInfoEditEx extends HRDataBaseEdit {
+
+    private static final Log log = LogFactory.getLog(VaInfoEditEx.class);
+
+    @Override
+    public void propertyChanged(PropertyChangedArgs e) {
+        super.propertyChanged(e);
+        String name = e.getProperty().getName();
+        DynamicObject dataEntity = this.getModel().getDataEntity();
+        if(name.equals("datechange") || name.equals("vacationtype")) {
+            String typeNumber = dataEntity.getString("vacationtype.number");
+            Date startDate = dataEntity.getDate("startdate");
+            Date endDate = dataEntity.getDate("enddate");
+            // 如果这些都不为空
+            if(!(ObjectUtils.isEmpty(typeNumber) || ObjectUtils.isEmpty(startDate) || ObjectUtils.isEmpty(endDate))) {
+                // 获取父页面的employeeId
+                IFormView parentView = this.getView().getParentView();
+                IDataModel parentModel = parentView.getModel();
+                DynamicObject parentDataEntity = parentModel.getDataEntity();
+                Long employeeId = parentDataEntity.getLong("attfilebasef7.employee.id");
+                log.info("-------- 开始查询历史休假明细 empId:{}, typeNumber:{}", employeeId, typeNumber);
+                DynamicObjectCollection historyBillCols = WtcUtils.getHistoryVaApplyInfos(employeeId, startDate, typeNumber);
+                log.info("-------- 结束查询历史休假明细 条数:{}", historyBillCols.size());
+
+                // 先删除现有的历史休假明细数据
+                parentModel.deleteEntryData("nckd_hisentryentity");
+                for (DynamicObject historyDyn : historyBillCols) {
+                    int row = parentModel.createNewEntryRow("nckd_hisentryentity");
+                    parentModel.setValue("nckd_hisvaltype", historyDyn.getString("entryentity.entryvacationtype.name"), row);
+                    parentModel.setValue("nckd_hisstartdate", historyDyn.getDate("startdate"), row);
+                    parentModel.setValue("nckd_hisenddate", historyDyn.getDate("enddate"), row);
+                    parentModel.setValue("nckd_hisapplytime", historyDyn.getBigDecimal("applytime"), row);
+                }
+                // 刷新父页面
+                this.getView().sendFormAction(parentView);
+            }
+        }
+    }
+}

+ 47 - 0
code/wtc/nckd-jxccl-wtc/src/main/java/nckd/jxccl/wtc/wtabm/web/common/constant/WtcConstant.java

@@ -0,0 +1,47 @@
+package nckd.jxccl.wtc.wtabm.web.common.constant;
+
+import kd.hr.hbp.business.servicehelper.HRBaseServiceHelper;
+
+public class WtcConstant {
+
+    public static final String WTC_APPLY_ENTITY = "";
+
+    /* 考勤相关参数标识 */
+    public static final String WTC_PARAM_ENTITY = "nckd_wtparam";
+
+    /* 事假编码 */
+    public static final String PERSONALLEAVE_NUMBER = "1010_S";
+
+    /* 病假编码 */
+    public static final String SICKLEAVE_NUMBER = "1020_S";
+
+    /* 年假编码 */
+    public static final String ANNUALLEAVE_NUMBER = "1030_S";
+
+    /* 婚假编码 */
+    public static final String MARRIAGE_NUMBER = "1050_S";
+
+    /* 服务年限Helper */
+    public static final HRBaseServiceHelper PERSERLEN_HELPER = new HRBaseServiceHelper("hrpi_perserlen");
+
+    /* 员工Helper */
+    public static final HRBaseServiceHelper EMPLOYEE_HELPER = new HRBaseServiceHelper("hrpi_employee");
+
+    /* 婚姻状况-已婚-ID */
+    public static final Long STATUS_MARRIAGE = 1020L;
+
+    /* 考勤记录-明细项目信息Helper */
+    public static final HRBaseServiceHelper RECORDDETAIL_HEPLER = new HRBaseServiceHelper("wtte_attrecorddetail");
+
+    /* 考勤记录-明细人员信息Helper */
+    public static final HRBaseServiceHelper RECORDBASE_HEPLER = new HRBaseServiceHelper("wtte_attrecordbase");
+
+    /* 考勤项目-应出勤天数编码 */
+    public static final String SCHEDULED_NUMBER = "AT_1010";
+
+    /* 考勤项目-所有假期-结果时长的编码*/
+    public static final String[] LEAVE_NUMBERS = new String[] {"LE_1220_S","LE_1200_S","LE_1190_S","LE_1180_S","LE_1210_S","LE_1270_S","LE_1230_S","LE_1170_S","LE_1240_S"};
+
+    /* 考勤项目-旷工天数编码*/
+    public static final String ABSENT_NUMBER = "EX_1140_S";
+}

+ 108 - 0
code/wtc/nckd-jxccl-wtc/src/main/java/nckd/jxccl/wtc/wtabm/web/common/util/WtcUtils.java

@@ -0,0 +1,108 @@
+package nckd.jxccl.wtc.wtabm.web.common.util;
+
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+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.BusinessDataServiceHelper;
+import kd.bos.servicehelper.QueryServiceHelper;
+import kd.hr.haos.business.domain.adminorg.service.impl.AdminOrgQueryServiceHelper;
+import org.apache.commons.lang3.ObjectUtils;
+
+import java.time.LocalDate;
+import java.time.ZoneId;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * Tyx
+ * 2025-09-28
+ * 考勤模块工具类
+ */
+public class WtcUtils {
+
+    private static final Log log = LogFactory.getLog(WtcUtils.class);
+
+    /**
+     * 获取人员date所在年份的休假信息
+     * // @param dyn 休假单数据包
+     * @param employeeId 员工Id
+     * @param date 休假开始日期
+     * @param vaTypeNumber 休假类型编码
+     */
+    public static DynamicObjectCollection getHistoryVaApplyInfos (Long employeeId, Date date, String vaTypeNumber) {
+
+        // 获取date所在年份的第一天和最后一天
+        LocalDate localDate = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
+        LocalDate startDate = LocalDate.of(localDate.getYear(), 1, 1);
+        LocalDate endDate = LocalDate.of(localDate.getYear(), 12, 31);
+
+        // 日期过滤
+        QFilter dateFilter = new QFilter("enddate", QCP.large_equals, startDate);
+        dateFilter.and("enddate", QCP.less_equals, endDate);
+
+        // 人员
+        QFilter personFilter = new QFilter("attfilebasef7.employee.id", QCP.equals, employeeId);
+
+        // 单据版本过滤(存在变更,取最新的且时长不为0的),这里直接取审批通过的
+        QFilter statusFilter = new QFilter("billstatus", QCP.in, new String[]{"A","B","C"});
+
+        // 休假类型过滤
+        QFilter typeFilter = new QFilter("entryentity.entryvacationtype.number", QCP.equals, vaTypeNumber);
+
+        // 查询字段
+        String selectFields = "startdate,enddate,applytime,billstatus,entryentity.entryvacationtype.name";
+
+        // 查询数据
+        DynamicObjectCollection billCols = QueryServiceHelper.query("wtabm_vaapply", selectFields, new QFilter[]{dateFilter, personFilter, statusFilter, typeFilter});
+        return billCols;
+    }
+
+    /**
+     * 获取参数
+     * @param number
+     * @param entityName
+     * @return
+     */
+    public static Map<String, String> getWtcParams(String number, String entityName) {
+        String selectField = "nckd_entryentity.nckd_key, nckd_entryentity.nckd_value";
+        QFilter qFilter = new QFilter("number", "=", number);
+        DynamicObject commonParam = BusinessDataServiceHelper.loadSingle(entityName, selectField, qFilter.toArray());
+        if (ObjectUtils.isEmpty(commonParam)) {
+            return null;
+        } else {
+            DynamicObjectCollection entryentity = commonParam.getDynamicObjectCollection("nckd_entryentity");
+            if (entryentity != null && entryentity.size() != 0) {
+                Map<String, String> mapentity = (Map)entryentity.stream().collect(Collectors.toMap((k) -> {
+                    return k.getString("nckd_key");
+                }, (v) -> {
+                    return v.getString("nckd_value");
+                }, (existing, replacement) -> {
+                    return existing;
+                }));
+                return mapentity;
+            } else {
+                return null;
+            }
+        }
+    }
+
+
+    /**
+     * 获取下级组织
+     *
+     * @param adminOrgDyn
+     * @return
+     */
+    public static Set getSubOrgFilters (DynamicObject adminOrgDyn, String field) {
+        List<Long> adminOrgList = new ArrayList<Long>();
+        adminOrgList.add(adminOrgDyn.getLong("id"));
+        List<Map<String, Object>> subOrgs = AdminOrgQueryServiceHelper.batchQuerySubOrg(adminOrgList, new Date(), null);
+        Set subOrgIdset = subOrgs.stream().map(i -> i.get("orgId")).collect(Collectors.toSet());
+        return subOrgIdset;
+    }
+
+
+}

+ 147 - 0
code/wtc/nckd-jxccl-wtc/src/main/java/nckd/jxccl/wtc/wtabm/web/service/VaApplyValidateService.java

@@ -0,0 +1,147 @@
+package nckd.jxccl.wtc.wtabm.web.service;
+
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+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.QueryServiceHelper;
+import nckd.jxccl.wtc.wtabm.web.common.constant.WtcConstant;
+import nckd.jxccl.wtc.wtabm.web.common.util.WtcUtils;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.ZoneId;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+public class VaApplyValidateService {
+
+    private static final Log log = LogFactory.getLog(VaApplyValidateService.class);
+
+    /**
+     * 当员工当年事假N天以上,不允许进行当年度年假申请
+     * @param bill 请假单数据包
+     * @return
+     */
+    public static String checkOverTimeByPersonalLeave(DynamicObject bill) {
+        String msg = null;
+        // 先判断当前单据是否请年假
+        //DynamicObjectCollection vaTypeCols = bill.getDynamicObjectCollection("vacationtypelist");
+        //String vaTypeNumber = vaTypeCols.get(0).getDynamicObject("fbasedataid").getString("number");
+        DynamicObjectCollection entryCols = bill.getDynamicObjectCollection("entryentity");
+        String vaTypeNumber = entryCols.get(0).getString("entryvacationtype.number");
+        if(vaTypeNumber.equals(WtcConstant.ANNUALLEAVE_NUMBER)) {
+            Map<String, String> params = WtcUtils.getWtcParams("WTC", WtcConstant.WTC_PARAM_ENTITY);
+            // N天
+            BigDecimal standardDays = new BigDecimal(params.get("PersonalStandardDays"));
+            // 获取历史休事假信息
+            List<String> vaTypeNumbers = new ArrayList<String>();
+            vaTypeNumbers.add(WtcConstant.PERSONALLEAVE_NUMBER);
+            DynamicObjectCollection hisBillCols = getVaApplyInfos(bill, vaTypeNumbers);
+            // 汇总
+            BigDecimal totalTime = hisBillCols.stream().map(dyn -> dyn.getBigDecimal("applytime")).reduce(BigDecimal.ZERO, BigDecimal::add);
+            if(totalTime.compareTo(standardDays) >= 0) {
+                msg = String.format("本年度已请事假(%s)天,不允许申请年假!", totalTime);
+            }
+        }
+        return msg;
+    }
+
+    /**
+     * 社会工龄1年以上10年以下的员工,当年病假累计2个月以上,不允许进行当年度年假申请
+     * @param bill 请假单数据包
+     * @return
+     */
+    public static String checkOverTimeByAnnualSickLeave (DynamicObject bill) {
+        String msg = "";
+        Long employeeId = bill.getLong("attfilebasef7.employee.id");
+        // 获取社会工龄:人员档案-服务年限-参加工作年限
+        BigDecimal workYear = getWorkYearByEmployeeId(employeeId);
+        // 判断是否在1-10年之间
+        if(workYear.compareTo(new BigDecimal("1")) >= 0 && workYear.compareTo(new BigDecimal("10")) <= 0) {
+            // 先判断当前单据是否请年假
+            //DynamicObjectCollection vaTypeCols = bill.getDynamicObjectCollection("vacationtypelist");
+            //String vaTypeNumber = vaTypeCols.get(0).getDynamicObject("fbasedataid").getString("number");
+            DynamicObjectCollection entryCols = bill.getDynamicObjectCollection("entryentity");
+            String vaTypeNumber = entryCols.get(0).getString("entryvacationtype.number");
+            if (vaTypeNumber.equals(WtcConstant.ANNUALLEAVE_NUMBER)) {
+                Map<String, String> params = WtcUtils.getWtcParams("WTC", WtcConstant.WTC_PARAM_ENTITY);
+                BigDecimal standardDays = new BigDecimal(params.get("AnnualSickStandardDays"));
+                // 获取历史休事假信息
+                List<String> vaTypeNumbers = new ArrayList<String>();
+                vaTypeNumbers.add(WtcConstant.ANNUALLEAVE_NUMBER);
+                vaTypeNumbers.add(WtcConstant.SICKLEAVE_NUMBER);
+                DynamicObjectCollection hisBillCols = getVaApplyInfos(bill, vaTypeNumbers);
+                // 汇总
+                BigDecimal totalTime = hisBillCols.stream().map(dyn -> dyn.getBigDecimal("applytime")).reduce(BigDecimal.ZERO, BigDecimal::add);
+                if (totalTime.compareTo(standardDays) >= 0) {
+                    msg = String.format("本年度年病假已超过(%s)天,不允许申请年假!", standardDays);
+                }
+            }
+        }
+        return msg;
+    }
+
+    /**
+     * 获取当年度休假单数据包
+     *
+     * @param bill
+     * @return
+     */
+    public static DynamicObjectCollection getVaApplyInfos (DynamicObject bill, List<String> vaTypeNumbers) {
+        Long employeeId = bill.getLong("attfilebasef7.employee.id");
+        Date date = bill.getDate("startdate");
+        if(vaTypeNumbers.size() == 0) {
+            DynamicObjectCollection vaTypeCols = bill.getDynamicObjectCollection("vacationtypelist");
+            vaTypeNumbers.add(vaTypeCols.get(0).getDynamicObject("fbasedataid").getString("number"));
+        }
+        // 获取date所在年份的第一天和最后一天
+        LocalDate localDate = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
+        LocalDate startDate = LocalDate.of(localDate.getYear(), 1, 1);
+        LocalDate endDate = LocalDate.of(localDate.getYear(), 12, 31);
+
+        // 日期过滤
+        QFilter dateFilter = new QFilter("enddate", QCP.large_equals, startDate);
+        dateFilter.and("enddate", QCP.less_equals, endDate);
+
+        // 人员
+        QFilter personFilter = new QFilter("attfilebasef7.employee.id", QCP.equals, employeeId);
+
+        // 单据版本过滤(存在变更,取最新的且时长不为0的),这里直接取审批通过的
+        QFilter statusFilter = new QFilter("billstatus", QCP.in, new String[]{"A","B","C"});
+
+        // 休假类型过滤
+        QFilter typeFilter = new QFilter("entryentity.entryvacationtype.number", QCP.in, vaTypeNumbers);
+
+        // 排除当前单据
+        QFilter idFilter = new QFilter("id", QCP.not_equals, bill.getPkValue());
+
+        // 查询字段
+        String selectFields = "startdate,enddate,applytime,billstatus,entryentity.entryvacationtype.name";
+
+        // 查询数据
+        DynamicObjectCollection billCols = QueryServiceHelper.query("wtabm_vaapply", selectFields, new QFilter[]{dateFilter, personFilter, statusFilter, typeFilter, idFilter});
+        return billCols;
+    }
+
+    /**
+     * 获取人员服务年限
+     * @param employeeId
+     * @return
+     */
+    public static BigDecimal getWorkYearByEmployeeId (Long employeeId) {
+        BigDecimal workYear = BigDecimal.ZERO;
+        QFilter filter = new QFilter("employee.id", QCP.equals, employeeId);
+        String selectFields = "workyear";
+        DynamicObject[] cols = WtcConstant.PERSERLEN_HELPER.load(selectFields, new QFilter[]{filter});
+        if(cols.length > 0) {
+            workYear = cols[0].getBigDecimal("workyear");
+        }
+        return workYear;
+    }
+
+}

+ 55 - 0
code/wtc/nckd-jxccl-wtc/src/main/java/nckd/jxccl/wtc/wtabm/web/vaapply/VaApplyAuditOpPluginEx.java

@@ -0,0 +1,55 @@
+package nckd.jxccl.wtc.wtabm.web.vaapply;
+
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.entity.plugin.AbstractOperationServicePlugIn;
+import kd.bos.entity.plugin.PreparePropertysEventArgs;
+import kd.bos.entity.plugin.args.AfterOperationArgs;
+import kd.bos.entity.plugin.args.EndOperationTransactionArgs;
+import kd.bos.servicehelper.operation.SaveServiceHelper;
+import kd.sdk.plugin.Plugin;
+import nckd.jxccl.wtc.wtabm.web.common.constant.WtcConstant;
+
+import java.util.Date;
+
+/**
+ * Tyx
+ * 2025-09-28
+ * 休假申请审核操作,执行以下操作:
+ * 1.如果是休婚假,回写人员档案-基本信息-婚姻状况为二婚,回写人员档案-基本信息-婚姻登记日期为单据上二开填写字段婚姻日期;
+ */
+public class VaApplyAuditOpPluginEx extends AbstractOperationServicePlugIn implements Plugin {
+
+    @Override
+    public void onPreparePropertys(PreparePropertysEventArgs e) {
+        super.onPreparePropertys(e);
+        e.getFieldKeys().add("entryentity.nckd_weddingdate");
+    }
+
+    @Override
+    public void endOperationTransaction(EndOperationTransactionArgs e) {
+        super.endOperationTransaction(e);
+
+    }
+
+    @Override
+    public void afterExecuteOperationTransaction(AfterOperationArgs e) {
+        super.afterExecuteOperationTransaction(e);
+        DynamicObject[] bills = e.getDataEntities();
+        for (DynamicObject bill : bills) {
+            DynamicObjectCollection entryCols = bill.getDynamicObjectCollection("entryentity");
+            String vaTypeNumber = entryCols.get(0).getString("entryvacationtype.number");
+            // 如果请婚假才执行
+            if(vaTypeNumber.equals(WtcConstant.MARRIAGE_NUMBER)) {
+                // 查询人员信息
+                Long employeeId = bill.getLong("attfilebasef7.employee.id");
+                DynamicObject employeeDyn = WtcConstant.EMPLOYEE_HELPER.loadOne(employeeId);
+                // 结婚日期
+                Date weddingDate = entryCols.get(0).getDate("nckd_weddingdate");
+                employeeDyn.set("marriageregistdate", weddingDate);
+                employeeDyn.set("marriagestatus", WtcConstant.STATUS_MARRIAGE);
+                SaveServiceHelper.update(employeeDyn);
+            }
+        }
+    }
+}

+ 30 - 0
code/wtc/nckd-jxccl-wtc/src/main/java/nckd/jxccl/wtc/wtabm/web/vaapply/VaApplySubmitOpPluginEx.java

@@ -0,0 +1,30 @@
+package nckd.jxccl.wtc.wtabm.web.vaapply;
+
+import kd.bos.entity.plugin.AbstractOperationServicePlugIn;
+import kd.bos.entity.plugin.AddValidatorsEventArgs;
+import kd.bos.entity.plugin.PreparePropertysEventArgs;
+import kd.bos.logging.Log;
+import kd.bos.logging.LogFactory;
+import kd.sdk.plugin.Plugin;
+import nckd.jxccl.wtc.wtabm.web.validate.VaApplySubmitValidator;
+
+/**
+ * Tyx
+ * 2025-09-28
+ * 休假申请提交校验
+ */
+public class VaApplySubmitOpPluginEx extends AbstractOperationServicePlugIn implements Plugin {
+
+    private static final Log log = LogFactory.getLog(VaApplySubmitOpPluginEx.class);
+
+    @Override
+    public void onPreparePropertys(PreparePropertysEventArgs e) {
+        super.onPreparePropertys(e);
+    }
+
+    @Override
+    public void onAddValidators(AddValidatorsEventArgs e) {
+        super.onAddValidators(e);
+        e.addValidator(new VaApplySubmitValidator());
+    }
+}

+ 38 - 0
code/wtc/nckd-jxccl-wtc/src/main/java/nckd/jxccl/wtc/wtabm/web/validate/VaApplySubmitValidator.java

@@ -0,0 +1,38 @@
+package nckd.jxccl.wtc.wtabm.web.validate;
+
+import com.kingdee.util.StringUtils;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.entity.ExtendedDataEntity;
+import kd.bos.entity.validate.AbstractValidator;
+import kd.bos.logging.Log;
+import kd.bos.logging.LogFactory;
+import nckd.jxccl.wtc.wtabm.web.service.VaApplyValidateService;
+
+/**
+ * Tyx
+ * 2025-09-28
+ * 休假单提交校验器,校验以下内容:
+ * 1,当员工当年事假N天以上,不允许进行当年度年假申请; N在nckd_wtparam配置中;
+ * 2,社会工龄1年以上10年以下的员工,当年病假累计2个月以上,不允许进行当年度年假申请
+ */
+public class VaApplySubmitValidator extends AbstractValidator {
+
+    private static final Log log = LogFactory.getLog(VaApplySubmitValidator.class);
+
+    @Override
+    public void validate() {
+        for (ExtendedDataEntity dataEntity : dataEntities) {
+            DynamicObject bill = dataEntity.getDataEntity();
+            String msg = VaApplyValidateService.checkOverTimeByPersonalLeave(bill);
+            if(!StringUtils.isEmpty(msg)) {
+                log.info("-------- 休假单事假校验返回信息:{}", msg);
+                this.addErrorMessage(dataEntity, msg);
+            }
+            msg = VaApplyValidateService.checkOverTimeByAnnualSickLeave(bill);
+            if(!StringUtils.isEmpty(msg)) {
+                log.info("-------- 休假单年病假校验返回信息:{}", msg);
+                this.addErrorMessage(dataEntity, msg);
+            }
+        }
+    }
+}

+ 79 - 0
code/wtc/nckd-jxccl-wtc/src/main/java/nckd/jxccl/wtc/wtte/report/AbsentDetailReportDataPlugin.java

@@ -0,0 +1,79 @@
+package nckd.jxccl.wtc.wtte.report;
+
+import kd.bos.algo.DataSet;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.utils.ObjectUtils;
+import kd.bos.entity.report.AbstractReportListDataPlugin;
+import kd.bos.entity.report.FilterInfo;
+import kd.bos.entity.report.ReportQueryParam;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
+import kd.sdk.plugin.Plugin;
+import nckd.jxccl.wtc.wtabm.web.common.constant.WtcConstant;
+import nckd.jxccl.wtc.wtabm.web.common.util.WtcUtils;
+
+import java.util.Date;
+import java.util.Set;
+
+/**
+ * 报表取数插件
+ */
+public class AbsentDetailReportDataPlugin extends AbstractReportListDataPlugin implements Plugin {
+
+    @Override
+    public DataSet query(ReportQueryParam reportQueryParam, Object o) throws Throwable {
+        QFilter filter = buildFilter(reportQueryParam);
+        DataSet dataSet = this.queryDataSet(reportQueryParam, filter);
+        return dataSet;
+    }
+
+    private QFilter buildFilter(ReportQueryParam reportQueryParam) {
+        FilterInfo filterInfo = reportQueryParam.getFilter();
+        //DynamicObject conOrg = (DynamicObject) filterInfo.getFilterItem("nckd_con_org").getValue();
+        DynamicObject conAdminOrg = (DynamicObject) filterInfo.getFilterItem("nckd_con_adminorg").getValue();
+        DynamicObject attPeriod = (DynamicObject) filterInfo.getFilterItem("nckd_attperiodentry").getValue();
+        Date startDate = filterInfo.getFilterItem("nckd_owndatestart").getDate();
+        Date endDate = filterInfo.getFilterItem("nckd_owndateend").getDate();
+        boolean isContainChild = filterInfo.getFilterItem("nckd_iscontainchild").getBoolean();
+
+        /* 组织过滤
+        QFilter orgFilter = new QFilter("attmain.orgid.id", QCP.equals, conOrg.getPkValue());
+        if(!ObjectUtils.isEmpty(conAdminOrg)) {
+            orgFilter.and("attmain.departmentvid.id", QCP.equals, conAdminOrg.getPkValue());
+        }*/
+
+        // 2025-10-16 改成按行政组织过滤,并根据是否包含下级字段取下级行政组织
+        QFilter orgFilter = null;
+        if(isContainChild) {
+            Set subOrgSet = WtcUtils.getSubOrgFilters(conAdminOrg, "attmain.departmentvid.id");
+            orgFilter = new QFilter("attmain.departmentvid.boid", QCP.in, subOrgSet);
+        }
+        else {
+            orgFilter = new QFilter("attmain.departmentvid.boid", QCP.equals, conAdminOrg.getPkValue());
+        }
+
+        // 日期过滤,期间和归属日期其中一个必填,如果都填了以日期为准
+        QFilter dateFilter = null;
+        if(ObjectUtils.isEmpty(attPeriod)) {
+            dateFilter = new QFilter("owndate", QCP.large_equals, startDate);
+            dateFilter.and("owndate", QCP.less_equals, endDate);
+        }
+        else {
+            dateFilter = new QFilter("owndate", QCP.large_equals, attPeriod.getDate("begindate"));
+            dateFilter.and("owndate", QCP.less_equals, attPeriod.getDate("enddate"));
+        }
+        return orgFilter.and(dateFilter);
+    }
+
+    /**
+     * 实际查询数据
+     * @param filter
+     * @return
+     */
+    public DataSet queryDataSet(ReportQueryParam reportQueryParam, QFilter filter) {
+        String selectFields = "attmain.employeeid.id as nckd_employee, attmain.departmentvid.boid as nckd_adminorg,attmain.positionvid.boid as nckd_position, owndate as nckd_absentdate";
+        filter.and("attitemid.number",QCP.equals, WtcConstant.ABSENT_NUMBER);
+        DataSet absentDataSet = WtcConstant.RECORDDETAIL_HEPLER.queryDataSet("AttendanceRateReportQuery-Sbsent", selectFields, new QFilter[]{filter});
+        return absentDataSet;
+    }
+}

+ 103 - 0
code/wtc/nckd-jxccl-wtc/src/main/java/nckd/jxccl/wtc/wtte/report/AttendanceRateReportDataPlugin.java

@@ -0,0 +1,103 @@
+package nckd.jxccl.wtc.wtte.report;
+
+import kd.bos.algo.DataSet;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.utils.ObjectUtils;
+import kd.bos.entity.report.AbstractReportListDataPlugin;
+import kd.bos.entity.report.FilterInfo;
+import kd.bos.entity.report.ReportQueryParam;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
+import kd.sdk.plugin.Plugin;
+import nckd.jxccl.wtc.wtabm.web.common.constant.WtcConstant;
+import nckd.jxccl.wtc.wtabm.web.common.util.WtcUtils;
+
+import java.util.*;
+
+/**
+ * Tyx 2025-10-15
+ * 出勤率统计报表查询插件
+ */
+public class AttendanceRateReportDataPlugin extends AbstractReportListDataPlugin implements Plugin {
+
+    @Override
+    public DataSet query(ReportQueryParam reportQueryParam, Object o) throws Throwable {
+        QFilter filter = buildFilter(reportQueryParam);
+        DataSet dataSet = this.queryDataSet(reportQueryParam, filter);
+        return dataSet;
+    }
+
+    private QFilter buildFilter(ReportQueryParam reportQueryParam) {
+        FilterInfo filterInfo = reportQueryParam.getFilter();
+        //DynamicObject conOrg = (DynamicObject) filterInfo.getFilterItem("nckd_con_org").getValue();
+        DynamicObject conAdminOrg = (DynamicObject) filterInfo.getFilterItem("nckd_con_adminorg").getValue();
+        DynamicObject attPeriod = (DynamicObject) filterInfo.getFilterItem("nckd_attperiodentry").getValue();
+        Date startDate = filterInfo.getFilterItem("nckd_owndatestart").getDate();
+        Date endDate = filterInfo.getFilterItem("nckd_owndateend").getDate();
+        boolean isContainChild = filterInfo.getFilterItem("nckd_iscontainchild").getBoolean();
+
+        /* 组织过滤
+        QFilter orgFilter = new QFilter("attmain.orgid.id", QCP.equals, conOrg.getPkValue());
+        if(!ObjectUtils.isEmpty(conAdminOrg)) {
+            orgFilter.and("attmain.departmentvid.id", QCP.equals, conAdminOrg.getPkValue());
+        }*/
+
+        // 2025-10-16 改成按行政组织过滤,并根据是否包含下级字段取下级行政组织
+        QFilter orgFilter = null;
+        if(isContainChild) {
+            Set subOrgSet = WtcUtils.getSubOrgFilters(conAdminOrg, "attmain.departmentvid.id");
+            orgFilter = new QFilter("attmain.departmentvid.boid", QCP.in, subOrgSet);
+        }
+        else {
+            orgFilter = new QFilter("attmain.departmentvid.boid", QCP.equals, conAdminOrg.getPkValue());
+        }
+
+        // 日期过滤,期间和归属日期其中一个必填,如果都填了以日期为准
+        QFilter dateFilter = null;
+        if(ObjectUtils.isEmpty(attPeriod)) {
+            dateFilter = new QFilter("owndate", QCP.large_equals, startDate);
+            dateFilter.and("owndate", QCP.less_equals, endDate);
+        }
+        else {
+            dateFilter = new QFilter("owndate", QCP.large_equals, attPeriod.getDate("begindate"));
+            dateFilter.and("owndate", QCP.less_equals, attPeriod.getDate("enddate"));
+        }
+        return orgFilter.and(dateFilter);
+    }
+
+    /**
+     * 实际查询数据
+     * @param filter
+     * @return
+     */
+    public DataSet queryDataSet(ReportQueryParam reportQueryParam, QFilter filter) {
+        DynamicObject conAdminOrg = (DynamicObject) reportQueryParam.getFilter().getFilterItem("nckd_con_adminorg").getValue();
+        String selectFields = "attmain.orgid.id as orgId,value";
+        // 先查询所有休假时长
+        QFilter filter1 = filter.copy();
+        filter1.and("attitemid.number",QCP.in, WtcConstant.LEAVE_NUMBERS);
+        DataSet leaveDataSet = WtcConstant.RECORDDETAIL_HEPLER.queryDataSet("AttendanceRateReportQuery-Leave", selectFields, new QFilter[]{filter1});
+        // 汇总
+        DataSet leaveDataSetGroup = leaveDataSet.groupBy(new String[]{"orgId"}).sum("value").finish();
+
+        // 再查询所有出勤时长,SUM汇总
+        QFilter filter2 = filter.copy();
+        filter2.and("attitemid.number",QCP.equals, WtcConstant.SCHEDULED_NUMBER);
+        DataSet schDataSet = WtcConstant.RECORDDETAIL_HEPLER.queryDataSet("AttendanceRateReportQuery-Sch", selectFields, new QFilter[]{filter2});
+        // 汇总
+        DataSet schDataSetGroup = schDataSet.groupBy(new String[]{"orgId"}).sum("value").finish();
+
+        QFilter filter3 = filter.copy();
+        filter3.and("attitemid.number",QCP.equals, WtcConstant.ABSENT_NUMBER);
+        DataSet absentDataSet = WtcConstant.RECORDDETAIL_HEPLER.queryDataSet("AttendanceRateReportQuery-Sbsent", selectFields, new QFilter[]{filter3});
+        // 汇总
+        DataSet absentDataSetGroup = absentDataSet.groupBy(new String[]{"orgId"}).sum("value").finish();
+
+        // 应出勤 Join 休假
+        DataSet joinDataSet1 = schDataSetGroup.join(leaveDataSetGroup).on("orgId","orgId").select(new String[]{"orgId","value as nckd_scheduledday"}, new String[]{"value as nckd_leaveday"}).finish();
+        // 再 Join 旷工
+        DataSet joinDataSet2 = joinDataSet1.join(absentDataSetGroup).on("orgId","orgId").select(new String[]{"orgId", "nckd_scheduledday", "nckd_leaveday"}, new String[]{"value as nckd_absentday"}).finish();
+        // 处理出勤率
+        return joinDataSet2.select(conAdminOrg.getLong("id") + " as nckd_adminorg,nckd_scheduledday, nckd_leaveday, nckd_absentday, nckd_scheduledday - nckd_leaveday - nckd_absentday as nckd_actualday, round((nckd_scheduledday - nckd_leaveday - nckd_absentday) / nckd_scheduledday,2) as nckd_rate");
+    }
+}

+ 105 - 0
code/wtc/nckd-jxccl-wtc/src/main/java/nckd/jxccl/wtc/wtte/report/AttendanceRateReportFormPlugin.java

@@ -0,0 +1,105 @@
+package nckd.jxccl.wtc.wtte.report;
+
+import kd.bos.dataentity.resource.ResManager;
+import kd.bos.entity.datamodel.IDataModel;
+import kd.bos.entity.datamodel.events.PropertyChangedArgs;
+import kd.bos.entity.report.FilterInfo;
+import kd.bos.entity.report.ReportQueryParam;
+import kd.bos.form.events.HyperLinkClickEvent;
+import kd.bos.form.events.HyperLinkClickListener;
+import kd.bos.orm.util.CollectionUtils;
+import kd.bos.report.ReportList;
+import kd.bos.report.ReportShowParameter;
+import kd.bos.report.plugin.AbstractReportFormPlugin;
+import kd.hr.hbp.common.util.HRStringUtils;
+import kd.sdk.plugin.Plugin;
+import kd.wtc.wtbs.common.util.third.collect.Sets;
+import kd.wtc.wtte.business.viewcalsteps.AttRecordUtils;
+
+import java.util.EventObject;
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * Tyx 2025-10-15
+ * 出勤率统计报表界面插件 nckd_attendanceraterpt
+ * 缺勤明细报表也用这个插件 nckd_absentdetailrpt
+ */
+public class AttendanceRateReportFormPlugin extends AbstractReportFormPlugin implements HyperLinkClickListener {
+
+    /**
+     * 校验考勤期间和归属日期其中之一必填
+     * @param queryParam
+     * @return
+     */
+    @Override
+    public boolean verifyQuery(ReportQueryParam queryParam) {
+        FilterInfo filterInfo = queryParam.getFilter();
+        boolean mustFlag = filterInfo.getDynamicObject("nckd_attperiodentry") == null && (filterInfo.getDate("nckd_owndatestart") == null || filterInfo.getDate("nckd_owndateend") == null);
+        if (mustFlag) {
+            this.getView().showTipNotification(ResManager.loadKDString("“考勤期间”与“归属日期”至少一个必填。", "RecordSumDayListRFPlugin_1", "wtc-wtte-formplugin", new Object[0]));
+            return false;
+        } else {
+            return super.verifyQuery(queryParam);
+        }
+    }
+
+    @Override
+    public void propertyChanged(PropertyChangedArgs e) {
+        super.propertyChanged(e);
+        String name = e.getProperty().getName();
+        clearViewKey(name, this.getModel());
+        switch (name) {
+            case "nckd_owndatestart":
+                AttRecordUtils.checkQwndate("nckd_owndatestart", "nckd_owndateend", this.getView(), name);
+                break;
+            case "nckd_owndateend":
+                AttRecordUtils.checkQwndate("nckd_owndatestart", "nckd_owndateend", this.getView(), name);
+        }
+    }
+
+    public static void clearViewKey(String name, IDataModel model) {
+        if (HRStringUtils.equals("nckd_con_org", name)) {
+            Set<String> clearSet = Sets.newHashSetWithExpectedSize(16);
+            clearSet.add("nckd_attperiodentry");
+            clearViewKey((Set)clearSet, model);
+        }
+
+    }
+
+    public static void clearViewKey(Set<String> clearSet, IDataModel model) {
+        if (!CollectionUtils.isEmpty(clearSet) && model != null) {
+            Iterator it = clearSet.iterator();
+            while(it.hasNext()) {
+                String clearKet = (String)it.next();
+                model.setValue(clearKet, (Object)null);
+            }
+        }
+
+    }
+
+    @Override
+    public void registerListener(EventObject e) {
+        super.registerListener(e);
+        ReportList list = this.getControl("reportlistap");
+        list.addHyperClickListener(this);
+    }
+
+    /**
+     * 点击缺勤天数后 携带参数跳转到缺勤明细报表nckd_absentdetailrpt
+     * @param hyperLinkClickEvent
+     */
+    @Override
+    public void hyperLinkClick(HyperLinkClickEvent hyperLinkClickEvent) {
+        String fieldName = hyperLinkClickEvent.getFieldName();
+        if(fieldName.equals("nckd_absentday")) {
+           // 把当前页面的参数传过去
+            ReportShowParameter param = new ReportShowParameter();
+            param.setFormId("nckd_absentdetailrpt");
+            param.getOpenStyle().setTargetKey(getView().getFormShowParameter().getOpenStyle().getTargetKey());
+            param.getOpenStyle().setShowType(getView().getFormShowParameter().getFormConfig().getShowType());
+            param.setQueryParam(this.getQueryParam());
+            this.getView().showForm(param);
+        }
+    }
+}

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно