# 操作者二开扩展菜单选项 （KB240401以上版本）

- 来源：https://weapp.eteams.cn/build/techdoc/wdoc/index.html#/public/doc/4d13996d-449b-4787-a779-5a1da7be1114

一，操作者扩展菜单选项实现的功能如图：

![image.png](https://weapp.eteams.cn/api/file/preview?fileId=1000698543817392131&type=imgs)

1，动态添加操作者tab选项自定义依次逐个处理。(最多3个设置项)

2，操作者找人能根据设置找到对应的人员。

二，实现功能需要扩展相关接口

1，扩展操作者配置信息设置项

《1》后端实现ECODE钩子(OperatorRegHookEventType)

```plaintext
               OPERATOR_EXTEND_CONFIG("operatorExtendConfig",262533,"扩展操作者配置信息钩子"),
             传入参数： 数组 第一个参数 workflowId ,第二个参数 nodeId
              返回结果：Map<String,List<Map<String,Object>>> 固定2个Key 
                       Key1: bigTypeValues     —扩展OperatorBigType 即tab菜单项
                       Map<String,Object> bigTypMap = new HashMap<String,Object>();
                       //tab  可扩展 8,9,10 不能重复设置，最多只有3个tab
                       bigTypMap.put("bigType",8);
                       bigTypMap.put("labelId",261393);  — tab 多语言labelId
                       bigTypMap.put("isOpen",1);  — 开启
                      bigTypMap.put("desc","AI智能化");  — tab菜单选项默认名
                      bigTypMap.put("extendSourceType","1"); —扩展哪个操作者类型    0 所有 1 节点操作者   2 人员规则  3 超时提醒人 4 督办操作者设置 5 抄清操作者设置  6 代录操作者设置  7 限时办理提醒人设置
                   bigTypMap.put("extendType",1); — 1 非创建节点 2 创建节点
                          bigTypMap.put("showSignOrder","1");  — 是否显示会签属性  0 不显示 1 显示

                         Key2:itemTypeValues    —扩展OperatorItemType即配置处理相关类型信息 

                         Map<String,Object> itemMap = new HashMap<String,Object>();
                         //— 操作者找人type 最多3个选项 801,901,1001
                        itemMap.put("type",801);
                         // — 操作者所属菜单项type 对应上面tab数字
                       itemMap.put("bigType",8);
                         itemMap.put("labelId",1);  — 类型labelId
                        itemMap.put("isOpen",1);  — 是否启用
                         itemMap.put("desc","AI智能化"); — 类型默认名
                         itemMap.put("allowSecLevel",true);  — 是否需要安全级别   
```

参考代码：

```java
package com.weaver.seconddev.hooks.pathdef;

import com.alibaba.fastjson.JSON;
import com.weaver.loom.api.annotation.RegHook;
import com.weaver.loom.context.register.AbstractRegHookEvent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author wbo
 * @date 2024/3/29
 * @description
 */
@Slf4j
@RegHook(module = "workflow", event = "operatorExtendConfig", order = 0)
public class CustomOperatorTabHook extends AbstractRegHookEvent {

    @Value("${weaver.flow.secondDev.customTabName:自定义依次逐个处理}")
    private String customTabName;

    @Value("${weaver.flow.secondDev.customTabLabelId:-1}")
    private String customTabLabelId;

    @Override
    public Object handle(Object[] args) throws Exception {
        Long workflowId = (Long) args[0];
        Long nodeId = (Long) args[1];
        long startTime = System.currentTimeMillis();
        log.info("[CustomOperatorTabHook][Start] workflowId:{},nodeId:{},time:{}",workflowId,nodeId,startTime);

        Map<String, List<Map<String,Object>>> result = new HashMap<>();
        List<Map<String, Object>> OperatorBigType = new ArrayList<>();
        result.put("bigTypeValues",OperatorBigType);
        Map<String,Object> bigTypMap = new HashMap<String,Object>();
        OperatorBigType.add(bigTypMap);

         //tab 可扩展 8,9,10 不能重复设置，最多只有3个tab
        bigTypMap.put("bigType",8);
        //tab 多语言labelId
        bigTypMap.put("labelId",customTabLabelId);
        // 是否启用
        bigTypMap.put("isOpen",1);
        //tab菜单选项默认名
        bigTypMap.put("desc",customTabName);
        //扩展哪个操作者类型    0 所有 1 节点操作者   2 人员规则  3 超时提醒人 4 督办操作者设置 5 抄清操作者设置  6 代录操作者设置  7 限时办理提醒人设置
        bigTypMap.put("extendSourceType","1");
        // 1 非创建节点 2 创建节点
        bigTypMap.put("extendType",1);
        // — 是否显示会签属性  0 不显示 1 显示
        bigTypMap.put("showSignOrder","0");

        List<Map<String, Object>> OperatorItemType = new ArrayList<>();
        result.put("itemTypeValues",OperatorItemType);
        Map<String,Object> itemMap = new HashMap<String,Object>();
        OperatorItemType.add(itemMap);

         //— 操作者找人type 最多3个选项 801,901,1001
        itemMap.put("type",801);
        // — 操作者所属菜单项type
        itemMap.put("bigType",8);
        // — 类型labelId
        itemMap.put("labelId",customTabLabelId);
        //  — 是否启用
        itemMap.put("isOpen",1);
        // — 类型默认名
        itemMap.put("desc",customTabName);
        //  — 是否需要安全级别
        itemMap.put("allowSecLevel",true);

        log.info("[CustomOperatorTabHook][End] workflowId:{},nodeId:{},result:{},time:{}",workflowId,nodeId, JSON.toJSONString(result),startTime);
        return result;
    }
}
```

《2》 前端ecode复写组件

```plaintext
weappWorkflow  — wfpOperatorExtendDevOutItem 

<ExtendDevOutItem weId={`${this.props.weId || ''}_o3g1jr`}

workflowId={workflowId}  —审批流ID

nodeId={nodeId}  —节点ID
otherItems={otherItems}   — 如果有安全级别则总共有2个控件 第一个是表单字段 最后一个是安全级别
triggerRef={this.bindRef}  — 需要获取组件的ref
onThridChange={onThridChange} — 用于安全级别回调
getExtHeaders={this.getExtHeaders} —用于安全级别appId
editExtendData={editExtendData} —为空时新建，不为空是编辑 json对象字符串
/>

 提供方法

   getExtendData    返回 json对象

   {

       itemName：“”,    — 名称

      endApproversCondition:””, — 结束条件显示

      itemLevel:”-999~999” — 级别

   level: "-999~999",—安全级别格式

      —其他的需要存储的自己定义

       signOrder: "2"， —前面如果不配置会签属性，需要默认带会签属性添加此选项

       signOrderCN: "依次逐个处理"  —前面如果不配置会签属性，需要默认带会签属性添加此选项

   }
checkExtendData 校验验证是否提示  返回空串无需提示，字符串提示相关信息     
```

参考代码：

```javascript
import { Provider, inject, observer } from 'mobx-react';
import React from 'react';
import {withRouter,RouteComponentProps } from 'react-router-dom';
import { Dialog,Button,Browser,Select,Input,Radio,Layout,Icon,Switch,Help,CorsComponent } from '@weapp/ui';
import {getLabel} from "@weapp/utils";
const { Row, Col } = Layout;
const { InputNumber } = Input;
import CustomOperatorStore from './customOperatorStore';
import {mathCompareOptions,stepCompareOptions,startComPareOptions,conditionRadioOptions,belongOptions,isKeepOptions,titleGridWidth,contentGridWidth,spanStyle,spanClassName}  from './util/index';

interface CustomOperatorProps extends RouteComponentProps{
    customOperatorStore?:CustomOperatorStore
}

// interface CustomOperatorStates{
//   visible: boolean,
// }
class CustomOperator extends  React.Component<CustomOperatorProps>{
    customOperatorStore:any;
    constructor(props:any){
      super(props);
      this.customOperatorStore = new CustomOperatorStore();
    }
    componentDidMount(){
      // console.log("1111111111111111111111111111");
    }

    render(){
      return (
        <Provider weId={`${this.props.weId || ''}_ymzd3l`} customOperatorStore={this.customOperatorStore} >
            <Content weId={`${this.props.weId || ''}_xjupru`} {...this.props}/>
        </Provider>
      )
    }
}

@inject('customOperatorStore')
@observer
// class Content extends  React.Component<CustomOperatorProps,CustomOperatorStates>{
class Content extends  React.Component<CustomOperatorProps>{
    constructor(props:any){
      super(props);
      // this.state = {
      //   visible:false
      // }
    }

    componentDidMount(){
      // console.log("22222222222222222222222222");
      window.$devThis = this;
      const {editExtendData='',customOperatorStore,triggerRef,otherItems=[]} = this.props;
      if(typeof triggerRef != 'undefined' && triggerRef){
        triggerRef(this);
      }
      if(editExtendData!=''){
        const {initOperatorData} = customOperatorStore;
        initOperatorData(editExtendData);
      }
      customOperatorStore.setScope(otherItems);
    }

    /**
     * 提供给标准，用于获取用户选择的JSON数据
     */
    getExtendData=()=>{
      const {getExtendData} = this.props?.customOperatorStore;
      return getExtendData();
    }

    /**
     * 提供给标准，做必填值校验
     */
    checkExtendData=()=>{
       const {checkExtendData} = this.props?.customOperatorStore;
       return checkExtendData();
    }

    /**
     * 获取自定义条件组件，主要针对条件3和条件6做处理
     */
    getCustomModule=(conditionType)=>{
      const {customFieldConfig,customOperatorStore} = this.props;
      const {operatorData,setOperatorData} = customOperatorStore;
      const {condition3={},condition6={}} = operatorData;

      //各个组件数据值
      let conditionSelectVal = (conditionType=='condition6'?condition6.selectVal:condition3.selectVal) || '';
      const {fieldVal={}} = conditionType=='condition6'?condition6:condition3;
      let conditionSelectCompareVal = fieldVal.selectVal || '';
      let conditionFieldVal = fieldVal.fieldVal || '';
      let conditionFieldVal2 = fieldVal.fieldVal2 || '';
      let isKeep = condition3?.isKeep || '24';//默认不保留

      //根据用户自定义抽出必要信息
      let selectOptionData = [];
      let fieldTypeData = {};
      let customOptionData = {};
      customFieldConfig.map((item,index)=>{
        let option={id:item.fieldId,content:item.fieldName,separator:false,disabled:false};
        selectOptionData.push(option);
        fieldTypeData[item.fieldId]=item.fieldType;
        if(item.fieldType=='4'){
          customOptionData[item.fieldId]=item.options;
        }
      });

      //解析当前字段类型
      let fieldType = '';
      if(conditionSelectVal!=''){
        fieldType = fieldTypeData[conditionSelectVal] || '';
      }
      if(fieldType=='1' || fieldType == '2'){
        conditionFieldVal = fieldVal.fieldVal || [];
      }
      return (<span>
                <Select weId={`${this.props.weId || ''}_lzldj1`}
                  className="dev_custom_radio_select"
                  data={selectOptionData}
                  onChange={v=>setOperatorData(v,conditionType,'fieldSelect')}
                  value={conditionSelectVal}>
                </Select>
                <Select weId={`${this.props.weId || ''}_lzldj1`}
                  className="dev_custom_radio_select"
                  data={(fieldType=='1' || fieldType=='2')?belongOptions:mathCompareOptions}
                  onChange={v=>setOperatorData(v,conditionType,'fieldValCompareSelect')}
                  value={conditionSelectCompareVal}>
                </Select>
                {(fieldType=='1' || fieldType=='2')&&
                  <Browser
                    module='workflow/pathdef'
                    type={fieldType=='1'?'position':'resource'}
                    browserAssociativeProps={{
                      useBoxSelection: false
                    }}
                    multiple={true}
                    onChange={data=>setOperatorData(data,conditionType,'fieldValSelect','browser')}
                    commonParams={fieldType=='1'?{virtualType:"All"}:{}}
                    value={conditionFieldVal}
                  />}
                {fieldType=='3'&&<InputNumber style={{width:50,"margin":"0 5px 0 5px"}} precision={0} value={conditionFieldVal} onChange={v=>setOperatorData(v,conditionType,'fieldValSelect')} />}
                {fieldType=='4'&&
                <Select weId={`${this.props.weId || ''}_lzldj1`}
                  className="dev_custom_radio_select"
                  data={customOptionData[conditionSelectVal]||[]}
                  onChange={v=>setOperatorData(v,conditionType,'fieldValSelect')}
                  value={conditionFieldVal}>
                </Select>}
                {conditionType=='condition3'&&<span><span className={spanClassName} style={spanStyle}>{getLabel(-982504924713181185,"的时候，结束逐级审批。满足当前结束条件时，")}</span>
                <Select weId={`${this.props.weId || ''}_lzldj1`}
                  className="dev_custom_radio_select"
                  data={isKeepOptions}
                  onChange={v=>setOperatorData(v,conditionType,'isKeep')}
                  value={isKeep}>
                </Select><span className={spanClassName} style={spanStyle}>{"当前审批人。"}</span>
                </span>}
                {conditionType=='condition6'&&<span><span className={spanClassName} style={spanStyle}>{"的时候，需要向上审批 "}</span>
                <InputNumber style={{width:50,margin:"0px 5px 0px 5px"}} value={conditionFieldVal2} precision={0} onChange={v=>setOperatorData(v,conditionType,'fieldVal2')} />
                <span className={spanClassName} style={spanStyle}>{" 个层级"}</span></span>}              
             </span>);
    }

    /**
     * 重写条件选项，每一项都重写
     */
    customOptionRender = (_props: RadioOptionProps, ele: React.ReactNode) => {
      const {formFieldDataParams} = this.props;
      const {operatorData,setOperatorData} = this.props.customOperatorStore;
      const {condition1={},condition2={},condition4={},condition5={}} = operatorData;
      let condition1SelectVal = condition1.selectVal || '';
      let condition1FieldVal = condition1.fieldVal || '';

      let condition2SelectVal = condition2.selectVal || '';
      let condition2FieldVal = condition2.fieldVal || [];
      let condition4SelectVal = condition4.selectVal || '';
      let condition4FieldVal = condition4.fieldVal || [];
      let condition5SelectVal = condition5.selectVal || '';
      let condition5SelectVal2 = condition5.selectVal2 || '';
      let condition5FieldVal = condition5.fieldVal || [];
      let condition5FieldVal2 = condition5.fieldVal2 || '';
      
      let optionData = _props.option;  
      let content;
      let divStyle = {"display":"flex","margin-bottom":"5px"};
      switch(optionData.id) {  
          case "15":  
              content=(<div style={divStyle}>
                          <div>{ele}</div>
                          <div><span className={spanClassName} style={spanStyle}>{"当前审批人的职级（安全级别）"}</span>
                              <Select weId={`${this.props.weId || ''}_lzldj1`}
                                className={'dev_custom_radio_select'}
                                data={mathCompareOptions}
                                onChange={v=>setOperatorData(v,'condition1','selectVal')}
                                value={condition1SelectVal}>
                              </Select>
                              <InputNumber style={{width:50,"margin-right":"5px"}} precision={0} value={condition1FieldVal} onChange={v=>setOperatorData(v,'condition1','fieldVal')} />
                              <span className={spanClassName} style={spanStyle}>{"时，结束逐级审批。"}</span>
                          </div></div>);  
              break;  
          case "16":  
              content = (<div style={divStyle}>
                          <div>{ele}</div>
                          <div><span className={spanClassName} style={spanStyle}>{"当前审批人的岗位"}</span>
                          <Select weId={`${this.props.weId || ''}_lzldj2`}
                                className={'dev_custom_radio_select'}
                                data={belongOptions}
                                onChange={v=>setOperatorData(v,'condition2','selectVal')}
                                value={condition2SelectVal}>
                          </Select>
                          <Browser
                            module='workflow/pathdef'
                            type='position'
                            browserAssociativeProps={{
                              useBoxSelection: false
                            }}
                            multiple={true}
                            onChange={data=>setOperatorData(data,'condition2','fieldVal','browser')}
                            commonParams={{virtualType:"All"}}
                            value={condition2FieldVal}
                          />
                          <span className={spanClassName} style={spanStyle}>{"时，结束逐级审批。"}</span></div></div>);  
              break;  
          case "17":
              content=(<div style={divStyle}>
                          <div>{ele}</div>
                          <div><span className={spanClassName} style={spanStyle}>{"当前审批人的人员卡片自定义字段"}</span>
                            {this.getCustomModule('condition3')}
                          </div>
                        </div>);  
              break;
          case "18":  
              content=(<div style={divStyle}><div>{ele}</div><div><span className={spanClassName} style={spanStyle}>{"当前审批人"}</span>
                        <Select weId={`${this.props.weId || ''}_lzldj2`}
                            className={'dev_custom_radio_select'}
                            data={belongOptions}
                            onChange={v=>setOperatorData(v,'condition4','selectVal')}
                            value={condition4SelectVal}>
                        </Select>
                        <Browser
                          module='workflow/pathdef'
                          type='resource'
                          browserAssociativeProps={{
                            useBoxSelection: false
                          }}
                          onChange={data=>setOperatorData(data,'condition4','fieldVal','browser')}
                          multiple={true}
                          value={condition4FieldVal}
                        /><span className={spanClassName} style={spanStyle}>{"时，结束逐级审批。"}</span>
              </div></div>);  
              break;
          case "19":  
              content=(<div style={divStyle}><div>{ele}</div><div><span className={spanClassName} style={spanStyle}>{"当前审批人"}</span>
                        <Select weId={`${this.props.weId || ''}_lzldj2`}
                            className={'dev_custom_radio_select'}
                            data={belongOptions}
                            onChange={v=>setOperatorData(v,'condition5','selectVal')}
                            value={condition5SelectVal}>
                        </Select>
                        <span className={spanClassName} style={spanStyle}>{"表单字段"}</span>
                        <Browser
                          module='workflow/core'
                          type='formFieldBrowser'
                          style={{"margin":"0px 5px 0px 5px"}}
                          browserAssociativeProps={{
                            useBoxSelection: false
                          }}
                          onChange={data=>setOperatorData(data,'condition5','fieldVal','browser')}
                          multiple={false}
                          dataParams={formFieldDataParams}
                          completeParams={formFieldDataParams}
                          value={condition5FieldVal}
                        /><span className={spanClassName} style={spanStyle}>{"里的人员时，在"}</span>
                         <Select weId={`${this.props.weId || ''}_lzldj1`}
                                  className="dev_custom_radio_select"
                                  data={stepCompareOptions}
                                  onChange={v=>setOperatorData(v,'condition5','selectVal2')}
                                  value={condition5SelectVal2}
                          ></Select>
                         {condition5SelectVal2!='23'&&<span><span className={spanClassName} style={spanStyle}>{"审批 "}</span>
                         <InputNumber style={{width:50,margin:"0px 5px 0px 5px"}} precision={0} value={condition5FieldVal2} onChange={v=>setOperatorData(v,'condition5','fieldVal2')} />
                         <span className={spanClassName} style={spanStyle}>{"个层级，"}</span></span>}
                         <span className={spanClassName} style={spanStyle}>{"结束逐级审批。"}</span>
                      </div></div>);  
              break;
          case "20":  
              content=(<div style={divStyle}>
                        <div>{ele}</div>
                        <div><span className={spanClassName} style={spanStyle}>{"当发起人的人员卡片自定义字段"}</span>
                        {this.getCustomModule('condition6')}
                        </div>
                      </div>);  
              break;
          default:  
              content=(<div>{ele}</div>)  
      }
      return content
    }

    render(){
      const {nodeDataParams,formFieldDataParams} = this.props;
      const {operatorData,setOperatorData} = this.props.customOperatorStore;
      const {approveStartOpertor={},approveLevel='',endCondition='',exceptionData={}} = operatorData;
      const {isOpen=false} = exceptionData;
      const startSelectVal = approveStartOpertor.selectVal || '';//逐级审批起始人 下拉框选项值
      const startFieldVal = approveStartOpertor.fieldVal || [];
      const exceptionFieldVal = exceptionData.nodeid || [];
      return (
            <div className='dev_custom_operator' style={{ width: "100%" }} >
              <Row weId={`${this.props.weId || ''}_9nswch`} align={"middle"} justify={"center"} style={{ minHeight: "40px" }}>
                <Col weId={`${this.props.weId || ''}_pe3sni`} span={titleGridWidth}><span className={spanClassName} style={spanStyle}>{"逐级审批起始人"}</span></Col>
                <Col weId={`${this.props.weId || ''}_tw9l1c`} span={contentGridWidth}>
                  <div className='dev_custom_fieldval'>
                      <Select weId={`${this.props.weId || ''}_lzldj1`}
                          data={startComPareOptions}
                          onChange={v=>setOperatorData(v,'approveStartOpertor','selectVal')}
                          value={startSelectVal}>
                      </Select>
                    {startSelectVal=='10'&&<Browser
                        module='workflow/pathdef'
                        type='resource'
                        browserAssociativeProps={{
                          useBoxSelection: false
                        }}
                        onChange={data=>setOperatorData(data,'approveStartOpertor','fieldVal','browser')}
                        multiple={false}
                        value={startFieldVal}
                      />}
                    {startSelectVal=='11'&&<Browser
                        module='workflow/core'
                        type='formFieldBrowser'
                        browserAssociativeProps={{
                          useBoxSelection: false
                        }}
                        onChange={data=>setOperatorData(data,'approveStartOpertor','fieldVal','browser')}
                        multiple={false}
                        dataParams={formFieldDataParams}
                        completeParams={formFieldDataParams}
                        value={startFieldVal}
                      />}
                  </div>
                </Col>
              </Row>
              <Row weId={`${this.props.weId || ''}_9nswch`} align={"middle"} justify={"center"} style={{ minHeight: "40px" }}>
                <Col weId={`${this.props.weId || ''}_pe3sni`} span={titleGridWidth}><span className={spanClassName} style={spanStyle}>{"审批层级"}</span></Col>
                <Col weId={`${this.props.weId || ''}_tw9l1c`} span={contentGridWidth}>
                  <div className='dev_custom_fieldval'>
                    <InputNumber style={{width:80,"margin-right":"5px"}} precision={0} value={approveLevel} onChange={v=>setOperatorData(v,'approveLevel','')} />
                    <Help title={"不设置，表示所有领导审批；设置了层级，则满足设置层级后结束审批"} placement="rightBottom" width={200} />
                  </div>
                </Col>
              </Row>
              <Row weId={`${this.props.weId || ''}_9nswch`} align={"middle"} justify={"center"} style={{ minHeight: "40px" }}>
                <Col weId={`${this.props.weId || ''}_pe3sni`} span={titleGridWidth}><span className={spanClassName} style={spanStyle}>{"结束条件"}</span></Col>
                <Col weId={`${this.props.weId || ''}_tw9l1c`} span={contentGridWidth}>
                  <div className='dev_custom_fieldval' id="dev_radio">
                      <Radio
                        data={conditionRadioOptions}
                        customOptionRender={this.customOptionRender}
                        onChange={v=>setOperatorData(v,'endCondition','')}
                        value={endCondition}
                        vertical
                      />
                  </div>
                </Col>
              </Row>
              <Row weId={`${this.props.weId || ''}_9nswch`} align={"middle"} justify={"center"} style={{ minHeight: "40px" }}>
                <Col weId={`${this.props.weId || ''}_pe3sni`} span={titleGridWidth}><span className={spanClassName} style={spanStyle}>{"异常处理"}</span></Col>
                <Col weId={`${this.props.weId || ''}_tw9l1c`} span={contentGridWidth}>
                  <div className='dev_custom_fieldval'>
                    <div><span className={spanClassName} style={spanStyle}>{"是否启用 "}</span><Switch style={{"margin-left":"5px","margin-bottom":"2px"}} size="sm" value={isOpen} onChange={v=>setOperatorData(v,'exceptionData','isOpen')}/>
                    {isOpen&&<span><span className={spanClassName} style={{"margin-left":"10px"}}>{" 指定流转节点 "}</span>
                    <Browser
                      module='workflow/pathdef'
                      type='workflowPathNodeBrowser'
                      browserAssociativeProps={{
                        useBoxSelection: false
                      }}
                      style={{"margin-left":"5px","margin-right":"5px"}}
                      destDataParams={nodeDataParams}
                      dataParams={nodeDataParams}
                      completeParams={nodeDataParams}
                      onChange={data=>setOperatorData(data,'exceptionData','nodeid','browser')}
                      value={exceptionFieldVal}
                    /><Help title={"启用后，当实际审批层级小于设置的层级时，才会进入异常判断。"} placement="rightBottom" width={200} /></span>}</div>
                  </div>
                </Col>
              </Row>
            </div>
        ) 
    }

}

export default withRouter(CustomOperator)

import { action, observable } from 'mobx';
import {mathCompareOptions,stepCompareOptions,belongOptions,startComPareOptions}  from './util/index';
import {customFieldConfig}  from './config/config';

class CustomOperatorStore {

    //操作者设置数据
     /**
       * 数据结构设计
       * {
       * approveStartOpertor:{selectVal:1,fieldVal:1}//逐级审批人
       * approveLevel:2//审批层级。
       * endCondition:1//单选
       * condition1:{selectVal:1,fieldVal:2}//条件1
       * condition2:{selectVal:1,fieldVal:2}//条件2
       * condition3:{selectVal:1,fieldVal:{selectVal:1,fieldVal:2},isKeep:24}//条件3
       * condition4:{selectVal:1,fieldVal:2}//条件4
       * condition5:{selectVal:1,fieldVal:2,selectVal2:1,fieldVal2:2}//条件5
       * condition6:{selectVal:1,fieldVal:{selectVal:1,fieldVal:2,fieldVal2:3}}//条件6
       * exceptionData:{isOpen:1,nodeid:2}//异常处理逻辑
       * }
       * 
      */
    @observable operatorData:any = {
      approveStartOpertor:{},
      approveLevel:'',
      endCondition:'',
      condition1:{},
      condition2:{},
      condition3:{},
      condition4:{},
      condition5:{},
      condition6:{},
      exceptionData:{}
    };

    scope='';//安全级别

    //原始数据，用于后续condition拼接显示
    rawData={};

    @action('设置安全级别')
    setScope=(otherItems=[])=>{
      otherItems.map(item=>{
        if(item?.itemType == "SCOPE"){
          const {allowMinLevel=-999,allowMaxLevel=999} = item?.otherParams;
          this.scope=allowMinLevel+"~"+allowMaxLevel;
        }
      })
      
    }

    @action('初始化操作者数据，用于编辑回显')
    initOperatorData=(data)=>{
      let editExtendData = JSON.parse(data);
      let oldOperatorData = editExtendData?.operatorData;
      if(oldOperatorData.endCondition == '15'){
        oldOperatorData['condition1'] = oldOperatorData.condition;
      }else if(oldOperatorData.endCondition == '16'){
        oldOperatorData['condition2'] = oldOperatorData.condition;
      }else if(oldOperatorData.endCondition == '17'){
        oldOperatorData['condition3'] = oldOperatorData.condition;
      }else if(oldOperatorData.endCondition == '18'){
        oldOperatorData['condition4'] = oldOperatorData.condition;
      }else if(oldOperatorData.endCondition == '19'){
        oldOperatorData['condition5'] = oldOperatorData.condition;
      }else if(oldOperatorData.endCondition == '20'){
        oldOperatorData['condition6'] = oldOperatorData.condition;
      }
      delete oldOperatorData.condition;
      this.operatorData = oldOperatorData;
      console.log("initOperatorData",this.operatorData);
    }

    @action('封装操作者设置数据')
    setOperatorData = (data,key,operateKey,componentType) => {
      let _data = this.operatorData[key] || {};
      
      if('approveLevel' == key || 'endCondition' == key){
        _data = data;
      }else if('condition3' == key || 'condition6' == key){
        if('fieldSelect' == operateKey){
          //自定义字段下拉框选择
          _data['selectVal'] = data;
          //自定义字段下拉框数据一改变，必须清空后续关联数据
          _data['fieldVal'] = {};
        }else if('fieldValCompareSelect' == operateKey){
          //自定义字段值比较下拉框选择
          let fieldVal = _data['fieldVal'] || {};
          fieldVal['selectVal'] = data;
          _data['fieldVal'] = fieldVal;
        }else if('fieldValSelect' == operateKey || 'fieldVal2' == operateKey){
          //自定义字段值选择
          let fieldVal = _data['fieldVal'] || {};
          if('fieldVal2'==operateKey){
            fieldVal['fieldVal2'] = data;
          }else{
            fieldVal['fieldVal'] = data;
          }
          _data['fieldVal'] = fieldVal;
        }else if('isKeep' == operateKey){
          //是否保留 满足条件时的审批人
          _data['isKeep'] = data;
        }
      }else{
        if('approveStartOpertor' == key && 'selectVal' == operateKey){
          //下拉框切换，清空fieldval
          _data['fieldVal'] = undefined;
        }
        else if('exceptionData' == key && 'isOpen' == operateKey && !data){
          //关闭异常处理节点开关时，清空掉节点Id数据
          _data['nodeid'] = undefined;
        }
        _data[operateKey] = data;        
      }
      this.operatorData[key] = _data;

      this.operatorData = JSON.parse(JSON.stringify(this.operatorData));
    }

    @action('重置参数')
    reset=()=>{
      this.operatorData={};
      this.scope='';
    }
    
    /**
     * 必填校验
     */
    @action('必填校验')
    checkExtendData = ()=>{
      const {approveStartOpertor={},approveLevel='',endCondition='',condition1={},condition2={},condition3={},condition4={},condition5={},condition6={},exceptionData={}} = this.operatorData; 
      const {selectVal='',fieldVal=[]} = approveStartOpertor;

      //逐级审批人校验
      if(selectVal=='' || (selectVal!='9'&&fieldVal.length==0)){
        return '逐级审批起始人不能为空';
      }

      //条件校验
      if(endCondition=='' && approveLevel==''){
        return '审批层级和结束条件必须设置其中一个！';
      }

      let tipMsg = '';
      if(endCondition=='15'&&!this.checkCondition(condition1,'1')){
        tipMsg = '条件1必要信息不完整，请确认';
      }else if(endCondition=='16'&&!this.checkCondition(condition2,'2')){
        tipMsg = '条件2必要信息不完整，请确认';
      }else if(endCondition=='17'&&!this.checkCondition(condition3,'3')){
        tipMsg = '条件3必要信息不完整，请确认';
      }else if(endCondition=='18'&&!this.checkCondition(condition4,'4')){
        tipMsg = '条件4必要信息不完整，请确认';
      }else if(endCondition=='19'&&!this.checkCondition(condition5,'5')){
        tipMsg = '条件5必要信息不完整，请确认';
      }else if(endCondition=='20'&&!this.checkCondition(condition6,'6')){
        tipMsg = '条件6必要信息不完整，请确认';
      }

      //异常处理校验
      const {isOpen=false,nodeid=[]} = exceptionData;
      if(isOpen&&nodeid.length==0){
        tipMsg = '请选择异常处理需要流转的节点';
      }
      if(""==tipMsg){
        //校验通过，执行清空动作
        this.reset(); 
      }
      console.log("tipMsg",tipMsg);
      return tipMsg;
    }

    /**
     * 条件值校验
     */
    checkCondition=(conditionData,type)=>{
      let isCheckPass = false;
      const {selectVal,fieldVal,selectVal2,fieldVal2} = conditionData;
      if(type=='1'&&selectVal&&selectVal!=''&&fieldVal&&fieldVal!=''){
        isCheckPass = true;
      }else if((type=='2' || type=='4')&&selectVal&&selectVal!=''&&this.isArray(fieldVal)&&fieldVal.length>0){
        isCheckPass = true;
      }else if((type=='3' || type=='6')&&selectVal&&selectVal!=''&&fieldVal&&
              fieldVal.selectVal&&fieldVal.selectVal!=''&&((this.isArray(fieldVal.fieldVal)&&fieldVal.fieldVal.length>0)||(fieldVal.fieldVal&&fieldVal.fieldVal!=''))
              &&(type=='3'||(type=='6'&&fieldVal.fieldVal2&&fieldVal.fieldVal2!=''))){
        isCheckPass=true;
      }else if(type=='5'&&selectVal&&selectVal!=''&&this.isArray(fieldVal)&&fieldVal.length>0&&selectVal2&&selectVal2!=''&&fieldVal2&&fieldVal2!=''){
        isCheckPass=true;
      }
      return isCheckPass;
    }

    /**
     * 打包JSON数据
     */
    packageNewOperatorData=()=>{
      let newOperatorData={};
      const {approveStartOpertor={},approveLevel='',endCondition='',exceptionData={}} = this.operatorData;
  
      //1.逐级审批起始人
      newOperatorData['approveStartOpertor'] = {selectVal:approveStartOpertor['selectVal'],fieldVal:this.simplifyData(approveStartOpertor['fieldVal'])};
      //2.审批层级
      newOperatorData['approveLevel'] = approveLevel;
      //3.结束条件
      newOperatorData['endCondition'] = endCondition;
      this.setCondition(newOperatorData,endCondition);
      //4.异常处理
      newOperatorData['exceptionData'] = {isOpen:exceptionData?.isOpen,nodeid:exceptionData?.nodeid}

      console.log("newOperatorData",newOperatorData);
      // return JSON.stringify(newOperatorData);
      return newOperatorData;
    }

    /**
     * 是否是数组
     */
    isArray = (obj) =>{
      if(!obj) return false;
      return obj instanceof Array;
    }

    /**
     * 数据瘦身
     */
    simplifyData = (fieldVal) => {
      let isArray = this.isArray(fieldVal);
      // console.log("simplifyData_fieldVal",fieldVal,"isArray",isArray);
      if(isArray){
        let simplifyData = [];
        fieldVal.map(item=>{
          let param = {id:item.id,name:item.name};
          if(item.avatar){
            param['avatar'] = item.avatar;
          }
          if(item.icon){
            param['icon'] = item.icon;
          }
          simplifyData.push(param);
        })
        return simplifyData;
      }
      return fieldVal;
    }

    /**
     * 抽出选中的条件数据
     */
    setCondition=(newOperatorData,endCondition)=>{
      if(endCondition=='15'){
        newOperatorData['condition'] = this.operatorData?.condition1 || {};
      }else if(endCondition=='16'){
        let condition2 = this.operatorData?.condition2 || {};
        newOperatorData['condition'] = {selectVal:condition2?.selectVal,fieldVal:this.simplifyData(condition2?.fieldVal)};
      }else if(endCondition=='17'){
        let condition3 = this.operatorData?.condition3 || {};
        newOperatorData['condition'] = {selectVal:condition3?.selectVal,fieldVal:{selectVal:condition3?.fieldVal?.selectVal,fieldVal:this.simplifyData(condition3?.fieldVal?.fieldVal)},isKeep:condition3?.isKeep||'24'};
      }else if(endCondition=='18'){
        let condition4 = this.operatorData?.condition4 || {};
        newOperatorData['condition'] = {selectVal:condition4?.selectVal,fieldVal:this.simplifyData(condition4?.fieldVal)};
      }else if(endCondition=='19'){
        let condition5 = this.operatorData?.condition5 || {};
        newOperatorData['condition'] = {selectVal:condition5?.selectVal,fieldVal:this.simplifyData(condition5?.fieldVal),selectVal2:condition5?.selectVal2,fieldVal2:condition5?.fieldVal2};
      }else if(endCondition=='20'){
        let condition6 = this.operatorData?.condition6 || {};
        newOperatorData['condition'] = {selectVal:condition6?.selectVal,fieldVal:{selectVal:condition6?.fieldVal?.selectVal,fieldVal:this.simplifyData(condition6?.fieldVal?.fieldVal),fieldVal2:condition6?.fieldVal?.fieldVal2}};
      }else {
        newOperatorData['condition'] = {};
      }
    }

    /**
     * 浏览那妞数据格式抽出ID数据
     */
    getIds=(fieldVal)=>{
      let ids = [];
      if(this.isArray(fieldVal)){
        fieldVal.map(item=>{
          ids.push(item.id);
        })
      }
      return ids;
    }
    
    /**
     * 封装条件中文显示数据
     */
    packageConditionData=()=>{
      /**
       * 数据结构设计
       * {
       * approveStartOpertor:{selectVal:1,fieldVal:1}//逐级审批人
       * approveLevel:2//审批层级。
       * endCondition:1//单选
       * condition1:{selectVal:1,fieldVal:2}//条件1
       * condition2:{selectVal:1,fieldVal:2}//条件2
       * condition3:{selectVal:1,fieldVal:{selectVal:1,fieldVal:2}}//条件3
       * condition4:{selectVal:1,fieldVal:2}//条件4
       * condition5:{selectVal:1,fieldVal:2,selectVal2:1,fieldVal2:2}//条件5
       * condition6:{selectVal:1,fieldVal:{selectVal:1,fieldVal:2,fieldVal2:3}}//条件6
       * exceptionData:{isOpen:1,nodeid:2}//异常处理逻辑
       * }
       * 
      */
      const {endCondition='',condition1={},condition2={},condition3={},condition4={},condition5={},condition6={}} = this.operatorData;
      if(endCondition == ''){
        return '';
      }
      let customFieldOption=[];
      let fieldTypeData = {};
      let customOptionData = {};
      if(endCondition=='17' || endCondition=='20'){
        customFieldConfig.map((item,index)=>{
          let option={id:item.fieldId,content:item.fieldName,separator:false,disabled:false};
          customFieldOption.push(option);
          fieldTypeData[item.fieldId]=item.fieldType;
          if(item.fieldType=='4'){
            customOptionData[item.fieldId]=item.options;
          }
        });
      }

      let conditionContent = '';
      if(endCondition == '15'){
        conditionContent += '当前审批人的职级（安全级别）'+this.getSelectShowName(condition1?.selectVal,mathCompareOptions)+condition1?.fieldVal;
      }else if(endCondition == '16'){
        conditionContent += '当前审批人的岗位'+this.getSelectShowName(condition2?.selectVal,belongOptions)+this.getFieldShowName(condition2?.fieldVal);
      }else if(endCondition == '17'){
        conditionContent += '当前审批人的人员卡片字段【'+this.getSelectShowName(condition3?.selectVal,customFieldOption,true)+"】";
        if(fieldTypeData[condition3?.selectVal]=='1' || fieldTypeData[condition3?.selectVal]=='2'){
          //浏览按钮
          conditionContent += this.getSelectShowName(condition3?.fieldVal?.selectVal,belongOptions)+this.getFieldShowName(condition3?.fieldVal?.fieldVal);
        }else if(fieldTypeData[condition3?.selectVal]=='4'){
          //下拉框
          conditionContent += this.getSelectShowName(condition3?.fieldVal?.selectVal,mathCompareOptions)+this.getSelectShowName(condition3?.fieldVal?.fieldVal,customOptionData[condition3?.selectVal],true);
        }else {
          //数值
          conditionContent += this.getSelectShowName(condition3?.fieldVal?.selectVal,mathCompareOptions)+condition3?.fieldVal?.fieldVal;
        }
      }else if(endCondition == '18'){
        conditionContent += '当前审批人'+this.getSelectShowName(condition4?.selectVal,belongOptions)+this.getFieldShowName(condition4?.fieldVal);
      }else if(endCondition == '19'){
        // conditionContent += '当前审批人'+this.getSelectShowName(condition5?.selectVal,belongOptions)+"【"+this.getFieldShowName(condition5?.fieldVal,true)+"】表单字段里的人员时，需"+this.getSelectShowName(condition5?.selectVal2,stepCompareOptions)+"审批"+condition5?.fieldVal2+"个层级";
        conditionContent += '当前审批人'+this.getSelectShowName(condition5?.selectVal,belongOptions)+"【"+this.getFieldShowName(condition5?.fieldVal,true)+"】表单字段里的人员时，"+(condition5?.selectVal2=='23'?'需本级审批':'需'+this.getSelectShowName(condition5?.selectVal2,stepCompareOptions)+"审批"+condition5?.fieldVal2+"个层级");
      }else if(endCondition == '20'){
        conditionContent += '当发起人的人员卡片字段【'+this.getSelectShowName(condition6?.selectVal,customFieldOption,true)+"】";
        if(fieldTypeData[condition6?.selectVal]=='1' || fieldTypeData[condition6?.selectVal]=='2'){
          //浏览按钮
          conditionContent += this.getSelectShowName(condition6?.fieldVal?.selectVal,belongOptions)+this.getFieldShowName(condition6?.fieldVal?.fieldVal);
        }else if(fieldTypeData[condition6?.selectVal]=='4'){
          //下拉框
          conditionContent += this.getSelectShowName(condition6?.fieldVal?.selectVal,mathCompareOptions)+this.getSelectShowName(condition6?.fieldVal?.fieldVal,customOptionData[condition6?.selectVal],true);
        }else {
          //数值
          conditionContent += this.getSelectShowName(condition6?.fieldVal?.selectVal,mathCompareOptions)+condition6?.fieldVal?.fieldVal;
        }
        conditionContent += "时，需向上审批"+condition6?.fieldVal?.fieldVal2+"个层级";
      }
      console.log("conditionContent",conditionContent);
      return conditionContent;
    }

    /**
     * 获取浏览按钮字段显示值
     */
    getFieldShowName=(fieldVal,noBrackets)=>{
      if(!this.isArray(fieldVal)){
        return '';
      }
      let fieldShowName = [];
      fieldVal.map(item=>{
        fieldShowName.push(item.name);
      })
      if(noBrackets){
        return fieldShowName.join();
      }
      return "("+fieldShowName.join()+")";
    }

    /**
     * 获取下拉框显示值
     */
    getSelectShowName=(selectVal,options,noSpace)=>{
      let content = '';
      if(this.isArray(options)){
        for(let i=0;i<options.length;i++){
          let item = options[i];
          if(item?.id == selectVal){
            content = item?.content;
            break;
          }
        }
      }
      if(noSpace){
        return content;
      }
      return " "+content+" ";
    }

    /**
     * 封装自定义名称
     */
    packageItemName=()=>{
      const {approveStartOpertor={}} = this.operatorData;
      const {selectVal,fieldVal}=approveStartOpertor;
      let content = this.getSelectShowName(selectVal,startComPareOptions,true);
      content += this.getFieldShowName(fieldVal,false);
      content += "(所有上级)";
      return content;
    }

    @action('获取封装的JSON数据')
    getExtendData = ()=>{
      let extendData = {itemName:this.packageItemName(),endApproversCondition:this.packageConditionData(),itemLevel:this.scope,level:this.scope,signOrder:'2',signOrderCN:'依次逐个处理',operatorData:this.packageNewOperatorData()};
      console.log('extendData',extendData);
      return extendData;
    }

}
export default CustomOperatorStore;
```

2，扩展操作者找人实现

《1》操作者找人实现钩子

```plaintext
 OPERATOR_EXTEND_FIND_OPERATOR("operatorExtendFindOperator",262534,"扩展操作者配置找人钩子")   

 参数说明:
Map<String,Object>  extendParams = new HashMap<String,Object>();
             extendParams.put("workflowId",workflowid);  -- 路径ID
            extendParams.put("nodeId",nodeid); -- 节点ID
            extendParams.put("isSubCompanySupport",isSubCompanySupport);-- 是否支持分部
            extendParams.put("enableSecurityLevel",enableSecurityLevel);-- 是否启用安全级别
            extendParams.put("privateDeploy",privateDeploy);-- 是否私有化部署
            extendParams.put("extendData",operatorSet.getExtendData());--存储设置的json字符串格式
            extendParams.put("tenantKey",operatorSet.getTenantKey()); -- 租户Key
            extendParams.put("requestInfo",requestInfo);  -- 当前请求相关的对象
            extendParams.put("requestContext",requestContext); -- 当前流程相关表单数据，已设上下文数据，非本tab选项的表单字段上下文
            extendParams.put("user",user); --当前操作者
            extendParams.put("operatorSet",operatorSet); -- 当前批次相关数据
 返回结构:List<Long> 人员ID列表
```

参考代码：

```java
package com.weaver.seconddev.hooks.pathdef;

import com.alibaba.fastjson.JSON;
import com.weaver.common.base.entity.result.WeaResult;
import com.weaver.common.form.data.detail.FormDataDetail;
import com.weaver.common.form.data.option.FormDataOption;
import com.weaver.common.hrm.domain.organization.HrmOrgEmpCondition;
import com.weaver.common.hrm.dto.syncdata.HrmSyncDataConfig;
import com.weaver.common.hrm.remote.HrmRemoteIntegrationSyncDataService;
import com.weaver.ebuilder.datasource.api.entity.SqlParamEntity;
import com.weaver.ebuilder.datasource.api.enums.SourceType;
import com.weaver.ebuilder.datasource.api.enums.SqlParamType;
import com.weaver.ebuilder.datasource.api.service.DataSetService;
import com.weaver.framework.rpc.annotation.RpcReference;
import com.weaver.loom.api.annotation.RegHook;
import com.weaver.loom.context.register.AbstractRegHookEvent;
import com.weaver.seconddev.hooks.util.CommonUtil;
import com.weaver.workflow.common.cfg.org.OrgConfig;
import com.weaver.workflow.common.entity.core.flow.RequestRuntimeDataEntity;
import com.weaver.workflow.common.entity.nodeoperator.OperatorSetEntity;
import com.weaver.workflow.common.entity.org.WeaUser;
import com.weaver.workflow.core.api.rest.publicapi.WfcFormDataRest;
import dm.jdbc.util.IDGenerator;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@RegHook(module = "workflow", event = "operatorExtendFindOperator", order = 0)
public class CustomFindOperatorHook extends AbstractRegHookEvent {

    @Autowired
    private DataSetService dataSetService;

    @Value("${weaver.flow.secondDev.flowGroupId:weaver-workflow-report-serviceworkflowreport}")
    private String flowGroupId;

    @Value("${weaver.flow.secondDev.sourceType:logic}")
    private String sourceType;

    /**
     * 是否具有审批权限 的人力资源卡片字段
     */
    @Value("${weaver.flow.secondDev.fixHrmFieldId:981000797163003908}")
    private String spqxFieldId;

    /**
     * 是否具有审批权限 的人力资源卡片字段，选项为 【是】 的值
     */
    @Value("${weaver.flow.secondDev.fixHrmFieldValue:1}")
    private String spqxFieldValue;

    /**
     * 存储流程流转异常数据信息表
     */
    @Value("${weaver.flow.secondDev.flowExceptionInfoTabName:ft_exceptionInfo}")
    private String flowExceptionInfoTabName;

    @RpcReference
    WfcFormDataRest wfcFormDataRest;

    @RpcReference
    HrmRemoteIntegrationSyncDataService hrmRemoteIntegrationSyncDataService;

    @Override
    public Object handle(Object[] args) throws Exception {
        Map<String,Object> extendParams = (Map<String, Object>) args[0];
        List<Long> customOperatorList = new ArrayList<>();
        long startTime = System.currentTimeMillis();
        //1.入参
        String extendData = CommonUtil.null2String(extendParams.get("extendData"));
        Long nodeid = CommonUtil.null2Long(extendParams.get("nodeId"));
        JSONObject extendDataJsonObj =  JSONObject.fromObject(extendData);
        String tenantKey = CommonUtil.null2String(extendParams.get("tenantKey"));
        RequestRuntimeDataEntity requestInfo = (RequestRuntimeDataEntity) extendParams.get("requestInfo");
        long requestId = requestInfo.getRequestId();
        WeaUser user = (WeaUser) extendParams.get("user");
        OperatorSetEntity operatorSet = (OperatorSetEntity) extendParams.get("operatorSet");

        log.info("[CustomFindOperatorHook][workStart] requestId:{},extendData:{},nodeid:{},flowGroupId:{},sourceType:{},spqxFieldId:{},spqxFieldValue:{},flowExceptionInfoTabName:{},groupinfo:{},time:{}",requestId,extendData,nodeid,flowGroupId,sourceType,spqxFieldId,spqxFieldValue,flowExceptionInfoTabName,(CommonUtil.null2String(operatorSet.getGroupId())+"__"+CommonUtil.null2String(operatorSet.getGroupName())+"__"+CommonUtil.null2String(operatorSet.getId())),startTime);

        if (extendData.isEmpty()){
            return customOperatorList;
        }

        //2.解析出配置信息
        if (extendDataJsonObj.containsKey("operatorData")){
            JSONObject operatorData = extendDataJsonObj.getJSONObject("operatorData");
            //逐级审批起始人
            JSONObject approveStartOpertor = operatorData.getJSONObject("approveStartOpertor");
            //审批层级
            int approveLevel = CommonUtil.null2Int(operatorData.get("approveLevel"));
            //审批结束条件
            int endCondition = CommonUtil.null2Int(operatorData.get("endCondition"));
            JSONObject conditionJsonObj = operatorData.getJSONObject("condition");
            //异常处理
            JSONObject exceptionData = operatorData.getJSONObject("exceptionData");

            /**
             * TODO
             * 找人逻辑：
             * 1.根据逐级审批起始人和审批层级 找出所有上级【即为待处理人员】
             * 2.调人力接口，获取某个人员的人员卡片所有字段数据    --- 此时定出 审批层级数
             * 3.再过滤一遍人员，将不具有审批权限的人员过滤掉
             * 4.按照审批结束条件进行过滤    --- 此时定出  实际审批层级数
             * 5.判断 实际审批层级数 < 审批层级数 。如果True，则判断异常处理开关是否启用，如果启用，则取出指定流转节点ID。搞个表记录下来，记录 requestid、curNodeId、exceptionNodeID
             * 6.当前节点审批结束后，需要掉流程标准接口，将流程提交到指定节点去
             *
             */
            //流程创建人
            long creater = requestInfo.getRequestBaseInfo().getUserId();
            //2.1根据逐级审批起始人和审批层级 找出所有上级【即为待处理人员】
            //逐级审批起始人
            long startUser = 0;
            int selectVal = CommonUtil.null2Int(approveStartOpertor.getOrDefault("selectVal", "9"));
            if (9 == selectVal) {
                //流程发起人
                startUser = creater;
            }else if (10 == selectVal || 11 == selectVal){
                JSONArray fieldValArray = approveStartOpertor.getJSONArray("fieldVal");
                if (10 == selectVal){
                    //指定人员
                    startUser = fieldValArray!=null&&fieldValArray.size()>0?CommonUtil.null2Long(((JSONObject)fieldValArray.get(0)).get("id")):0;
                }else {
                    //指定表单字段
                    Long fieldId = fieldValArray!=null&&fieldValArray.size()>0?CommonUtil.null2Long(((JSONObject)fieldValArray.get(0)).get("id")):0;
                    /**
                     * 调用流程接口，获取表单字段值
                     */
                    List<FormDataDetail> formFieldValue = wfcFormDataRest.getFormFieldValue(requestId, Collections.singletonList(fieldId),user.getUserId());
                    log.info("[CustomFindOperatorHook][findFormFieldValue] requestId:{},formFieldValue:{},time:{}",requestId,JSON.toJSONString(formFieldValue),startTime);
                    if (formFieldValue.size()>0){
                        List<FormDataOption> dataOptions = formFieldValue.get(0).getDataOptions();
                        if (dataOptions.size()>0){
                            FormDataOption formDataOption = dataOptions.get(0);
                            startUser = Long.parseLong(formDataOption.getOptionId());
                        }
                    }
                }
            }
            log.info("[CustomFindOperatorHook][findStartUser] requestId:{},startUser:{},selectVal:{},creater:{},time:{}",requestId,startUser,selectVal,creater,startTime);
            if (startUser>0){
                //根据起始人找所有直接上级
                Set<Long> allManager = new LinkedHashSet<>();
                findAllManager(startUser,allManager);

                List<Long> allSuperior = new ArrayList<>(allManager);

                log.info("[CustomFindOperatorHook][findAllSuperior] requestId:{},startUser:{},allSuperior:{},time:{}",requestId,startUser,JSON.toJSONString(allSuperior),startTime);

                //找到所有直接上级后人员，过滤一下不具有审批权限的，以及审批层级
                if (!spqxFieldId.isEmpty()){
                    String fixFieldKey = "employeeExtend."+spqxFieldId;
                    Map<String, Object> fixFieldData = findUserFieldInfo(allSuperior, user.getTenantKey(), Collections.singletonList(fixFieldKey));
                    if (fixFieldData!=null){
                        List<Map<String, Object>> userDataList = (List<Map<String, Object>>) fixFieldData.get("data");
                        List<Long> needApproveSuperior = userDataList.stream().filter(data -> {
                            boolean isHasSpqx = false;
                            if (data.containsKey(fixFieldKey)&&data.get(fixFieldKey)!=null) {
                                Map<String, Object> employeeExtendMap = (Map<String, Object>) data.get(fixFieldKey);
                                String fixFieldVal = CommonUtil.null2String(employeeExtendMap.get("id")).trim();
                                if (fixFieldVal.isEmpty()){
                                    fixFieldVal = CommonUtil.null2String(employeeExtendMap.get("value")).trim();
                                }
                                if (spqxFieldValue.equals(fixFieldVal)){
                                    isHasSpqx = true;
                                }
                            }
                            return isHasSpqx;
                        }).map(data -> CommonUtil.null2Long(data.get("id"))).collect(Collectors.toList());
                        allSuperior = allSuperior.stream().filter(needApproveSuperior::contains).collect(Collectors.toList());
                    }
                    log.info("[CustomFindOperatorHook][findfixFieldData] requestId:{},fixFieldData:{},allSuperior:{},time:{}",requestId,JSON.toJSONString(fixFieldData),JSON.toJSONString(allSuperior),startTime);
                }
                if (CollectionUtils.isEmpty(allSuperior)){
                    return customOperatorList;
                }

                //审批人员已查找完毕，当前需要审批的层级级数
                int curApprovalLevel = allSuperior.size();
                approveLevel = approveLevel<=0?curApprovalLevel:approveLevel;
                //循环次数
                int cycleCount = Math.min(curApprovalLevel, approveLevel);

                //最终的审批人员
                customOperatorList = findApproveUserByEndCondition(cycleCount, allSuperior, user.getTenantKey(), endCondition, conditionJsonObj, requestId, user.getUserId(), creater);

            }
            log.info("[CustomFindOperatorHook][filterOperatorByEndCondition] requestId:{},customOperatorList:{},time:{}",requestId,JSON.toJSONString(customOperatorList),startTime);
            if (CollectionUtils.isNotEmpty(customOperatorList) && exceptionData.containsKey("isOpen")){
                //3.解析 异常处理设置 数据
                boolean isOpen = exceptionData.getBoolean("isOpen");
                if (customOperatorList.size()<approveLevel&&isOpen){
                    //当实际审批的层级小于设置的层级时，且启用了异常处理，需要进行执行流转
                    JSONArray nodeidJsonArray = exceptionData.getJSONArray("nodeid");
                    if (nodeidJsonArray!=null&&nodeidJsonArray.size()>0){
                        JSONObject nodeJson = nodeidJsonArray.getJSONObject(0);
                        Long exceptionNodeId = CommonUtil.null2Long(nodeJson.get("id"));
                        if (exceptionNodeId>0&&!exceptionNodeId.equals(nodeid)){
                            //存储异常指定流转的数据信息
                            recordExceptionNodeInfo(requestId,nodeid,exceptionNodeId,customOperatorList,tenantKey,operatorSet);
                        }
                    }
                }
            }
        }
        return customOperatorList;

    }

    /**
     * 记录异常流转信息数据
     * @param requestId 请求ID
     * @param nodeid 当前节点ID
     * @param exceptionNodeId 异常流向节点ID
     * @param customOperatorList 当前审批人
     * @param tenantKey 租户Key
     * @param operatorSet 操作信息
     */
    private void recordExceptionNodeInfo(long requestId, Long nodeid, Long exceptionNodeId, List<Long> customOperatorList, String tenantKey, OperatorSetEntity operatorSet) {
        long groupid = operatorSet!=null?operatorSet.getGroupId():-1;
        long groupdetailid = operatorSet!=null?operatorSet.getId():-1;
        Date now = new Date();

        //1.先查，如果当前操作组操作信息已存在，则现将老数据删除（逻辑删除），再做插入
        String updateSql = "update " + flowExceptionInfoTabName + " set isvalid=0 , DELETE_TYPE = 1,update_time=? where reqid = " + requestId + " and nownodeid = " + nodeid + " and groupid = " + groupid + " and groupdetailid = " + groupdetailid + " and isvalid = 1 and TENANT_KEY = '" + tenantKey + "' and DELETE_TYPE = 0 ";
        List<SqlParamEntity> sqlParams = new ArrayList<>();
        SqlParamEntity sqlParamEntity = new SqlParamEntity();
        sqlParamEntity.setParamType(SqlParamType.DATE);
        sqlParamEntity.setValue(now.getTime()+"");
        sqlParams.add(sqlParamEntity);
        Map<String, Object> updateMap = excuteSql(updateSql,sqlParams);
        log.info("[CustomFindOperatorHook][recordExceptionNodeInfo][update] requestId:{},updateSql:{},updateMap:{}",requestId,updateSql,JSON.toJSONString(updateMap));

        //2.执行插入动作
        long id = IDGenerator.generate();
        String insertSql = "insert into "+flowExceptionInfoTabName+"(id,FORM_DATA_ID,DATA_INDEX,CREATE_TIME,TENANT_KEY,IS_DELETE,DELETE_TYPE,FT_STATUS," +
                "reqid,nownodeid,flownodeid,operators,isvalid,groupid,groupdetailid) " +
                " values (" + id + "," + id + ",1,?,'"+tenantKey+"',0,0,0,"+
                requestId+","+nodeid+","+exceptionNodeId+",'"+ StringUtils.join(customOperatorList,",") +"',1,"+groupid+","+groupdetailid+")";
        sqlParams = new ArrayList<>();
        sqlParamEntity = new SqlParamEntity();
        sqlParamEntity.setParamType(SqlParamType.DATE);
        sqlParamEntity.setValue(now.getTime()+"");
        sqlParams.add(sqlParamEntity);
        Map<String, Object> insertData = excuteSql(insertSql,sqlParams);
        log.info("[CustomFindOperatorHook][recordExceptionNodeInfo][insert] requestId:{},insertSql:{},insertData:{}",requestId,insertSql,JSON.toJSONString(insertData));
    }

    /**
     * 根据结束条件和设置的审批层级找出最终的审批人员集合
     * @param cycleCount 设置的循环审批层级数
     * @param allSuperior 全部的审批人
     * @param tenantKey 租户key
     * @param endCondition 结束条件选项值
     * @param conditionJsonObj 结束条件数据
     * @param requestId 流程请求ID
     * @param curEmployeeId 当前用户ID
     * @param creater 流程创建人ID
     * @return 最终审批链条人员
     */
    private List<Long> findApproveUserByEndCondition(int cycleCount, List<Long> allSuperior, String tenantKey, int endCondition, JSONObject conditionJsonObj,Long requestId,Long curEmployeeId,Long creater) {
        List<Long> finalApproveUserList = new ArrayList<>();
        //不同的条件执行不同的逻辑
        if (endCondition == 15) {
            //当前审批人的职级（安全级别）达到某一级别是，结束逐级审批
            Map<String, Object> sec_levelFieldInfo = findUserFieldInfo(allSuperior, tenantKey, Collections.singletonList("employee.SEC_LEVEL"));
            if (sec_levelFieldInfo!=null){
                List<Map<String, Object>> dataList = (List<Map<String, Object>>) sec_levelFieldInfo.get("data");
                Map<Long, Integer> userSecLevelMap = dataList.stream().collect(Collectors.toMap(data -> CommonUtil.null2Long(data.get("id")), data -> CommonUtil.null2Int(data.get("employee.SEC_LEVEL"))));
                for (int i = 0; i < cycleCount; i++) {
                    long curUserId = allSuperior.get(i);
                    //安全级别
                    Integer sec_level = userSecLevelMap.get(curUserId);
                    //比较表达式
                    int selectVal = CommonUtil.null2Int(conditionJsonObj.get("selectVal"));
                    //安全级别数值
                    int fieldVal = CommonUtil.null2Int(conditionJsonObj.get("fieldVal"));

                    finalApproveUserList.add(curUserId);
                    if (checkNumComparison(sec_level,fieldVal,selectVal)){
                        break;
                    }
                }
                log.info("[CustomFindOperatorHook][endCondition1] requestId:{},sec_levelFieldInfo:{},finalApproveUserList:{}",requestId,JSON.toJSONString(sec_levelFieldInfo),JSON.toJSONString(finalApproveUserList));
            }
        } else if (endCondition == 16) {
            //当前审批人的岗位为既定岗位时，结束逐级审批
            Map<String, Object> positionFieldInfo = findUserFieldInfo(allSuperior, tenantKey, Collections.singletonList("employee.position"));
            if (positionFieldInfo!=null){
                List<Map<String, Object>> dataList = (List<Map<String, Object>>) positionFieldInfo.get("data");
                Map<Long, Long> userSecLevelMap = dataList.stream().collect(Collectors.toMap(data -> CommonUtil.null2Long(data.get("id")), data -> CommonUtil.null2Long(data.get("employee.position"))));
                for (int i = 0; i < cycleCount; i++) {
                    long curUserId = allSuperior.get(i);
                    //岗位信息
                    Long positionId = userSecLevelMap.get(curUserId);
                    //比较表达式
                    int selectVal = CommonUtil.null2Int(conditionJsonObj.get("selectVal"));
                    //设置的岗位条件
                    JSONArray fieldVal = conditionJsonObj.getJSONArray("fieldVal");

                    finalApproveUserList.add(curUserId);
                    if (checkBrowserComparison(Collections.singletonList(positionId),fieldVal,selectVal)){
                        break;
                    }
                }
                log.info("[CustomFindOperatorHook][endCondition2] requestId:{},positionFieldInfo:{},finalApproveUserList:{}",requestId,JSON.toJSONString(positionFieldInfo),JSON.toJSONString(finalApproveUserList));
            }
        } else if (endCondition == 17) {
            //当前审批人的人员卡片自定义字段（有多个自定义字段作为判断依据），等于某个值的时候，结束逐级审批
            Long customFieldId = CommonUtil.null2Long(conditionJsonObj.get("selectVal"));
            //是否保留当前审批人
            Integer isKeep = CommonUtil.null2Int(conditionJsonObj.get("isKeep"), "24");
            JSONObject fieldVal = conditionJsonObj.getJSONObject("fieldVal");
            if (customFieldId>0&&fieldVal!=null){
                String customFieldKey = "employeeExtend."+customFieldId;
                /**
                 * 如果说对应的自定义字段没值，则给个默认空值，进行条件比较。则将会按照数据值将会按照0参与判断逻辑
                 *
                 * TODO  是否这样设计？所有人条件设计的字段值都有可能为空值，这种场景下如何梳理逻辑。
                 */
                Map<String, Object> customFieldInfo = findUserFieldInfo(allSuperior, tenantKey, Collections.singletonList(customFieldKey));
                if (customFieldInfo!=null){
                    List<Map<String, Object>> dataList = (List<Map<String, Object>>) customFieldInfo.get("data");
                    Map<Long, Object> customDataMap = dataList.stream().collect(Collectors.toMap(data -> CommonUtil.null2Long(data.get("id")), data -> (data.get(customFieldKey)==null?new HashMap<>():data.get(customFieldKey))));
                    for (int i = 0; i < cycleCount; i++) {
                        long curUserId = allSuperior.get(i);
                        //自定义字段值
                        Map<String,Object> customFieldVal = (Map<String, Object>) customDataMap.get(curUserId);
                        //比较表达式
                        int selectVal = CommonUtil.null2Int(fieldVal.getString("selectVal"));
                        if (selectVal==21||selectVal==22){
                            //浏览按钮字段类型值，岗位或者人员
                            List<String> idsList = Arrays.asList(CommonUtil.null2String(customFieldVal.get("id")).split(","));
                            List<Long> idsList2 = idsList.stream().map(CommonUtil::null2Long).collect(Collectors.toList());
                            JSONArray fieldVal2 = fieldVal.getJSONArray("fieldVal");

                            if (checkBrowserComparison(idsList2,fieldVal2,selectVal)){
                                if (isKeep==23){
                                    //需要保留当前审批人
                                    finalApproveUserList.add(curUserId);
                                }
                                break;
                            }
                            finalApproveUserList.add(curUserId);
                        }else if (selectVal<7){
                            //数值或者下拉框类型字段，仅执行数学比较表达式
                            long id = CommonUtil.null2Long(customFieldVal.get("id"))>0?CommonUtil.null2Long(customFieldVal.get("id")):CommonUtil.null2Long(customFieldVal.get("value"));
                            long fieldVal2 = CommonUtil.null2Long(fieldVal.get("fieldVal"));

                            if (checkNumComparison(id,fieldVal2,selectVal)){
                                if (isKeep==23){
                                    //需要保留当前审批人
                                    finalApproveUserList.add(curUserId);
                                }
                                break;
                            }
                            finalApproveUserList.add(curUserId);
                        }
                    }
                    log.info("[CustomFindOperatorHook][endCondition3] requestId:{},customFieldInfo:{},finalApproveUserList:{}",requestId,JSON.toJSONString(customFieldInfo),JSON.toJSONString(finalApproveUserList));
                }
            }
        } else if (endCondition == 18) {
            //当前审批人是指定人员时，结束逐级审批
            for (int i = 0; i < cycleCount; i++) {
                long curUserId = allSuperior.get(i);
                //比较表达式
                int selectVal = CommonUtil.null2Int(conditionJsonObj.get("selectVal"));
                //设置的人员条件
                JSONArray fieldVal = conditionJsonObj.getJSONArray("fieldVal");

                finalApproveUserList.add(curUserId);
                if (checkBrowserComparison(Collections.singletonList(curUserId),fieldVal,selectVal)){
                    break;
                }
            }
            log.info("[CustomFindOperatorHook][endCondition4] requestId:{},finalApproveUserList:{}",requestId,JSON.toJSONString(finalApproveUserList));
        } else if (endCondition == 19) {
            //当前审批人等于或者属于某个表单字段里的人员时，结束逐级审批(需向前、或向后审批（N）个层级）
            JSONArray fieldVal = conditionJsonObj.getJSONArray("fieldVal");
            //指定表单字段
            Long fieldId = fieldVal!=null&&fieldVal.size()>0?CommonUtil.null2Long(((JSONObject)fieldVal.get(0)).get("id")):0;
            List<FormDataDetail> formFieldValue = wfcFormDataRest.getFormFieldValue(requestId, Collections.singletonList(fieldId),curEmployeeId);
            if (formFieldValue.size()>0){
                List<FormDataOption> dataOptions = formFieldValue.get(0).getDataOptions();
                if (dataOptions!=null){
                    List<Long> formFieldValList = dataOptions.stream().map(dataOption -> CommonUtil.null2Long(dataOption.getOptionId())).collect(Collectors.toList());
                    //比较表达式
                    int selectVal = CommonUtil.null2Int(conditionJsonObj.get("selectVal"));
                    for (int i = 0; i < cycleCount; i++) {
                        long curUserId = allSuperior.get(i);

                        finalApproveUserList.add(curUserId);
                        if (checkComparison(Collections.singletonList(curUserId),formFieldValList,selectVal)){
                            break;
                        }
                    }
                    int approveCount = finalApproveUserList.size();
                    if (approveCount>0){
                        //向前或者向后审批层级 或在本级
                        int selectVal2 = CommonUtil.null2Int(conditionJsonObj.get("selectVal2"));
                        //审批的层级数
                        int fieldVal2 = CommonUtil.null2Int(conditionJsonObj.get("fieldVal2"));

                        if (selectVal2==7){
                            //向前审批层级数
                            if (fieldVal2>=approveCount){
                                //只需第一个人审批
                                finalApproveUserList = Collections.singletonList(finalApproveUserList.get(0));
                            } else {
                                finalApproveUserList = finalApproveUserList.stream().limit(approveCount-fieldVal2).collect(Collectors.toList());
                            }
                        }else if (selectVal2==8){
                            //向后审批层级数
                            if ((fieldVal2+approveCount)>=cycleCount){
                                //超过总人数，则审批人为全部上级
                                finalApproveUserList = allSuperior;
                            }else {
                                for (int i = approveCount; i < (fieldVal2+approveCount); i++) {
                                    finalApproveUserList.add(allSuperior.get(i));
                                }
                            }
                        }
                    }
                }
                log.info("[CustomFindOperatorHook][endCondition5] requestId:{},dataOptions:{},finalApproveUserList:{}",requestId,JSON.toJSONString(dataOptions),JSON.toJSONString(finalApproveUserList));
            }
        } else if (endCondition == 20) {
            //当 发起人 属于（人员卡片字段 可选）的时候，需要向上审批N（可设置）个层级
            Long customFieldId = CommonUtil.null2Long(conditionJsonObj.get("selectVal"));
            JSONObject fieldVal = conditionJsonObj.getJSONObject("fieldVal");
            if (customFieldId>0&&fieldVal!=null){
                String customFieldKey = "employeeExtend."+customFieldId;
                Map<String, Object> customFieldInfo = findUserFieldInfo(Collections.singletonList(creater), tenantKey, Collections.singletonList(customFieldKey));
                if (customFieldInfo!=null){
                    List<Map<String, Object>> dataList = (List<Map<String, Object>>) customFieldInfo.get("data");
                    Map<Long, Object> customDataMap = dataList.stream().collect(Collectors.toMap(data -> CommonUtil.null2Long(data.get("id")), data -> (data.get(customFieldKey)==null?new HashMap<>():data.get(customFieldKey))));
                    boolean isMeetCondition = false;
                    //自定义字段值
                    Map<String,Object> customFieldVal = (Map<String, Object>) customDataMap.get(creater);
                    //比较表达式
                    int selectVal = CommonUtil.null2Int(fieldVal.getString("selectVal"));
                    if (selectVal==21||selectVal==22){
                        //浏览按钮字段类型值，岗位或者人员
                        List<String> idsList = Arrays.asList(CommonUtil.null2String(customFieldVal.get("id")).split(","));
                        List<Long> idsList2 = idsList.stream().map(CommonUtil::null2Long).collect(Collectors.toList());
                        JSONArray fieldVal2 = fieldVal.getJSONArray("fieldVal");
                        isMeetCondition = checkBrowserComparison(idsList2,fieldVal2,selectVal);
                    }else if (selectVal<7){
                        //数值或者下拉框类型字段，仅执行数学比较表达式
                        long id = CommonUtil.null2Long(customFieldVal.get("id"))>0?CommonUtil.null2Long(customFieldVal.get("id")):CommonUtil.null2Long(customFieldVal.get("value"));
                        long fieldVal2 = CommonUtil.null2Long(fieldVal.get("fieldVal"));
                        isMeetCondition = checkNumComparison(id,fieldVal2,selectVal);
                    }
                    if (isMeetCondition){
                        int fieldVal2 = CommonUtil.null2Int(fieldVal.get("fieldVal2"));
                        if (fieldVal2<=0 || fieldVal2>=cycleCount){
                            //配置的层级数不对或者配置的层级大于实际审批层级，则按照设置的审批层级来
                            finalApproveUserList = allSuperior.stream().limit(cycleCount).collect(Collectors.toList());
                        }else {
                            finalApproveUserList = allSuperior.stream().limit(fieldVal2).collect(Collectors.toList());
                        }
                    }else {
                        //不满足条件，则按照实际设置的审批层级来
                        finalApproveUserList = allSuperior.stream().limit(cycleCount).collect(Collectors.toList());
                    }
                    log.info("[CustomFindOperatorHook][endCondition5] requestId:{},customFieldInfo:{},finalApproveUserList:{}",requestId,JSON.toJSONString(customFieldInfo),JSON.toJSONString(finalApproveUserList));
                }
            }
        }else {
            //没有设置结束条件，按照设置的层级直接查询操作者
            for (int i = 0; i < cycleCount; i++) {
                long curUserId = allSuperior.get(i);
                finalApproveUserList.add(curUserId);
            }
        }
        return finalApproveUserList;
    }

    /**
     * 浏览按钮数值比较
     * @param dataIdList 查询数据库的真实值
     * @param fieldVal 用户设置的条件值
     * @param selectVal 条件关系 属于、不属于
     * @return boolean
     */
    private boolean checkBrowserComparison(List<Long> dataIdList, JSONArray fieldVal, int selectVal) {
        if (fieldVal!=null){
            List<Long> selectDataIds = new ArrayList<>();
            fieldVal.forEach(obj->{
                selectDataIds.add(CommonUtil.null2Long(((JSONObject)obj).get("id")));
            });
            return checkComparison(dataIdList,selectDataIds,selectVal);
        }
        return false;
    }

    /**
     * 具体比较方法实现
     * @param dataIdList 查询数据库的真实值
     * @param selectDataIds 用户设置的条件值
     * @param selectVal 条件关系 属于、不属于
     * @return boolean
     */
    private boolean checkComparison(List<Long> dataIdList, List<Long> selectDataIds, int selectVal) {
        if (selectVal==21){
            //属于
            return selectDataIds.containsAll(dataIdList);
        }else if(selectVal==22){
            //不属于
            return !selectDataIds.containsAll(dataIdList);
        }
        return false;
    }

    /**
     * 数值比较
     * @param num1 查询的数据库真实值
     * @param num2 用户设置的条件值
     * @param selectVal 条件关系 = > >= < <= !=
     * @return boolean
     */
    private boolean checkNumComparison(long num1, long num2, int selectVal) {
        if (selectVal==1){
            return num1==num2;
        }else if (selectVal==2){
            return num1!=num2;
        }else if (selectVal==3){
            return num1>num2;
        }else if (selectVal==4){
            return num1>=num2;
        }else if (selectVal==5){
            return num1<num2;
        }else if (selectVal==6){
            return num1<=num2;
        }
        return false;
    }

    /**
     * Sql Query Method
     * @param sql sql
     * @return Map<String, Object>
     */
    private Map<String, Object> excuteSql(String sql,List<SqlParamEntity> sqlParams){
        return this.dataSetService.executeSql(CommonUtil.getExecuteSqlEntity(sql, flowGroupId, SourceType.getSourceTypeByValue(sourceType),sqlParams));
    }

    /**
     * 查找人员基本信息字段值
     * @param employeeIdList 待查找的人员集合
     * @param tenantKey 租户Key
     * @param fieldList 待查找的字段集合
     * @return 结果集
     */
    private Map<String,Object> findUserFieldInfo(List<Long> employeeIdList,String tenantKey,List<String> fieldList){
        HrmOrgEmpCondition hrmOrgEmpCondition = new HrmOrgEmpCondition();
        hrmOrgEmpCondition.setIds(employeeIdList);
        hrmOrgEmpCondition.setTenantKey(tenantKey);

        HrmSyncDataConfig hrmSyncDataConfig = new HrmSyncDataConfig();
        hrmSyncDataConfig.setBrowserIdAndName(true);

        WeaResult<Map<String, Object>> data = hrmRemoteIntegrationSyncDataService.pageEmployeeData(hrmOrgEmpCondition, fieldList, hrmSyncDataConfig, 1, 1000);
        return data.getCode() == 200?data.getData():null;
    }

    /**
     * 查找某个人员的所有直接上级
     * @param startUser 起始人
     * @param allManager 所有上级集合
     * @return 所有上级集合
     */
    private Set<Long> findAllManager(long startUser, Set<Long> allManager){
        WeaUser managerUser = OrgConfig.getUserService().getManager(startUser);
        long managerUserId = 0;
        if (managerUser != null&&managerUser.getUserId()!=null) {
            managerUserId = managerUser.getUserId();
            if(managerUserId == 0 || managerUserId == startUser || allManager.contains(managerUserId)){
                return allManager;
            }
        }else {
            return allManager;
        }
        allManager.add(managerUserId);
        return findAllManager(managerUserId,allManager);
    }
}
```
