Procházet zdrojové kódy

feat(opmc): 添加人员考评管理功能

- 新增人员考评管理单据插件、列表插件、树形列表插件等- 实现考评年份校验、重复年份检查等功能
- 添加人员考评向导功能,支持分步骤录入考评信息
- 新增调薪情况列表和树形列表插件
wyc před 2 týdny
rodič
revize
7ca2af82e8
15 změnil soubory, kde provedl 662 přidání a 1 odebrání
  1. 1 1
      code/nckd-cosmic-debug/src/main/java/nckd/cosmic/debug/DebugApplication.java
  2. 25 0
      code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/business/PerfManagerService.java
  3. 27 0
      code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/common/PerfManagerFormConstant.java
  4. 0 0
      code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/mservice/.gitkeep
  5. 165 0
      code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/form/PerfManagerBillPlugin.java
  6. 59 0
      code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/form/PerfManagerListPlugin.java
  7. 48 0
      code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/form/PerfManagerTreeListPlugin.java
  8. 264 0
      code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/form/PerfManagerWizardFormPlugin.java
  9. 49 0
      code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/form/SalAdjTrackerTreeListPlugin.java
  10. 24 0
      code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/form/SalAdjtTackerListPlugin.java
  11. 0 0
      code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/operate/.gitkeep
  12. 0 0
      code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/other/.gitkeep
  13. 0 0
      code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/report/.gitkeep
  14. 0 0
      code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/workflow/.gitkeep
  15. 0 0
      code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/webapi/.gitkeep

+ 1 - 1
code/nckd-cosmic-debug/src/main/java/nckd/cosmic/debug/DebugApplication.java

@@ -29,7 +29,7 @@ public class DebugApplication {
 //        cosmic.setConfigUrl("127.0.0.1:2183");
         
 //        cosmic.setMcServerUrl("http://127.0.0.1:8090");
-        cosmic.setMcServerUrl("http://127.0.0.1:8093/"); 
+        cosmic.setMcServerUrl("http://127.0.0.1:8095/");
         
 //        cosmic.setFsServerUrl("127.0.0.1", 8100);
 //        cosmic.setImageServerUrl("127.0.0.1", 8100);

+ 25 - 0
code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/business/PerfManagerService.java

@@ -0,0 +1,25 @@
+package nckd.jxccl.opmc.pm.business;
+
+import java.util.List;
+
+/**
+ * 人员考评业务逻辑
+ * @author W.Y.C
+ * @date 2025/6/14 18:43
+ * @version 1.0
+ */
+public class PerfManagerService {
+    
+    /**
+     * 生成人员考评结果
+     * @param perfManagerId 人员考评Id
+     * @return: void
+     * @author W.Y.C
+     * @date: 2025/06/14 19:55
+     */
+    public static void generateEvaluationResult(List<Long> perfManagerId){
+        for (int i = 0; i < 100; i++) {
+
+        }
+    }
+}

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

@@ -0,0 +1,27 @@
+package nckd.jxccl.opmc.pm.common;
+
+import nckd.jxccl.base.common.constant.FromConstant;
+
+/**
+ * 人员考评页面常量
+ * @author W.Y.C
+ * @date 2025/6/10 17:14
+ * @version 1.0
+ */
+public class PerfManagerFormConstant extends FromConstant {
+
+    /** 人员考评实体名称 */
+    public static final String ENTITY_NAME_KEY = "nckd_perfmanager";
+    /** 人员考评向导页面标识*/
+    public static final String PERF_MANAGER_WIZARD_KEY = "nckd_perfmanagerwizard";
+    /** 周期开始年份 */
+    public static final String BEGIN_YEAR_KEY = "nckd_beginyear";
+    /** 周期结束年份 */
+    public static final String END_YEAR_KEY = "nckd_endyear";
+    /** 分录-考核年份 */
+    public static final String APPRAISAL_YEAR_KEY = "nckd_appraisalyear";
+    /** 人员 */
+    public static final String PERSON_ID_KEY = "nckd_person";
+    /**生成调薪按钮*/
+    public static final String GENERATE_KEY = "nckd_generate";
+}

+ 0 - 0
code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/mservice/.gitkeep


+ 165 - 0
code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/form/PerfManagerBillPlugin.java

@@ -0,0 +1,165 @@
+package nckd.jxccl.opmc.pm.plugin.form;
+
+import kd.bos.bill.AbstractBillPlugIn;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.entity.datamodel.events.PropertyChangedArgs;
+import kd.bos.form.control.EntryGrid;
+import kd.bos.form.events.BeforeDoOperationEventArgs;
+import kd.bos.form.field.DateEdit;
+import kd.bos.form.field.FieldEdit;
+import kd.bos.form.operate.FormOperate;
+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 kd.bos.util.CollectionUtils;
+import kd.sdk.plugin.Plugin;
+import nckd.jxccl.base.common.constant.FromConstant;
+import nckd.jxccl.base.common.utils.ConvertUtil;
+import nckd.jxccl.base.common.utils.DateUtil;
+import nckd.jxccl.base.common.utils.StrFormatter;
+import nckd.jxccl.opmc.pm.common.PerfManagerFormConstant;
+
+import java.util.Date;
+import java.util.EventObject;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+* 人员考评管理单据插件
+* @author W.Y.C
+* @date 2025/6/9 9:59
+* @version 1.0
+*/
+public class PerfManagerBillPlugin extends AbstractBillPlugIn implements Plugin {
+
+    private final static Log logger = LogFactory.getLog(PerfManagerBillPlugin.class);
+
+
+    public PerfManagerBillPlugin() {
+        super();
+    }
+
+    @Override
+    public void afterBindData(EventObject e) {
+        setEntryYear();
+    }
+
+    @Override
+    public void propertyChanged(PropertyChangedArgs e) {
+        super.propertyChanged(e);
+        String fieldKey = e.getProperty().getName();
+        if(PerfManagerFormConstant.END_YEAR_KEY.equals(fieldKey)){
+            setEntryYear();
+        }
+    }
+
+
+
+    @Override
+    public void beforeDoOperation(BeforeDoOperationEventArgs e) {
+        String operateKey = ((FormOperate) e.getSource()).getOperateKey();
+        DynamicObject dataEntity = this.getModel().getDataEntity();
+        DynamicObjectCollection entrys = dataEntity.getDynamicObjectCollection(FromConstant.ENTRY_ENTITY_KEY);
+        List<Date> dateList = entrys.stream().map(entry -> entry.getDate(nckd.jxccl.opmc.pm.common.PerfManagerFormConstant.APPRAISAL_YEAR_KEY)).collect(Collectors.toList());
+        if(FromConstant.SAVE_KEY.equals(operateKey)){
+            if(CollectionUtils.isNotEmpty(dateList) && !dateList.stream().allMatch(Objects::isNull)) {
+                Date beginYear = dataEntity.getDate(nckd.jxccl.opmc.pm.common.PerfManagerFormConstant.BEGIN_YEAR_KEY);
+                Date endYear = dataEntity.getDate(nckd.jxccl.opmc.pm.common.PerfManagerFormConstant.END_YEAR_KEY);
+                if(beginYear != null && endYear != null){
+                    //校验考核年份是否在周期内
+                    boolean hasOutOfRangeEntry = entrys != null ? entrys.stream()
+                            .map(entry -> entry.getDate(nckd.jxccl.opmc.pm.common.PerfManagerFormConstant.APPRAISAL_YEAR_KEY))
+                            .filter(Objects::nonNull)
+                            .anyMatch(date -> !DateUtil.isInRange(date, beginYear, endYear)) : false;
+                    if(hasOutOfRangeEntry){
+                        e.setCancel(true);
+                        this.getView().showErrorNotification("考核年份不在周期范围内,请检查!");
+                        return;
+                    }
+                }
+
+                //校验考核年份是否重复
+                if(hasDuplicateYear(dateList)){
+                    e.setCancel(true);
+                    this.getView().showErrorNotification("考核结果存在重复的考核年份,请检查!");
+                    return;
+                }
+
+                //判断人员是否有重叠的考核周期
+                DynamicObject person = (DynamicObject) this.getModel().getValue(nckd.jxccl.opmc.pm.common.PerfManagerFormConstant.PERSON_ID_KEY);
+                QFilter finalFilter = new QFilter(nckd.jxccl.opmc.pm.common.PerfManagerFormConstant.PERSON_ID_KEY, QCP.equals, person.getLong(nckd.jxccl.opmc.pm.common.PerfManagerFormConstant.ID_KEY));
+                Object id = this.getModel().getValue(nckd.jxccl.opmc.pm.common.PerfManagerFormConstant.ID_KEY);
+                if (id != null) {
+                    QFilter filter = new QFilter(nckd.jxccl.opmc.pm.common.PerfManagerFormConstant.ID_KEY, QCP.not_equals, id);
+                    finalFilter.and(filter);
+                }
+                QFilter filter = new QFilter(nckd.jxccl.opmc.pm.common.PerfManagerFormConstant.ENTRY_ENTITY_KEY + "." + nckd.jxccl.opmc.pm.common.PerfManagerFormConstant.APPRAISAL_YEAR_KEY, QCP.in, dateList);
+                finalFilter.and(filter);
+                DynamicObjectCollection query = QueryServiceHelper.query(nckd.jxccl.opmc.pm.common.PerfManagerFormConstant.ENTITY_NAME_KEY, nckd.jxccl.opmc.pm.common.PerfManagerFormConstant.ENTRY_ENTITY_KEY + "." + nckd.jxccl.opmc.pm.common.PerfManagerFormConstant.APPRAISAL_YEAR_KEY, new QFilter[]{finalFilter}, null);
+                if(!query.isEmpty()){
+                    List<String> yearList = query.stream()
+                            .map(dynamicObject -> {
+                                Date date = dynamicObject.getDate(nckd.jxccl.opmc.pm.common.PerfManagerFormConstant.ENTRY_ENTITY_KEY + "." + nckd.jxccl.opmc.pm.common.PerfManagerFormConstant.APPRAISAL_YEAR_KEY);
+                                return DateUtil.format(date, "yyyy");
+                            })
+                            .collect(Collectors.toList());
+                    String yearJoin = String.join("、", yearList);
+                    e.setCancel(true);
+                    this.getView().showErrorNotification(StrFormatter.format("人员【{}】已存在【{}】年的考核结果,不能重复添加", person.getString(nckd.jxccl.opmc.pm.common.PerfManagerFormConstant.NAME_KEY), yearJoin));
+                }
+            }
+        }
+
+    }
+
+    /**
+     * 设置分录考核年份只能在周期开始和结束范围内
+     * @author W.Y.C
+     * @date 2025/6/10 18:15
+     * @version 1.0
+     */
+    private void setEntryYear() {
+        EntryGrid entryGrid = this.getControl(FromConstant.ENTRY_ENTITY_KEY);
+        List<FieldEdit> fieldEdits = entryGrid.getFieldEdits();
+        for (FieldEdit fieldEdit : fieldEdits) {
+            //选择周期结束年份后设置分录考核年份只能在周期开始和结束范围内
+            if(nckd.jxccl.opmc.pm.common.PerfManagerFormConstant.APPRAISAL_YEAR_KEY.equalsIgnoreCase(fieldEdit.getProperty().getName())) {
+                DateEdit appraisalYearEdit = (DateEdit) fieldEdit;
+                Date beginYear = ConvertUtil.toDate(this.getModel().getValue(nckd.jxccl.opmc.pm.common.PerfManagerFormConstant.BEGIN_YEAR_KEY));
+                Date endYear = ConvertUtil.toDate(this.getModel().getValue(nckd.jxccl.opmc.pm.common.PerfManagerFormConstant.END_YEAR_KEY));
+                appraisalYearEdit.setMinDate(beginYear);
+                appraisalYearEdit.setMaxDate(endYear);
+            }
+        }
+    }
+
+    /**
+     * 判断日期列表中是否有重复的年份
+     *
+     * @param dateList 日期列表
+     * @return true 表示有重复的年份,false 表示无重复
+     */
+    public static boolean hasDuplicateYear(List<Date> dateList) {
+        if (dateList == null || dateList.isEmpty()) {
+            return false;
+        }
+        Set<Integer> yearSet = new HashSet<>();
+        for (Date date : dateList) {
+            int year = DateUtil.getYear(date);
+            if (yearSet.contains(year)) {
+                return true;
+            }
+            yearSet.add(year);
+        }
+        return false;
+    }
+
+
+
+}

+ 59 - 0
code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/form/PerfManagerListPlugin.java

@@ -0,0 +1,59 @@
+package nckd.jxccl.opmc.pm.plugin.form;
+
+import kd.bos.entity.datamodel.ListSelectedRow;
+import kd.bos.form.IFormView;
+import kd.bos.list.events.ListRowClickEvent;
+import kd.bos.list.plugin.AbstractListPlugin;
+import kd.bos.mvc.form.FormView;
+import kd.sdk.plugin.Plugin;
+import nckd.jxccl.base.common.constant.FromConstant;
+import nckd.jxccl.opmc.pm.common.PerfManagerFormConstant;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.ArrayList;
+import java.util.EventObject;
+import java.util.List;
+import java.util.StringJoiner;
+
+/**
+* 人员考评管理列表插件
+* @author W.Y.C
+* @date 2025/6/9 18:43
+* @version 1.0
+*/
+public class PerfManagerListPlugin extends AbstractListPlugin implements Plugin {
+
+
+
+    @Override
+    public void afterBindData(EventObject e) {
+        super.afterBindData(e);
+        this.getView().setVisible(false, FromConstant.SEARCH_DATE_KEY);
+        IFormView parentView = this.getView().getParentView();
+        if(parentView != null &&  ((FormView) parentView).getFormId().equals(PerfManagerFormConstant.PERF_MANAGER_WIZARD_KEY)) {
+            //是否向导方式进入
+            this.getPageCache().put("isWizard","1");
+            //隐藏退出按钮/生成调薪按钮
+            this.getView().setVisible(Boolean.FALSE,PerfManagerFormConstant.CLOSE_KEY);
+            this.getView().setVisible(Boolean.FALSE,PerfManagerFormConstant.GENERATE_KEY);
+        }
+    }
+
+
+    @Override
+    public void listRowClick(ListRowClickEvent evt) {
+        IFormView parentView = this.getView().getParentView();
+        if(StringUtils.isNotBlank(this.getPageCache().get("isWizard"))){
+            //缓存选中的id(用于人员考评向导)
+            List<Long> rowKeys = new ArrayList<>(evt.getListSelectedRowCollection().size());
+            StringJoiner rowJoin = new StringJoiner(",");
+            for (ListSelectedRow listSelectedRow : evt.getListSelectedRowCollection()) {
+                Object primaryKeyValue = listSelectedRow.getPrimaryKeyValue();
+                if (primaryKeyValue != null) {
+                    rowJoin.add(primaryKeyValue.toString());
+                }
+            }
+            this.getView().getParentView().getPageCache().put("rowKeys", rowJoin.toString());
+        }
+    }
+}

+ 48 - 0
code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/form/PerfManagerTreeListPlugin.java

@@ -0,0 +1,48 @@
+package nckd.jxccl.opmc.pm.plugin.form;
+
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.list.events.BuildTreeListFilterEvent;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
+import kd.hr.hbp.business.dao.factory.HRBaseDaoFactory;
+import kd.hr.hbp.common.constants.org.OrgTreeDynEnum;
+import kd.hr.hbp.common.util.org.model.OrgTreeModel;
+import kd.hr.hbp.formplugin.web.org.template.AdminOrgTreeListTemplate;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+* 人员考评管理列表左树右表
+* @author W.Y.C
+* @date 2025/6/9 17:55
+* @version 1.0
+*/
+public class PerfManagerTreeListPlugin extends AdminOrgTreeListTemplate {
+
+    public PerfManagerTreeListPlugin() {
+        super(new OrgTreeModel(OrgTreeDynEnum.ADMIN_STRUCT.getDynEntity(), OrgTreeDynEnum.ADMIN_MAIN_ENTITY.getDynEntity(), Boolean.TRUE, Boolean.TRUE, Boolean.FALSE));
+    }
+
+    @Override
+    protected QFilter buildNodeClickFilter(BuildTreeListFilterEvent buildTreeListFilterEvent) {
+        String focusNodeId = buildTreeListFilterEvent.getNodeId().toString();
+        QFilter nodeClickFilter = null;
+        if(!this.getTreeModel().getRoot().getId().equalsIgnoreCase(focusNodeId)){
+            QFilter isCurrentVersionFilter = new QFilter("iscurrentversion", QCP.equals, "1");
+            QFilter initStatusFilter = new QFilter("initstatus", QCP.equals, "2");
+            QFilter dataStatusFilter = new QFilter("datastatus", QCP.in, Arrays.asList("1", "2"));
+            QFilter focusNodeIdFilter = new QFilter("adminorg.id", QCP.equals, Long.valueOf(focusNodeId));
+            DynamicObject structlongnumber = HRBaseDaoFactory.getInstance(this.getEntityName()).queryOne("structlongnumber", new QFilter[]{isCurrentVersionFilter, initStatusFilter, dataStatusFilter, focusNodeIdFilter});
+            String focusNodeLongNumber = (String)structlongnumber.get("structlongnumber");
+            QFilter filter = new QFilter("structlongnumber", QCP.like, focusNodeLongNumber + "%");
+            DynamicObjectCollection dynamicObjects = HRBaseDaoFactory.getInstance(this.getEntityName()).queryColl("adminorg.id adminorg", new QFilter[]{filter, isCurrentVersionFilter, initStatusFilter}, null);
+            Set<Long> ids = new HashSet<>(dynamicObjects.size());
+            dynamicObjects.forEach(dynamicObject -> ids.add(dynamicObject.getLong("adminorg")));
+            nodeClickFilter = new QFilter("nckd_person.adminorg.id", QCP.in, ids);
+        }
+        return nodeClickFilter;
+    }
+}

+ 264 - 0
code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/form/PerfManagerWizardFormPlugin.java

@@ -0,0 +1,264 @@
+package nckd.jxccl.opmc.pm.plugin.form;
+
+import kd.bos.dataentity.resource.ResManager;
+import kd.bos.form.CloseCallBack;
+import kd.bos.form.ConfirmCallBackListener;
+import kd.bos.form.MessageBoxOptions;
+import kd.bos.form.ShowType;
+import kd.bos.form.container.Tab;
+import kd.bos.form.container.Wizard;
+import kd.bos.form.control.Control;
+import kd.bos.form.control.Steps;
+import kd.bos.form.control.events.TabSelectEvent;
+import kd.bos.form.control.events.TabSelectListener;
+import kd.bos.form.events.ClosedCallBackEvent;
+import kd.bos.form.plugin.AbstractFormPlugin;
+import kd.bos.list.ListShowParameter;
+import nckd.jxccl.opmc.pm.business.PerfManagerService;
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.Arrays;
+import java.util.EventObject;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+* 人员考评向导
+* @author W.Y.C
+* @date 2025/6/13 11:26
+* @version 1.0
+*/
+public class PerfManagerWizardFormPlugin extends AbstractFormPlugin implements TabSelectListener{
+
+    private static final String WIZARD_AP_KEY = "nckd_wizard";
+    private static final String TAB_KEY = "nckd_wizard_tabap";
+
+    private static final String[] STEP_TAB_FORM_ID = new String[]{"nckd_tabpageap1","nckd_tabpageap2","nckd_tabpageap3","nckd_tabpageap4"};
+
+    private static final String BTN_NEXT_KEY = "nckd_btnnext";
+    private static final String BTN_PREV_KEY = "nckd_btnprev";
+
+    public PerfManagerWizardFormPlugin() {
+    }
+
+
+/*    @Override
+    public void initialize() {
+        //监听上一步、下一步按钮
+        this.addClickListeners(BTN_NEXT_KEY, BTN_PREV_KEY);
+    }*/
+
+
+
+
+
+    @Override
+    public void afterBindData(EventObject e) {
+        int currentStep = this.getCurrentStep();
+        //第一个步骤不显示“上一步”
+        if(currentStep == 0){
+            this.getView().setVisible(Boolean.FALSE, BTN_PREV_KEY);
+
+            ListShowParameter showParameter = new ListShowParameter();
+            showParameter.setBillFormId("nckd_perfmanager");
+            showParameter.getOpenStyle().setShowType(ShowType.InContainer);
+            showParameter.getOpenStyle().setTargetKey("nckd_tabpageap1");
+            showParameter.setCloseCallBack(new CloseCallBack(this, "listCallback")); // 设置回调标识
+            /*ListFilterParameter listFilterParameter = new ListFilterParameter();
+            QFilter qFilter = new QFilter("field_name", QCP.equals, "filter_value");
+            listFilterParameter.setFilter(qFilter);
+            showParameter.setListFilterParameter(listFilterParameter);*/
+            this.getView().showForm(showParameter);
+        }
+
+    }
+
+    // 父页面插件中
+    @Override
+    public void closedCallBack(ClosedCallBackEvent e) {
+        if ("listCallback".equals(e.getActionId())) {
+            List<Object> selectedData = (List<Object>)e.getReturnData();
+            // 使用selectedData处理业务逻辑
+        }
+    }
+
+    @Override
+    public void click(EventObject evt) {
+        //点击上一步、下一步
+        switch (((Control)evt.getSource()).getKey()) {
+            case BTN_NEXT_KEY:
+                this.next();
+                break;
+            case BTN_PREV_KEY:
+                this.previous();
+        }
+
+    }
+
+    /**
+     * 下一步
+     * @return: void
+     * @author W.Y.C
+     * @date: 2025/06/14 20:18
+     */
+    private void next() {
+        int currentStep = this.getCurrentStep();
+        if(beforeNext(currentStep)){
+            Tab tab = (Tab)this.getView().getControl(TAB_KEY);
+            tab.activeTab(STEP_TAB_FORM_ID[currentStep+1]);
+        }
+        afterNext(currentStep);
+       /* for(int i = 0; i < tab.getItems().size(); ++i) {
+            if (currentTab.equals(((Control)tab.getItems().get(tab.getItems().size() - 1)).getKey())) {
+                this.getView().showConfirm(ResManager.loadKDString("向导已完成,是否退出本页?", "WizardPlugin_0", "bos-designer-plugin", new Object[0]), MessageBoxOptions.YesNo, new ConfirmCallBackListener("exitGuideCallBack"));
+                break;
+            }
+            Control control = (Control)tab.getItems().get(i);
+            if (control.getKey().equals(currentTab)) {
+                tab.activeTab(((Control)tab.getItems().get(i + 1)).getKey());
+                break;
+            }
+        }*/
+    }
+
+    /**
+     * 上一步
+     * @return: void
+     * @author W.Y.C
+     * @date: 2025/06/14 20:18
+     */
+    private void previous() {
+        Tab tab = (Tab)this.getView().getControl(TAB_KEY);
+        String currentTab = tab.getCurrentTab();
+
+        for(int i = 0; i < tab.getItems().size(); ++i) {
+            if (currentTab.equals(((Control)tab.getItems().get(0)).getKey())) {
+                this.getView().showTipNotification(ResManager.loadKDString("当前页面为第一页。", "WizardPlugin_1", "bos-designer-plugin", new Object[0]));// 73
+                return;
+            }
+
+            Control control = (Control)tab.getItems().get(i);
+            if (control.getKey().equals(currentTab)) {
+                tab.activeTab(((Control)tab.getItems().get(i - 1)).getKey());
+                break;
+            }
+        }
+    }
+
+    /**
+     * 点击下一步之前触发(可用于数据校验)
+     * @param currentStep 当前步骤
+     * @return: Boolean
+     * @author W.Y.C
+     * @date: 2025/06/14 20:23
+     */
+    private Boolean beforeNext(int currentStep){
+        if(currentStep == 0){
+
+        }else if(currentStep == 1){
+
+        }else if(currentStep == 2){
+
+        }else if(currentStep == 3){
+
+        }else if(currentStep == 4){
+            this.getView().showConfirm(ResManager.loadKDString("向导已完成,是否退出本页?", "WizardPlugin_0", "bos-designer-plugin", new Object[0]), MessageBoxOptions.YesNo, new ConfirmCallBackListener("exitGuideCallBack"));
+            return Boolean.FALSE;
+        }
+        return Boolean.TRUE;
+    }
+
+    private boolean afterNext(int currentStep){
+        if(currentStep == 0) {
+            //录入考评页面选择的数据
+            String rowKeys = this.getView().getPageCache().get("rowKeys");
+            if(StringUtils.isNotBlank(rowKeys) && rowKeys.contains(",")){
+                List<Long> rowKeyList = Arrays.stream(rowKeys.split(","))
+                        .map(String::trim) // 去除每个元素周围的空格
+                        .map(Long::valueOf) // 转换为 Long 类型
+                        .collect(Collectors.toList());
+                kd.bos.form.control.ProgressBar bar = (kd.bos.form.control.ProgressBar)this.getControl("nckd_progressbarap");
+                bar.start();
+                PerfManagerService.generateEvaluationResult(rowKeyList);
+            }
+            System.out.println();
+        }
+        return Boolean.TRUE;
+    }
+
+
+
+
+
+    @Override
+    public void registerListener(EventObject e) {
+        Tab tab = (Tab)this.getControl(TAB_KEY);
+        tab.addTabSelectListener(this);
+
+        //监听上一步、下一步按钮
+        this.addClickListeners(BTN_NEXT_KEY, BTN_PREV_KEY);
+    }
+
+    @Override
+    public void tabSelected(TabSelectEvent tabSelectEvent) {
+
+        Tab tab = (Tab)this.getView().getControl(TAB_KEY);
+        String currentTab = tab.getCurrentTab();
+        int currentStep = getCurrentStep();
+        setStepStatus(currentStep, Steps.PROCESS);
+        if(currentStep != 0){
+            //除了第一个步骤都显示“上一步”
+            this.getView().setVisible(Boolean.TRUE, BTN_PREV_KEY);
+        }else{
+            //第一个步骤不显示“上一步”
+            this.getView().setVisible(Boolean.FALSE, BTN_PREV_KEY);
+        }
+        //最后一个步骤按钮显示“完成”,否则显示下一步
+        if(currentStep == 4){
+            Map<String, Object> textMap = new HashMap<>();
+            Map<String, Object> textValue = new HashMap<>();
+            textValue.put("zh_CN", "完成");
+            textMap.put("text", textValue);
+            this.getView().updateControlMetadata(BTN_NEXT_KEY, textMap);
+        }else{
+            Map<String, Object> textMap = new HashMap<>();
+            Map<String, Object> textValue = new HashMap<>();
+            textValue.put("zh_CN", "下一步");
+            textMap.put("text", textValue);
+            this.getView().updateControlMetadata(BTN_NEXT_KEY, textMap);
+        }
+    }
+
+
+    /**
+     * 设置步骤状态
+     * @param step 步骤索引(从0开始)
+     * @param stepStatus 步骤状态 {@link Steps}
+     * @return: void
+     * @author W.Y.C
+     * @date: 2025/06/14 20:12
+     */
+    private void setStepStatus(int step,String stepStatus) {
+        Wizard wizard = this.getControl(WIZARD_AP_KEY);
+        Map<String, Object> currentStepMap = new HashMap<>();
+        currentStepMap.put("currentStep", step);
+        currentStepMap.put("currentStatus", stepStatus);
+        wizard.setWizardCurrentStep(currentStepMap);
+    }
+
+
+    /**
+     * 获取当前步骤索引(从0开始)
+     * @return: int
+     * @author W.Y.C
+     * @date: 2025/06/14 20:15
+     */
+    private int getCurrentStep() {
+        Tab tab = (Tab)this.getControl(TAB_KEY);
+        String currentTab = tab.getCurrentTab();
+        return ArrayUtils.indexOf(STEP_TAB_FORM_ID, currentTab);
+    }
+}

+ 49 - 0
code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/form/SalAdjTrackerTreeListPlugin.java

@@ -0,0 +1,49 @@
+package nckd.jxccl.opmc.pm.plugin.form;
+
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.list.events.BuildTreeListFilterEvent;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
+import kd.hr.hbp.business.dao.factory.HRBaseDaoFactory;
+import kd.hr.hbp.common.constants.org.OrgTreeDynEnum;
+import kd.hr.hbp.common.util.org.model.OrgTreeModel;
+import kd.hr.hbp.formplugin.web.org.template.AdminOrgTreeListTemplate;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+* 调薪情况列表左树右表
+* @author W.Y.C
+* @date 2025/6/9 17:55
+* @version 1.0
+*/
+public class SalAdjTrackerTreeListPlugin extends AdminOrgTreeListTemplate {
+
+    public SalAdjTrackerTreeListPlugin() {
+        super(new OrgTreeModel(OrgTreeDynEnum.ADMIN_STRUCT.getDynEntity(), OrgTreeDynEnum.ADMIN_MAIN_ENTITY.getDynEntity(), Boolean.TRUE, Boolean.TRUE, Boolean.FALSE));
+    }
+
+    @Override
+    protected QFilter buildNodeClickFilter(BuildTreeListFilterEvent buildTreeListFilterEvent) {
+        String focusNodeId = buildTreeListFilterEvent.getNodeId().toString();
+        QFilter nodeClickFilter = null;
+        if(!this.getTreeModel().getRoot().getId().equalsIgnoreCase(focusNodeId)){
+            QFilter isCurrentVersionFilter = new QFilter("iscurrentversion", QCP.equals, "1");
+            QFilter initStatusFilter = new QFilter("initstatus", QCP.equals, "2");
+            QFilter dataStatusFilter = new QFilter("datastatus", QCP.in, Arrays.asList("1", "2"));
+            QFilter focusNodeIdFilter = new QFilter("adminorg.id", QCP.equals, Long.valueOf(focusNodeId));
+            DynamicObject structlongnumber = HRBaseDaoFactory.getInstance(this.getEntityName()).queryOne("structlongnumber", new QFilter[]{isCurrentVersionFilter, initStatusFilter, dataStatusFilter, focusNodeIdFilter});
+            String focusNodeLongNumber = (String)structlongnumber.get("structlongnumber");
+            QFilter filter = new QFilter("structlongnumber", QCP.like, focusNodeLongNumber + "%");
+            DynamicObjectCollection dynamicObjects = HRBaseDaoFactory.getInstance(this.getEntityName()).queryColl("adminorg.id adminorg", new QFilter[]{filter, isCurrentVersionFilter, initStatusFilter}, null);
+            Set<Long> ids = new HashSet<>(dynamicObjects.size());
+            dynamicObjects.forEach(dynamicObject -> ids.add(dynamicObject.getLong("adminorg")));
+            nodeClickFilter = new QFilter("nckd_person.adminorg.id", QCP.in, ids);
+
+        }
+        return nodeClickFilter;
+    }
+}

+ 24 - 0
code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/form/SalAdjtTackerListPlugin.java

@@ -0,0 +1,24 @@
+package nckd.jxccl.opmc.pm.plugin.form;
+
+import kd.bos.list.plugin.AbstractListPlugin;
+import kd.sdk.plugin.Plugin;
+import nckd.jxccl.base.common.constant.FromConstant;
+
+import java.util.EventObject;
+
+/**
+* 调薪情况列表插件
+* @author W.Y.C
+* @date 2025/6/9 18:43
+* @version 1.0
+*/
+public class SalAdjtTackerListPlugin extends AbstractListPlugin implements Plugin {
+
+    @Override
+    public void afterBindData(EventObject e) {
+        super.afterBindData(e);
+        this.getView().setVisible(false, FromConstant.SEARCH_DATE_KEY);
+    }
+
+
+}

+ 0 - 0
code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/operate/.gitkeep


+ 0 - 0
code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/other/.gitkeep


+ 0 - 0
code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/report/.gitkeep


+ 0 - 0
code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/workflow/.gitkeep


+ 0 - 0
code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/webapi/.gitkeep