Procházet zdrojové kódy

社保/考勤模块

Tyx před 2 týdny
rodič
revize
c7cc305c60
20 změnil soubory, kde provedl 2517 přidání a 0 odebrání
  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. 7 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/common/constant/SitConstant.java
  13. 45 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/formplugin/web/file/attach/FileSIBasePluginEx.java
  14. 416 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/formplugin/web/tp/SinsurTemplateEdit.java
  15. 475 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/formplugin/web/tp/SitItemSelectAddItemPlugin.java
  16. 122 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/formplugin/web/tp/SitItemSelectItemEntryPlugin.java
  17. 240 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/formplugin/web/tp/SitItemSelectTreePlugin.java
  18. 57 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/formplugin/web/tp/enums/SinsurPresetItemEnum.java
  19. 158 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/formplugin/web/tp/helper/SinsurTemplateHelper.java
  20. 129 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/formplugin/web/tp/helper/SitItemSelectAddItemServiceHelper.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");
+    }
+}

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

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

@@ -0,0 +1,416 @@
+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();
+    }
+
+    @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();
+                break;
+        }
+
+    }
+
+    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(this.getChangeableRowIndexs(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("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("itemtype");
+                Long itemId = entry.getLong("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");
+//        }
+    }
+    
+}

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

@@ -0,0 +1,475 @@
+package nckd.jxccl.sit.hcsi.formplugin.web.tp;
+
+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("itemunicodeid"))
+                .collect(Collectors.toSet());
+
+        List<TreeNode> checkNodeList = FormulaItemOrFuncTreeHelper.getCheckTreeNodeList(nodeList, uniqueCodeSet);
+        if (CollectionUtils.isNotEmpty(checkNodeList)) {
+            treeView.checkNodes(checkNodeList);
+        }
+    }
+
+    public void loadMainPageData() {
+        if (isMigrationTemplate()) {
+            loadMainPageDataFromMigrationTempate();
+        } else {
+            loadMainPageDataFromResultList();
+        }
+    }
+
+    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("hsas_migrationtplent");
+        if (CollectionUtils.isEmpty(matchRelationDatas)) {
+            return;
+        }
+
+        IDataModel model = this.getModel();
+        for (DynamicObject matchRelationData : matchRelationDatas) {
+            String itemType = matchRelationData.getString("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("itemnumber", sourceData.getString("itemnumber"), detailIndex);
+        model.setValue("itemcategory", itemCategory, detailIndex);
+        model.setValue("itemname", sourceData.getString("itemname"), detailIndex);
+        model.setValue("itemunicodeid", sourceData.getString("uniquecode"), detailIndex);
+        model.setValue("treenodeid", sourceData.getString("uniquecode"), 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 = 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('_'));
+        return normalizeItemCategory(itemCategory);
+    }
+
+    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) {
+        return nodeMap.entrySet().stream()
+                .map(Map.Entry::getValue)
+                .filter(node -> findInSubTree(node, treeId))
+                .findFirst()
+                .orElse(new TreeNode());
+    }
+
+    private boolean findInSubTree(TreeNode node, String treeId) {
+        if (SWCStringUtils.equals(node.getId(), treeId)) {
+            return true;
+        }
+
+        List<TreeNode> children = node.getChildren();
+        if (CollectionUtils.isEmpty(children)) {
+            return false;
+        }
+
+        return children.stream()
+                .anyMatch(child -> findInSubTree(child, treeId));
+    }
+
+    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());
+    }
+}

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

@@ -0,0 +1,57 @@
+package nckd.jxccl.sit.hcsi.formplugin.web.tp.enums;
+
+import kd.swc.hsbp.common.entity.SWCI18NParam;
+
+public enum SinsurPresetItemEnum {
+    CALPERIOD("A", 5L, new SWCI18NParam("期间", "PresetItemEnum_4", "swc-hsas-common"), 1030L, new SWCI18NParam("必填项,体现缴纳期间,格式:yyyy-MM", "PresetItemEnum_13", "swc-hsas-common"), new SWCI18NParam("期间.名称", "PresetItemEnum_28", "swc-hsas-common"), true),
+    EMP_IDCARD("B", 7L, 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", 7L, 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", 7L, 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;
+    }
+
+}

+ 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("itemtype");
+                Long itemId = entry.getLong("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);
+    }
+
+
+
+}
+
+

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

@@ -0,0 +1,129 @@
+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"));
+        return itemMap;
+    }
+
+    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> treeNodeList = 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);
+        treeNodeList.add(itemRoot);
+
+        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);
+    }
+
+}