Browse Source

Merge remote-tracking branch 'origin/master'

wyc 1 week ago
parent
commit
99ebe6d588
29 changed files with 4146 additions and 0 deletions
  1. 91 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/wtc/wtabm/formplugin/web/vaapply/VaApplyBillEditEx.java
  2. 61 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/wtc/wtabm/formplugin/web/vaapply/VaInfoEditEx.java
  3. 47 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/wtc/wtabm/opplugin/web/common/constant/WtcConstant.java
  4. 108 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/wtc/wtabm/opplugin/web/common/util/WtcUtils.java
  5. 149 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/wtc/wtabm/opplugin/web/service/VaApplyValidateService.java
  6. 55 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/wtc/wtabm/opplugin/web/vaapply/VaApplyAuditOpPluginEx.java
  7. 30 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/wtc/wtabm/opplugin/web/vaapply/VaApplySubmitOpPluginEx.java
  8. 38 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/wtc/wtabm/opplugin/web/validate/VaApplySubmitValidator.java
  9. 105 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/wtc/wtte/formplugin/web/report/AttendanceRateReportFormPlugin.java
  10. 79 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/wtc/wtte/report/AbsentDetailReportDataPlugin.java
  11. 105 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/wtc/wtte/report/AttendanceRateReportDataPlugin.java
  12. 202 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/business/importtaskguide/ImportTaskGuideExportService.java
  13. 431 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/business/importtaskguide/ImportTaskGuideImportService.java
  14. 236 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/business/importtaskguide/utils/ImportTaskUtils.java
  15. 7 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/common/constant/SitConstant.java
  16. 45 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/formplugin/web/file/attach/FileSIBasePluginEx.java
  17. 138 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/formplugin/web/tp/SinsurTempDataListPlugin.java
  18. 422 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/formplugin/web/tp/SinsurTemplateEdit.java
  19. 487 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/formplugin/web/tp/SitItemSelectAddItemPlugin.java
  20. 122 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/formplugin/web/tp/SitItemSelectItemEntryPlugin.java
  21. 240 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/formplugin/web/tp/SitItemSelectTreePlugin.java
  22. 77 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/formplugin/web/tp/basedata/SinsurImpTaskListPlugin.java
  23. 128 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/formplugin/web/tp/basedata/TaskGuideImportFormPlugin.java
  24. 73 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/formplugin/web/tp/enums/SinsurPresetItemEnum.java
  25. 158 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/formplugin/web/tp/guide/TaskImpGuideListPlugin.java
  26. 158 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/formplugin/web/tp/helper/SinsurTemplateHelper.java
  27. 186 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/formplugin/web/tp/helper/SitItemSelectAddItemServiceHelper.java
  28. 110 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/rptdata/DetailCompareReportDataPlugin.java
  29. 58 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/utils/ReportUtils.java

+ 91 - 0
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/wtc/wtabm/formplugin/web/vaapply/VaApplyBillEditEx.java

@@ -0,0 +1,91 @@
+package nckd.jxccl.hr.wtc.wtabm.formplugin.web.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.hr.wtc.wtabm.opplugin.web.common.util.WtcUtils;
+
+import java.math.BigDecimal;
+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");
+        }
+    }
+}

+ 61 - 0
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/wtc/wtabm/formplugin/web/vaapply/VaInfoEditEx.java

@@ -0,0 +1,61 @@
+package nckd.jxccl.hr.wtc.wtabm.formplugin.web.vaapply;
+
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.dataentity.utils.ObjectUtils;
+import kd.bos.db.DB;
+import kd.bos.entity.datamodel.IDataModel;
+import kd.bos.entity.datamodel.events.PropertyChangedArgs;
+import kd.bos.form.IFormView;
+import kd.bos.form.field.DateRangeEdit;
+import kd.bos.logging.Log;
+import kd.bos.logging.LogFactory;
+import kd.hr.hbp.formplugin.web.HRDataBaseEdit;
+import nckd.jxccl.hr.wtc.wtabm.opplugin.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/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/wtc/wtabm/opplugin/web/common/constant/WtcConstant.java

@@ -0,0 +1,47 @@
+package nckd.jxccl.hr.wtc.wtabm.opplugin.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/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/wtc/wtabm/opplugin/web/common/util/WtcUtils.java

@@ -0,0 +1,108 @@
+package nckd.jxccl.hr.wtc.wtabm.opplugin.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;
+    }
+
+
+}

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

@@ -0,0 +1,149 @@
+package nckd.jxccl.hr.wtc.wtabm.opplugin.web.service;
+
+import com.kingdee.util.StringUtils;
+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.hr.wtc.wtabm.opplugin.web.common.constant.WtcConstant;
+import nckd.jxccl.hr.wtc.wtabm.opplugin.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;
+import java.util.stream.Collectors;
+
+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/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/wtc/wtabm/opplugin/web/vaapply/VaApplyAuditOpPluginEx.java

@@ -0,0 +1,55 @@
+package nckd.jxccl.hr.wtc.wtabm.opplugin.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.hr.wtc.wtabm.opplugin.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/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/wtc/wtabm/opplugin/web/vaapply/VaApplySubmitOpPluginEx.java

@@ -0,0 +1,30 @@
+package nckd.jxccl.hr.wtc.wtabm.opplugin.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.hr.wtc.wtabm.opplugin.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/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/wtc/wtabm/opplugin/web/validate/VaApplySubmitValidator.java

@@ -0,0 +1,38 @@
+package nckd.jxccl.hr.wtc.wtabm.opplugin.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.hr.wtc.wtabm.opplugin.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);
+            }
+        }
+    }
+}

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

@@ -0,0 +1,105 @@
+package nckd.jxccl.hr.wtc.wtte.formplugin.web.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);
+        }
+    }
+}

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

@@ -0,0 +1,79 @@
+package nckd.jxccl.hr.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.hr.wtc.wtabm.opplugin.web.common.constant.WtcConstant;
+import nckd.jxccl.hr.wtc.wtabm.opplugin.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;
+    }
+}

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

@@ -0,0 +1,105 @@
+package nckd.jxccl.hr.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.mservice.extreport.dataset.datasource.generic.runtimemodel.JoinType;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
+import kd.hr.haos.business.domain.adminorg.service.impl.AdminOrgQueryServiceHelper;
+import kd.sdk.plugin.Plugin;
+import nckd.jxccl.hr.wtc.wtabm.opplugin.web.common.constant.WtcConstant;
+import nckd.jxccl.hr.wtc.wtabm.opplugin.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");
+    }
+}

+ 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;
+    }
+
+}