xiejun
2024-01-25 9f37175c7306d5b6c4e4272b7b62d16bba1fe906
Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/service/impl/MdmEngineServiceImpl.java
@@ -1,38 +1,47 @@
package com.vci.ubcs.code.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.vci.ubcs.code.applyjtcodeservice.vo.BaseModelVO;
import com.vci.ubcs.code.bo.CodeClassifyFullInfoBO;
import com.vci.ubcs.code.bo.CodeTemplateAttrSqlBO;
import com.vci.ubcs.code.constant.FrameWorkDefaultValueConstant;
import com.vci.ubcs.code.constant.MdmBtmTypeConstant;
import com.vci.ubcs.code.dto.CodeBZApplyDTO;
import com.vci.ubcs.code.dto.CodeDeleteBatchDTO;
import com.vci.ubcs.code.dto.CodeOrderDTO;
import com.vci.ubcs.code.dto.CodeOrderSecDTO;
import com.vci.ubcs.code.dto.datapush.BaseModelDTO;
import com.vci.ubcs.code.entity.*;
import com.vci.ubcs.code.enumpack.*;
import com.vci.ubcs.code.mapper.CodeWupinMapper;
import com.vci.ubcs.code.mapper.CommonsMapper;
import com.vci.ubcs.code.service.*;
import com.vci.ubcs.code.vo.CodeKeyAttrRepeatVO;
import com.vci.ubcs.code.vo.CodeReferConfigVO;
import com.vci.ubcs.code.vo.pagemodel.UITableFieldVO;
import com.vci.ubcs.code.vo.pagemodel.UITablePageVO;
import com.vci.ubcs.code.vo.pagemodel.*;
import com.vci.ubcs.omd.feign.IAttributeClient;
import com.vci.ubcs.omd.feign.IBtmTypeClient;
import com.vci.ubcs.omd.feign.IEnumClient;
import com.vci.ubcs.omd.feign.IRevisionRuleClient;
import com.vci.ubcs.code.wrapper.BaseMdodelWrapper;
import com.vci.ubcs.flow.core.dto.FlowStatusDTO;
import com.vci.ubcs.flow.core.feign.IMDMIFlowAttrClient;
import com.vci.ubcs.flow.core.vo.ProcessStageAttrVO;
import com.vci.ubcs.omd.constant.BtmTypeLcStatusConstant;
import com.vci.ubcs.omd.cache.EnumCache;
import com.vci.ubcs.omd.feign.*;
import com.vci.ubcs.omd.utils.VciOmdUtil;
import com.vci.ubcs.omd.vo.BtmTypeAttributeVO;
import com.vci.ubcs.omd.vo.BtmTypeVO;
import com.vci.ubcs.omd.vo.EnumVO;
import com.vci.ubcs.omd.vo.RevisionRuleVO;
import com.vci.ubcs.starter.exception.VciBaseException;
import com.vci.ubcs.starter.revision.model.BaseModel;
import com.vci.ubcs.starter.revision.model.TreeQueryObject;
import com.vci.ubcs.starter.revision.model.TreeWrapperOptions;
import com.vci.ubcs.starter.revision.service.RevisionModelUtil;
import com.vci.ubcs.starter.util.*;
import com.vci.ubcs.starter.web.constant.QueryOptionConstant;
import com.vci.ubcs.starter.web.constant.RegExpConstant;
import com.vci.ubcs.starter.web.enumpck.BooleanEnum;
@@ -49,13 +58,20 @@
import com.vci.ubcs.system.user.feign.IUserClient;
import net.logstash.logback.encoder.org.apache.commons.lang3.StringUtils;
import oracle.sql.TIMESTAMP;
import org.hibernate.validator.constraints.NotEmpty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springblade.core.cache.utils.CacheUtil;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.secure.BladeUser;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.DateUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.StringPool;
import org.springblade.core.tool.utils.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.Cache;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -63,21 +79,15 @@
import javax.annotation.Resource;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Supplier;
import java.util.concurrent.*;
import java.util.stream.Collectors;
import static com.vci.ubcs.code.constant.FrameWorkLangCodeConstant.DATA_OID_NOT_EXIST;
@@ -91,17 +101,74 @@
 * @date 2022-2-22
 */
@Service
public class MdmEngineServiceImpl extends ServiceImpl<CodeWupinMapper, CodeWupin> implements MdmEngineService {
public class MdmEngineServiceImpl implements MdmEngineService {
   /**
    * 多线程方式批量执行开启线程池的总数
    */
   @Value("${batchadd.thread_num:10}")
   private Integer THREAD_NUM;
   /**
    * 单次sql的最多导入数量
    */
   @Value("${batchadd.single_maxnum:200}")
   private Integer MAX_IMPORT_NUM;
   /**
    * 是否开启多线程方式导入历史数据
    */
   @Value("${batchadd.is_thread_import:false}")
   private boolean IS_THREAD_IMPORT;
   /***
    * 操作类型
    */
   @Value("${bzApply.operationType:operationType}")
   private String operationType;
   /***
    * 是否系列
    */
   @Value("${bzApply.isSeries:isSeries}")
   private String isSeries;
   /***
    *发布时间
    */
   @Value("${bzApply.releaseTime:releaseTime}")
   private String releaseTime;
   /***
    * 源标准号
    */
   @Value("${bzApply.oldCode:oldCode}")
   private String oldCode;
   /***
    * 系列流水
    */
   @Value("${bzApply.seriesFlow:seriesFlow}")
   private String seriesFlow;
   /***
    * 是否变更系列
    */
   @Value("${bzApply.isEditSeries:isEditSeries}")
   private String isEditSeries;
   /***
    * 控制是否写入值的码段名称
    */
   @Value("${bzApply.secName:系列号}")
   private String secName;
   /***
    * 控制是否写入值的码段名称
    */
   @Value("${bzApply.yearSecName:年代号}")
   private String yearSecName;
   /**
    * 模板的服务
    */
   @Resource
   private CodeClstemplateServiceImpl templateService;
   @Resource
   private IAttributeClient attributeClient;
   private ICodeClstemplateService templateService;
   /**
    * 生成编码的服务
@@ -120,6 +187,11 @@
   @Resource
   ISysClient iSysClient;
   /**
    * 密级服务
    */
   @Resource
   private IWebSecretClient secretService;
   /**
    * 用户服务
    */
   @Resource
@@ -129,12 +201,23 @@
    */
   @Resource
   IEnumClient enumClient;
   /**
    * 版本规则服务
    */
   @Resource
   private IRevisionRuleClient revisionRuleClient;
   /**
    * 公式的服务
    */
   @Autowired
   private FormulaServiceImpl formulaService;
   /**
    * 对omd中提供的feign接口进行调用,以及处理相关逻辑
    */
   @Autowired
   ICodeReferBtmTypeService codeReferBtmTypeService;
   /**
    * 相似项查询规则
@@ -158,20 +241,13 @@
    */
   @Autowired
   private IBtmTypeClient btmTypeClient;
   /**
    * 版本规则的服务
    */
   @Resource
   private IRevisionRuleClient revisionRuleClient;
//
   /**
    * 通用查询
    */
   @Resource
   CommonsMapper commonsMapper;
   private CommonsMapper commonsMapper;
   @Resource
   CodeWupinMapper codeWupinMapper;
   /**
    * 编码规则的服务
    */
@@ -223,6 +299,7 @@
    * 空格
    */
   public static final String SPACE = " ";
   /**
    * 缓存key
    */
@@ -266,10 +343,21 @@
   /**
    * 替换字符
    */
   public static final String SPECIAL_CHAR  = "VCI";
//   @Autowired
//   private CodeOsbtmtypeMapper codeOsbtmtypeMapper;----
   public static final String SPECIAL_CHAR = "VCI";
   /**
    * 主数据流程阶段服务
    */
   @Autowired
   private IMDMIFlowAttrClient imdmiFlowAttrClient;
   //   @Autowired
   //   private CodeOsbtmtypeMapper codeOsbtmtypeMapper;
   /**
    * 日志保存工具类
    */
   @Autowired
   private SaveLogUtil saveLogUtil;
   /**
@@ -312,7 +400,7 @@
//          Dict dict = new Dict();
//         dict.setParentId(Long.valueOf(attrVO.getEnumid()));
         R<List<EnumVO>> list = enumClient.getList(attrVO.getEnumId());
         if(list.isSuccess()){
         if (list.isSuccess()) {
            for (EnumVO datum : list.getData()) {
               KeyValue keyValue = new KeyValue();
               keyValue.setKey(datum.getItemValue());
@@ -323,6 +411,7 @@
      }
      return comboboxKVs;
   }
   /**
    * 修改状态
    *
@@ -331,47 +420,57 @@
   @Transactional
   @Override
   public void changeStatus(BaseModelDTO baseModelDTO) {
      VciBaseUtil.alertNotNull(baseModelDTO, "数据信息", baseModelDTO.getOid(), "主键", baseModelDTO.getBtmname(), "业务类型", baseModelDTO.getLcStatus(), "目标状态");
      List<String> oids = VciBaseUtil.str2List(baseModelDTO.getOid());
//      List<ClientBusinessObject> cboList = boService.selectCBOByOidCollection(oids, baseModelDTO.getBtmname());
      //插个点 业务类型完成后需要修改
//      QueryWrapper<BtmTypeVO> wrapper = new QueryWrapper<>();
      List<BaseModel> baseModels = new ArrayList<>();
      baseModels = selectByTypeAndOid(baseModelDTO.getBtmname(), baseModelDTO.getOid());
      if(baseModels.size() == 0){
         throw new VciBaseException("未查询到相关数据。");
      }
      // 待完善
      List<BtmTypeVO> cboList =  null;  // btmTypeClient.selectList(wrapper);
      //还需要修改allCode的生命周期
//      Map<String, String> conditionMap = new HashMap<>();
      QueryWrapper<CodeAllCode> allCodeWrapper = new QueryWrapper<>();
      allCodeWrapper.eq("createcodebtm",baseModelDTO.getBtmname());
      allCodeWrapper.in("createcodeoid",oids);
//      conditionMap.put("createcodeoid", QueryOptionConstant.IN + "(" + VciBaseUtil.toInSql(oids.toArray(new String[0])) + ")");
//      conditionMap.put("createcodebtm", baseModelDTO.getBtmname());
      List<CodeAllCode> codeCbos = codeAllCodeService.selectByWrapper(allCodeWrapper);
//      List<ClientBusinessObject> codeCbos = boService.queryCBO(MdmBtmTypeConstant.CODE_ALL_CODE, conditionMap);
      // 回收需要业务数据删除
      if (CodeDefaultLC.TASK_BACK.getValue().equals(baseModelDTO.getLcStatus())) {
         R<List<BtmTypeVO>> listR = btmTypeClient.selectByIdCollection(Collections.singletonList(baseModelDTO.getBtmname()));
//         String referTable = listR.getData().get(0).getTableName();
         commonsMapper.deleteByTaleAndOid(listR.getData().get(0).getTableName(),VciBaseUtil.toInSql(baseModelDTO.getOid()));
         // BatchCBO batchCBO = new BatchCBO();
         // batchCBO.getDeleteCbos().addAll(cboList);
         //boService.persistenceBatch(batchCBO);
      } else {
         for (BaseModel baseModel : baseModels) {
            baseModel.setLcStatus(baseModelDTO.getLcStatus());
      try {
         VciBaseUtil.alertNotNull(baseModelDTO, "数据信息", baseModelDTO.getOid(), "主键", baseModelDTO.getBtmname(), "业务类型", baseModelDTO.getLcStatus(), "目标状态");
         List<String> oids = VciBaseUtil.str2List(baseModelDTO.getOid());
         List<BaseModel> baseModels = selectByTypeAndOid(baseModelDTO.getBtmname(), baseModelDTO.getOid());
         if (baseModels.size() == 0) {
            throw new VciBaseException("未查询到相关数据。");
         }
         updateBatchByBaseModel(baseModelDTO.getBtmname(),baseModels);
         // lifeCycleService.transCboStatus(cboList, baseModelDTO.getLcStatus());
         //还需要修改allCode的生命周期
         QueryWrapper<CodeAllCode> allCodeWrapper = new QueryWrapper<>();
         allCodeWrapper.eq("createcodebtm", baseModelDTO.getBtmname());
         allCodeWrapper.in("createcodeoid", oids);
         List<CodeAllCode> codeCbos = codeAllCodeService.selectByWrapper(allCodeWrapper);// 回收需要业务数据删除
         if (CodeDefaultLC.TASK_BACK.getValue().equals(baseModelDTO.getLcStatus())) {
            R<List<BtmTypeVO>> listR = btmTypeClient.selectByIdCollection(Collections.singletonList(baseModelDTO.getBtmname()));
            if (!listR.isSuccess() || listR.getData().size() == 0) {
               throw new VciBaseException("传入业务类型未查询到相应表单,请检查!");
            }
            // 直接删除,不给状态
            commonsMapper.deleteByTaleAndOid(listR.getData().get(0).getTableName(), VciBaseUtil.toInSql(baseModelDTO.getOid()));
            // commonsMapper.updateByTaleAndOid(listR.getData().get(0).getTableName(), VciBaseUtil.toInSql(baseModelDTO.getOid()),CodeDefaultLC.TASK_BACK.getValue());
         } else {
            for (BaseModel baseModel : baseModels) {
               baseModel.setLcStatus(baseModelDTO.getLcStatus());
            }
            R r = updateBatchByBaseModel(baseModelDTO.getBtmname(), baseModels);
            if (!r.isSuccess()) {
               throw new VciBaseException("更新数据出错,重试!" + r.getMsg());
            }
         }
         // 刚好顺序是一致的,所以直接按照codeallcode的顺序来拿业务数据
         int i = -1;
         for (CodeAllCode codeCbo : codeCbos) {
            codeCbo.setLcStatus(baseModelDTO.getLcStatus());
            // 如果是回收,就需要将业务数据存储到码值表中
            if (baseModelDTO.getLcStatus().equals(FrameWorkDefaultValueConstant.FRAMEWORK_RELEASE_TAKEBACK)) {
               codeCbo.setBusinessData(JSON.toJSONString(baseModels.get(++i)));
            }
         }
         codeAllCodeService.updateBatchById(codeCbos);
         //记录日志信息
         saveLogUtil.operateLog(
            CodeDefaultLC.getTextByValue(baseModelDTO.getLcStatus()),
            false,
            JSON.toJSONString(baseModels)
         );
      } catch (Exception e) {
         // 插入更改日志记录
         saveLogUtil.operateLog(CodeDefaultLC.getTextByValue(baseModelDTO.getLcStatus()), true, e.toString());
         throw e;
      }
      for (CodeAllCode codeCbo : codeCbos) {
         codeCbo.setLcStatus(baseModelDTO.getLcStatus());
      }
      codeAllCodeService.updateBatchById(codeCbos);
      // lifeCycleService.transCboStatus(codeCbos, baseModelDTO.getLcStatus());
   }
   /**
@@ -382,11 +481,33 @@
    */
   @Override
   public String addSaveCode(CodeOrderDTO orderDTO) throws Exception {
      return addSaveCode(orderDTO, true);
   }
   /***
    * 集成可变码段申请接口
    * @param orderDTO 申请的信息,需要包含属性的内容和码段相关的内容
    * @return
    * @throws Exception
    */
   @Override
   public String addSaveCodeNotauthUser(CodeOrderDTO orderDTO, boolean authUser) throws Exception {
      return addSaveCode(orderDTO, authUser);
   }
   /**
    * 申请单一编码
    *
    * @param orderDTO 申请的信息,需要包含属性的内容和码段相关的内容
    * @return 返回编码的内容
    */
   private String addSaveCode(CodeOrderDTO orderDTO, boolean authUser) throws Exception {
      VciBaseUtil.alertNotNull(orderDTO, "编码申请相关的属性和码段的内容都为空", orderDTO.getCodeClassifyOid(), "主题库分类的主键",
         orderDTO.getTemplateOid(), "模板的主键", orderDTO.getCodeRuleOid(), "编码规则的主键");
      CodeClassifyFullInfoBO classifyFullInfo = classifyService.getClassifyFullInfo(orderDTO.getCodeClassifyOid());
      CodeClassifyTemplateVO templateVO = templateService.getObjectHasAttrByOid(orderDTO.getTemplateOid());
      CodeRuleVO ruleVO = ruleService.getObjectHasSecByOid(orderDTO.getCodeRuleOid());
      final BladeUser user = AuthUtil.getUser();
      //1.判断规则中除了流水码段,是否有其他码段
      checkSecValueOnOrder(ruleVO, orderDTO);
      //2.判断必输项
@@ -403,32 +524,43 @@
      checkEnumOnOrder(templateVO, orderDTO);
      //8.处理时间格式,在数据库里面不论是字符串还是日期格式,都使用相同的格式存储
      switchDateAttrOnOrder(templateVO, orderDTO);
      //9.生成编码的信息
//      ClientBusinessObject cbo = boService.createCBOByBtmName(classifyFullInfo.getTopClassifyVO().getBtmtypeid());
      BaseModel cbo = createCBOByBtmName(classifyFullInfo.getTopClassifyVO().getBtmtypeid());
//      //默认的属性都不用从前端拷贝
//      //设置编码需要的默认属性的内容
      //9.生成编码的信息 ,初始化业务类型:缓存先取消,因为版本规则会出现变动的情况所以无法使用缓存
      // BaseModel cbo = createCBOByBtmName(classifyFullInfo.getTopClassifyVO().getBtmTypeId());
      BaseModel cbo = createBaseModel(classifyFullInfo.getTopClassifyVO().getBtmTypeId().trim().toLowerCase());
      //默认的属性都不用从前端拷贝
      //设置编码需要的默认属性的内容
      copyValueToCBO(classifyFullInfo, cbo, orderDTO, templateVO, false);
//      //TODO:因为默认的属性都不拷贝,目前集团码叫name,并没有从DTO拷贝到cbo里。增加一个单独处理,以后再看要不要调整
      cbo.setOid(VciBaseUtil.getPk());
      cbo.setRevisionOid(VciBaseUtil.getPk());
      cbo.setNameOid(VciBaseUtil.getPk());
      cbo.setCreateTime(new Date());
      cbo.setLastModifyTime(new Date());
      //cbo.setCreator(String.valueOf(AuthUtil.getUser().getUserId()));、
      if (authUser) {
         // 要求显示账号,所以做了更改
         cbo.setCreator(String.valueOf(user.getAccount()));
         cbo.setLastModifier(String.valueOf(user.getAccount()));
      } else {
         cbo.setCreator(orderDTO.getCreator());
         cbo.setLastModifier(orderDTO.getLastModifier());
      }
      cbo.setTenantId(user.getTenantId());
      if (StringUtils.isNotBlank(orderDTO.getLcStatus()) || StringUtils.isNotBlank(orderDTO.getData().get("lcStatus"))) {
         cbo.setLcStatus(StringUtils.isNotBlank(orderDTO.getLcStatus()) ? orderDTO.getLcStatus() : orderDTO.getData().get("lcStatus"));
      }
      //TODO:因为默认的属性都不拷贝,目前集团码叫name,并没有从DTO拷贝到cbo里。增加一个单独处理,以后再看要不要调整
      cbo.setName(orderDTO.getName() == null ? "" : orderDTO.getName());
//      //end -- modify by lihang @20220407
      //end -- modify by lihang @20220407
      List<BaseModel> cboList = new ArrayList<>();
      //备注
      cbo.setDescription(orderDTO.getDescription());
      cboList.add(cbo);
//
//      cboList.add(cbo);
      List<String> codeList = productCodeService.productCodeAndSaveData(classifyFullInfo, templateVO, ruleVO, orderDTO.getSecDTOList(),cboList);
      List<String> codeList = productCodeService.productCodeAndSaveData(classifyFullInfo, templateVO, ruleVO, orderDTO.getSecDTOList(), cboList, user);
      List<String> charList = new ArrayList<>();
      for (BaseModel baseModel : cboList) {
         charList.add(baseModel.getId());
      }
      batchSaveSelectChar(templateVO, charList);
      batchSaveSelectChar(templateVO, cboList);
      return codeList.size() > 0 ? codeList.get(0) : "";
//      return null;
   }
   /**
@@ -439,7 +571,7 @@
    * @param orderDTO           编码申请的信息
    */
   private void switchClassifyLevelOnOrder(CodeClassifyTemplateVO templateVO, CodeClassifyFullInfoBO classifyFullInfoBO, CodeOrderDTO orderDTO) {
      Map<String,CodeClassifyTemplateAttrVO> classifyAttrVOMap = templateVO.getAttributes().stream().filter(
      Map<String, CodeClassifyTemplateAttrVO> classifyAttrVOMap = templateVO.getAttributes().stream().filter(
         s -> StringUtils.isNotBlank(s.getClassifyInvokeAttr()) && StringUtils.isNotBlank(s.getClassifyInvokeLevel())
      ).collect(Collectors.toMap(s -> s.getId().toLowerCase(Locale.ROOT), t -> t));
      if (classifyFullInfoBO.getTopClassifyVO() == null) {
@@ -453,7 +585,7 @@
            if (!CodeLevelTypeEnum.MIN.getValue().equalsIgnoreCase(attrVO.getClassifyInvokeLevel()) && !"min".equalsIgnoreCase(attrVO.getClassifyInvokeLevel())) {
               //指定了层级的
               //注意,因为查询上级分类出来的层级是倒序的,即顶层节点是最大的值
               List<CodeClassifyVO> classifyVOS = classifyFullInfoBO.getParentClassifyVOs().stream().sorted(((o1, o2) -> o2.getDataLevel().compareTo(o1.getDataLevel()))).collect(Collectors.toList());
               List<CodeClassifyVO> classifyVOS = classifyFullInfoBO.getParentClassifyVOs().stream().sorted(((o1, o2) -> -o2.getDataLevel().compareTo(o1.getDataLevel()))).collect(Collectors.toList());
               int level = VciBaseUtil.getInt(attrVO.getClassifyInvokeLevel());
               if (classifyVOS.size() >= level && level > 0) {
                  classifyVO = classifyVOS.get(level - 1);
@@ -474,7 +606,6 @@
         });
      }
   }
   /**
    * 判断编码的码段是否输入或者选择了码值
@@ -536,10 +667,15 @@
      String value = null;
      if (VciQueryWrapperForDO.BASIC_FIELD_MAP.containsKey(attrId)) {
         value = WebUtil.getStringValueFromObject(WebUtil.getValueFromField(WebUtil.getFieldForObject(attrId, orderDTO.getClass()).getName(), orderDTO));
         if (StringUtils.isBlank(value)) {
            value = orderDTO.getData().getOrDefault(attrId, "");
         }
      } else {
         //说明是自行配置的
         //前端必须要传递小写的属性
         value = orderDTO.getData().getOrDefault(attrId, "");
         String orDefault = orderDTO.getData().getOrDefault(attrId, "");
         value = Func.isBlank(orDefault) ? orderDTO.getData()
            .getOrDefault(attrId.toUpperCase(Locale.ROOT), "") : orDefault;
      }
      return value;
   }
@@ -570,7 +706,6 @@
         });
      }
   }
   /**
    * 设置新的值到申请对象上
@@ -635,14 +770,23 @@
      });
      //没有限制分类,但是一个模板只可能在一个业务类型里面,所以直接查询这个业务类型即可
      if (!CollectionUtils.isEmpty(conditionMap)) {
         // TODO: 同一个库判重不需要区分分类oid
         // conditionMap.put("CODETEMPLATEOID","'" + orderDTO.getTemplateOid() + "'");
//         final String[] sql = {"select count(*) from " + VciBaseUtil.getTableName(classifyFullInfo.getTopClassifyVO().getBtmtypeid()) + " t where 1 = 1 "};
         R<List<BtmTypeVO>> listR = btmTypeClient.selectByIdCollection(Collections.singletonList(classifyFullInfo.getTopClassifyVO().getBtmtypeid()));
         R<List<BtmTypeVO>> listR = btmTypeClient.selectByIdCollection(Collections.singletonList(classifyFullInfo.getTopClassifyVO().getBtmTypeId()));
//            String referTable = VciBaseUtil.getTableName(referVO.getReferType());
         final String[] sql = {"select count(*) from "+ listR.getData().get(0).getTableName() +" t where 1 = 1 "};
         if (!listR.isSuccess() || listR.getData().size() == 0) {
            throw new VciBaseException("传入业务类型未查询到相应表单,请检查!");
         }
         //final String[] sql = {"select count(*) from " + listR.getData().get(0).getTableName() + " t where 1 = 1 "};
         final String[] sql = {"select id from " + listR.getData().get(0).getTableName() + " t where 1 = 1 "};
         conditionMap.forEach((key, value) -> {
            sql[0] += " and " + key + " = " + value;
            if (StringUtils.isBlank(value) || value.equals(QueryOptionConstant.ISNULL)) {
               sql[0] += " and " + key + " is null";
            } else {
               sql[0] += " and " + key + " = " + value;
            }
         });
         if (StringUtils.isNotBlank(orderDTO.getOid())) {
            //修改的时候,需要排除自己
@@ -650,14 +794,432 @@
         } else if (StringUtils.isNotBlank(orderDTO.getCopyFromVersion())) {
            sql[0] += " and oid != '" + orderDTO.getCopyFromVersion() + "'";
         }
         sql[0] += " and islastR = '1' and islastV = '1' ";
         sql[0] += " and lastR = '1' and lastV = '1' ";
         // 获取不参与校验的分类oid
         String isParticipateCheckOids = classifyService.selectLeafByParentClassifyOid(classifyFullInfo.getTopClassifyVO().getOid(), classifyFullInfo.getCurrentClassifyVO().getOid());
         if (Func.isNotEmpty(isParticipateCheckOids)) {
            sql[0] += " and codeclsfid not in(" + isParticipateCheckOids + ")";
         }
//         if (boService.queryCountBySql(sql[0], new HashMap<>()) > 0) {
         if (Integer.parseInt(commonsMapper.selectById(sql[0]).get(0)) > 0) {
         List<String> repeatData = commonsMapper.selectList(sql[0]);
         if (!repeatData.isEmpty()) {
            String ruleInfoMsg = keyRuleVO == null ? "" : "查询规则:去除空格--{0},忽略大小写--{1},忽略全半角--{2},忽略全部空格--{3}";
            String[] objs = new String[]{trim ? "是" : "否", ignoreCase ? "是" : "否", ignoreWidth ? "是" : "否", trimAll ? "是" : "否"};
            throw new VciBaseException("根据您填写的关键属性的内容,结合关键属性查询规则,发现这个数据已经在系统中存在了。请修正!。" + ruleInfoMsg, objs);
            throw new VciBaseException("根据您填写的关键属性的内容,结合关键属性查询规则,发现该数据已经与系统中编号为" + repeatData.stream().collect(Collectors.joining(",")) + "的数据重复。请修正!。" + ruleInfoMsg, objs);
         }
      }
   }
   /**
    * 校验关键属性
    *
    * @param orderDTO 编码申请的相关的信息
    */
   @Override
   public List<Map> checkKeyAttrOnOrderFordatas(CodeOrderDTO orderDTO) {
      List<Map> dataList = new ArrayList<>();
      CodeClassifyFullInfoBO classifyFullInfo = classifyService.getClassifyFullInfo(orderDTO.getCodeClassifyOid());
      CodeClassifyTemplateVO templateVO = templateService.getObjectHasAttrByOid(orderDTO.getTemplateOid());
      //先获取关键属性的规则,也利用继承的方式
      CodeKeyAttrRepeatVO keyRuleVO = keyRuleService.getRuleByClassifyFullInfo(classifyFullInfo);
      //注意的是keyRuleVO可能为空,表示不使用规则控制
      //获取所有的关键属性
      Map<String, CodeClassifyTemplateAttrVO> ketAttrMap = templateVO.getAttributes().stream().filter(s -> VciBaseUtil.getBoolean(s.getKeyAttrFlag())).collect(Collectors.toMap(s -> s.getId().toLowerCase(Locale.ROOT), t -> t));
      Map<String, String> conditionMap = new HashMap<>();
      boolean trimAll = keyRuleVO == null ? false : VciBaseUtil.getBoolean(keyRuleVO.getIgnoreallspaceflag());
      //全部去空的优先级大于去空
      boolean trim = keyRuleVO == null ? false : VciBaseUtil.getBoolean(keyRuleVO.getIgnorespaceflag());
      boolean ignoreCase = keyRuleVO == null ? false : VciBaseUtil.getBoolean(keyRuleVO.getIgnorecaseflag());
      boolean ignoreWidth = keyRuleVO == null ? false : VciBaseUtil.getBoolean(keyRuleVO.getIgnorewidthflag());
      ketAttrMap.forEach((attrId, attrVO) -> {
         String value = getValueFromOrderDTO(orderDTO, attrId);
         if (value == null) {
            value = "";
         }
         wrapperKeyAttrConditionMap(value, keyRuleVO, attrId, trim, ignoreCase, ignoreWidth, trimAll, conditionMap);
      });
      //没有限制分类,但是一个模板只可能在一个业务类型里面,所以直接查询这个业务类型即可
      if (!CollectionUtils.isEmpty(conditionMap)) {
         conditionMap.put("CODETEMPLATEOID", "'" + orderDTO.getTemplateOid() + "'");
//         final String[] sql = {"select count(*) from " + VciBaseUtil.getTableName(classifyFullInfo.getTopClassifyVO().getBtmtypeid()) + " t where 1 = 1 "};
         R<List<BtmTypeVO>> listR = btmTypeClient.selectByIdCollection(Collections.singletonList(classifyFullInfo.getTopClassifyVO().getBtmTypeId()));
//            String referTable = VciBaseUtil.getTableName(referVO.getReferType());
         if (!listR.isSuccess() || listR.getData().size() == 0) {
            throw new VciBaseException("传入业务类型未查询到相应表单,请检查!");
         }
         final String[] sql = {"select * from " + listR.getData().get(0).getTableName() + " t where 1 = 1 "};
         conditionMap.forEach((key, value) -> {
            if (StringUtils.isBlank(value) || value.equals(QueryOptionConstant.ISNULL)) {
               sql[0] += " and " + key + " is null";
            } else {
               sql[0] += " and " + key + " = " + value;
            }
         });
         if (StringUtils.isNotBlank(orderDTO.getOid())) {
            //修改的时候,需要排除自己
            sql[0] += " and oid != '" + orderDTO.getOid() + "'";
         } else if (StringUtils.isNotBlank(orderDTO.getCopyFromVersion())) {
            sql[0] += " and oid != '" + orderDTO.getCopyFromVersion() + "'";
         }
         sql[0] += " and lastR = '1' and lastV = '1' ";
//         if (boService.queryCountBySql(sql[0], new HashMap<>()) > 0) {
         dataList = commonsMapper.selectBySql(sql[0]);
         if (!CollectionUtils.isEmpty(dataList)) {
//            String ruleInfoMsg = keyRuleVO == null ? "" : "查询规则:去除空格--{0},忽略大小写--{1},忽略全半角--{2},忽略全部空格--{3}";
//            String[] objs = new String[]{trim ? "是" : "否", ignoreCase ? "是" : "否", ignoreWidth ? "是" : "否", trimAll ? "是" : "否"};
//            throw new VciBaseException("根据您填写的关键属性的内容,结合关键属性查询规则,发现这个数据已经在系统中存在了。请修正!。" + ruleInfoMsg, objs);
            return dataList;
         }
      }
      return dataList;
   }
   /**
    * 根据当前申请编码的分类,逐层往上校验是否符合属于配置的中的分类子节点的分
    * 类,如果符合,则该分类申请的编码为集团码返回true,反之则为企业编码返回false
    *
    * @param parameter 传入数据,classifyGroupCode:配置的中的分类顶节点,oid:选择节点的oid
    */
   @Override
   public R checkGroupCode(Map<String, String> parameter) {
      List<CodeClassify> codeClassifyList = classifyService.selectAllLevelParentByOid(parameter.get("oid"));
      Set<String> configGroupCode = Arrays.stream(parameter.get("classifyGroupCode").split("#")).collect(Collectors.toSet());
//      Boolean checkGroupFlag = false;//是否查询到配置的顶层分类中
      for (int i = codeClassifyList.size() - 1; i >= 0; i--) {
         if (configGroupCode.contains(codeClassifyList.get(i).getId())) {
//            checkGroupFlag = true;
            return R.data("true");
         }
//         if(checkGroupFlag && parameter.get("nowApplyCode").equals(codeClassifyList.get(i).getId())){
//            return R.data(true);
//         }
      }
      return R.data("false");
   }
   /***
    *
    * @param codeBZApplyDTO 编码申请相关的信息,需要有属性和码段相关的信息
    * @return
    * @throws Exception
    */
   @Override
   public String addSaveBZ(CodeBZApplyDTO codeBZApplyDTO) throws Exception {
      return addSaveBZCode(codeBZApplyDTO, true);
   }
   /**
    * 标准申请和修订用
    *
    * @param codeBZApplyDTO 编码申请相关的信息,需要有属性和码段相关的信息
    * @param authUser
    * @return
    */
   public String addSaveBZCode(CodeBZApplyDTO codeBZApplyDTO, boolean authUser) throws Exception {
      String code = "";
      VciBaseUtil.alertNotNull(codeBZApplyDTO.getCodeClassifyOid(), "主题库分类的主键",
         codeBZApplyDTO.getTemplateOid(), "模板的主键", codeBZApplyDTO.getCodeRuleOid(), "编码规则的主键");
      //操作类型
      if (StringUtils.isBlank(codeBZApplyDTO.getOperationType())) {
         String operationTypeValue = codeBZApplyDTO.getData().get(operationType);
         codeBZApplyDTO.setOperationType(operationTypeValue);
      }
      //是否系列
      if (!codeBZApplyDTO.isSeries()) {
         boolean isSeriesValue = codeBZApplyDTO.getData().get(isSeries).equals("true") ? true : false;
         codeBZApplyDTO.setSeries(isSeriesValue);
      }
      //原标准号
      if (StringUtils.isBlank(codeBZApplyDTO.getOldCode())) {
         String oldCodeValue = codeBZApplyDTO.getData().get(oldCode);
         codeBZApplyDTO.setOldCode(oldCodeValue);
      }
      //系列流水
      if (StringUtils.isBlank(codeBZApplyDTO.getSeriesFlow())) {
         String seriesFlowValue = codeBZApplyDTO.getData().get(seriesFlow);
         codeBZApplyDTO.setSeriesFlow(seriesFlowValue);
      }
      //发布时间
      if (StringUtils.isBlank(codeBZApplyDTO.getReleaseTime())) {
         String releaseTimeValue = codeBZApplyDTO.getData().get(releaseTime);
         codeBZApplyDTO.setReleaseTime(releaseTimeValue);
      }
      //是否变更系列
      if (!codeBZApplyDTO.isEditSeries()) {
         boolean isEditSeriesValue = codeBZApplyDTO.getData().get(isEditSeries).equals("true") ? true : false;
         codeBZApplyDTO.setEditSeries(isEditSeriesValue);
      }
      VciBaseUtil.alertNotNull(codeBZApplyDTO.getOperationType(), "操作类型",
         codeBZApplyDTO.isSeries(), "是否系列", codeBZApplyDTO.getReleaseTime(), "发布时间");
      if (codeBZApplyDTO.getOperationType().equals(CodeBZOperationTypeEnum.CODE_BZ_FORMULATE.getValue())) {//制定
         code = addsaveDataBZ(codeBZApplyDTO, authUser);
      } else if (codeBZApplyDTO.getOperationType().equals(CodeBZOperationTypeEnum.CODE_BZ_AMENDMENT.getValue())) {//修订
         VciBaseUtil.alertNotNull(codeBZApplyDTO.getOldCode(), "源标准号");
         code = amendmentDataBZ(codeBZApplyDTO, authUser);
         createChangeOder(code, codeBZApplyDTO, authUser);
      } else if (codeBZApplyDTO.getOperationType().equals(CodeBZOperationTypeEnum.CODE_BZ_EDIT.getValue())) {//更改
         code = amendmentDataBZ(codeBZApplyDTO, authUser);
         createChangeOder(code, codeBZApplyDTO, authUser);
      } else if (codeBZApplyDTO.getOperationType().equals(CodeBZOperationTypeEnum.CODE_BZ_DISABLE.getValue())) {//作废
         code = amendmentDataBZ(codeBZApplyDTO, authUser);
         createChangeOder(code, codeBZApplyDTO, authUser);
      } else if (codeBZApplyDTO.getOperationType().equals(CodeBZOperationTypeEnum.CODE_BZ_AMENDMENT.getValue())) {//备查
         code = amendmentDataBZ(codeBZApplyDTO, authUser);
         createChangeOder(code, codeBZApplyDTO, authUser);
      }
      return code;
   }
   /***
    * 修订
    * @param codeBZApplyDTO
    * @param authUser
    * @return
    */
   private String amendmentDataBZ(CodeBZApplyDTO codeBZApplyDTO, boolean authUser) throws Exception {
      CodeOrderDTO orderDTO = new CodeOrderDTO();
      BeanUtil.convert(codeBZApplyDTO, orderDTO);
      CodeRuleVO ruleVO = ruleService.getObjectHasSecByOid(codeBZApplyDTO.getCodeRuleOid());
      Map<String, CodeBasicSecVO> codeCodeBasicSecMap = ruleVO.getSecVOList().stream().filter(s -> StringUtils.isNotBlank(s.getOid())).collect(Collectors.toMap(s -> s.getOid().toLowerCase(Locale.ROOT), t -> t));
      VciBaseUtil.alertNotNull(orderDTO, "编码申请相关的属性和码段的内容都为空", orderDTO.getCodeClassifyOid(), "主题库分类的主键",
         orderDTO.getTemplateOid(), "模板的主键", orderDTO.getCodeRuleOid(), "编码规则的主键");
      String oldCode = codeBZApplyDTO.getOldCode();//源标准编码
      String releaseTime = codeBZApplyDTO.getReleaseTime();
      List<CodeOrderSecDTO> secDTOS = orderDTO.getSecDTOList();
      LinkedList<CodeOrderSecDTO> newSecDTOList = new LinkedList<>();
      changeCodeOrderSecDTO(ruleVO, secDTOS, oldCode, newSecDTOList);//根据要求重新算码段码值
      if (!codeBZApplyDTO.isEditSeries()) {//变更为标准
         //if(!codeBZApplyDTO.isSeries()){//如果是表准,则需要将系列好流水置为null
         //因为是标准则控制码段中的系列流水码段值为空
         newSecDTOList.stream().forEach(codeOrderSecDTO -> {
            if (codeCodeBasicSecMap.containsKey(codeOrderSecDTO.getSecOid()) && codeCodeBasicSecMap.get(codeOrderSecDTO.getSecOid()).getName().equals(secName)) {
               codeOrderSecDTO.setSecValue("");
            }
         });
         //}
         orderDTO.setSecDTOList(newSecDTOList);
         return createDataBZ(orderDTO, ruleVO, authUser);
      } else {//变更为系列.则按照逻辑去处理
         orderDTO.setSecDTOList(newSecDTOList);
         return createDataBZ(orderDTO, ruleVO, authUser);
      }
   }
   private String createDataBZ(CodeOrderDTO orderDTO, CodeRuleVO ruleVO, boolean authUser) throws Exception {
      CodeClassifyFullInfoBO classifyFullInfo = classifyService.getClassifyFullInfo(orderDTO.getCodeClassifyOid());
      CodeClassifyTemplateVO templateVO = templateService.getObjectHasAttrByOid(orderDTO.getTemplateOid());
      //1.判断规则中除了流水码段,是否有其他码段
      checkSecValueOnOrder(ruleVO, orderDTO);
      //2.判断必输项
      checkRequiredAttrOnOrder(templateVO, orderDTO);
      //3.先注入,再组合,最后校验
      switchClassifyLevelOnOrder(templateVO, classifyFullInfo, orderDTO);
      //4.处理组合规则。组合规则不能使用编码的属性,因为编码的生成可能是需要属性的
      switchComponentAttrOnOrder(templateVO, orderDTO);
      //5.校验规则
      checkVerifyOnOrder(templateVO, orderDTO);
      //6.关键属性
      checkKeyAttrOnOrder(classifyFullInfo, templateVO, orderDTO);
      //7.枚举转换
      checkEnumOnOrder(templateVO, orderDTO);
      //8.处理时间格式,在数据库里面不论是字符串还是日期格式,都使用相同的格式存储
      switchDateAttrOnOrder(templateVO, orderDTO);
      //9.生成编码的信息 ,初始化业务类型:缓存先取消,因为版本规则会出现变动的情况所以无法使用缓存
      // BaseModel cbo = createCBOByBtmName(classifyFullInfo.getTopClassifyVO().getBtmTypeId());
      BaseModel cbo = createBaseModel(classifyFullInfo.getTopClassifyVO().getBtmTypeId().trim().toLowerCase());
      //默认的属性都不用从前端拷贝
      //设置编码需要的默认属性的内容
      copyValueToCBO(classifyFullInfo, cbo, orderDTO, templateVO, false);
      cbo.setOid(VciBaseUtil.getPk());
      cbo.setRevisionOid(VciBaseUtil.getPk());
      cbo.setNameOid(VciBaseUtil.getPk());
      cbo.setCreateTime(new Date());
      cbo.setLastModifyTime(new Date());
      //cbo.setCreator(String.valueOf(AuthUtil.getUser().getUserId()));、
      if (authUser) {
         // 要求显示账号,所以做了更改
         cbo.setCreator(String.valueOf(AuthUtil.getUser().getAccount()));
         cbo.setLastModifier(String.valueOf(AuthUtil.getUser().getAccount()));
      } else {
         cbo.setCreator(orderDTO.getCreator());
         cbo.setLastModifier(orderDTO.getLastModifier());
      }
      cbo.setTenantId(AuthUtil.getTenantId());
      if (StringUtils.isNotBlank(orderDTO.getLcStatus()) || StringUtils.isNotBlank(orderDTO.getData().get("lcStatus"))) {
         cbo.setLcStatus(StringUtils.isNotBlank(orderDTO.getLcStatus()) ? orderDTO.getLcStatus() : orderDTO.getData().get("lcStatus"));
      }
      //TODO:因为默认的属性都不拷贝,目前集团码叫name,并没有从DTO拷贝到cbo里。增加一个单独处理,以后再看要不要调整
      cbo.setName(orderDTO.getName() == null ? "" : orderDTO.getName());
      //end -- modify by lihang @20220407
      List<BaseModel> cboList = new ArrayList<>();
      //备注
      cbo.setDescription(orderDTO.getDescription());
      cboList.add(cbo);
      List<String> codeList = productCodeService.productCodeAndSaveDataBZ(classifyFullInfo, templateVO, ruleVO, orderDTO.getSecDTOList(), cboList);
      batchSaveSelectChar(templateVO, cboList);
      return codeList.size() > 0 ? codeList.get(0) : "";
   }
   /***
    * 根据编号获取码段码值
    * @param secDTOList
    */
   private void changeCodeOrderSecDTO(CodeRuleVO ruleVO, List<CodeOrderSecDTO> secDTOList, String oldCode, LinkedList<CodeOrderSecDTO> newSecDTOList) throws Exception {
      //还需要修改allCode的生命周期
      QueryWrapper<CodeAllCode> allCodeWrapper = new QueryWrapper<>();
      allCodeWrapper.in("id", VciBaseUtil.str2List(oldCode));
      Map<String, String> secDTOMap = secDTOList.stream().collect(Collectors.toMap(s -> s.getSecOid(), t -> t.getSecValue(), (o1, o2) -> o2));
      List<CodeAllCode> codeAllcodeList = codeAllCodeService.selectByWrapper(allCodeWrapper);
      if (!CollectionUtils.isEmpty(codeAllcodeList)) {
         String codeDelimit = codeAllcodeList.get(0).getCodeDelimit();
         String[] secValues = StringUtils.splitByWholeSeparatorPreserveAllTokens(codeDelimit, SERIAL_VALUE_SPACE);
         //VciBaseUtil.str2List()
         for (int i = 0; i < ruleVO.getSecVOList().size(); i++) {
            CodeBasicSecVO codeBasicSecVO = ruleVO.getSecVOList().get(i);
            CodeOrderSecDTO codeOrderSecDTO = new CodeOrderSecDTO();
            String secValue = secValues[i];
            boolean isRoman = VciBaseUtil.isRoman(secValue);
            if (isRoman) {
               continue;
            }
            if (secDTOMap.containsKey(codeBasicSecVO.getOid())) {
               secValue = secDTOMap.get(codeBasicSecVO.getOid());
            }
            if (StringUtils.isNotBlank(secValue)) {
               codeOrderSecDTO.setSecOid(codeBasicSecVO.getOid());
               codeOrderSecDTO.setSecValue(secValue);
               newSecDTOList.add(codeOrderSecDTO);
            }
         }
      } else {
         throw new Exception("根据原标准编号,在系统中未查询到相应的信息");
      }
   }
   /***
    * 制定,则不需要产生更改单直接生成编码
    * @param codeBZApplyDTO
    * @param authUser
    * @return
    */
   private String addsaveDataBZ(CodeBZApplyDTO codeBZApplyDTO, boolean authUser) throws Exception {
      String code = "";
      CodeOrderDTO orderDTO = new CodeOrderDTO();
      BeanUtil.convert(codeBZApplyDTO, orderDTO);
      CodeRuleVO ruleVO = ruleService.getObjectHasSecByOid(codeBZApplyDTO.getCodeRuleOid());
      Map<String, CodeBasicSecVO> codeCodeBasicSecMap = ruleVO.getSecVOList().stream().filter(s -> StringUtils.isNotBlank(s.getOid())).collect(Collectors.toMap(s -> s.getOid(), t -> t));
      //是否是标准,不是标准的不会去管
      if (!codeBZApplyDTO.isSeries()) {
         //因为是标准则控制码段中的系列流水码段值为空
         orderDTO.getSecDTOList().stream().forEach(codeOrderSecDTO -> {
            if (codeCodeBasicSecMap.containsKey(codeOrderSecDTO.getSecOid()) && codeCodeBasicSecMap.get(codeOrderSecDTO.getSecOid()).getName().equals(secName)) {
               codeOrderSecDTO.setSecValue("");
            }
         });
      }
      VciBaseUtil.alertNotNull(orderDTO, "编码申请相关的属性和码段的内容都为空", orderDTO.getCodeClassifyOid(), "主题库分类的主键",
         orderDTO.getTemplateOid(), "模板的主键", orderDTO.getCodeRuleOid(), "编码规则的主键");
      return createDataBZ(orderDTO, ruleVO, authUser);
   }
   /***
    * 更改单的创建
    * @param code
    * @param codeBZApplyDTO
    * @param authUser
    * @return
    */
   private String createChangeOder(String code, CodeBZApplyDTO codeBZApplyDTO, boolean authUser) {
      return "";
   }
   /***
    * 集成可变码段申请接口
    * @param codeBZApplyDTO 申请的信息,需要包含属性的内容和码段相关的内容
    * @param    authUser 是否用登录用户记录
    * @return
    * @throws Exception
    */
   @Override
   public String addSaveBZCodeNotauthUser(CodeBZApplyDTO codeBZApplyDTO, boolean authUser) throws Exception {
      return addSaveBZCode(codeBZApplyDTO, authUser);
   }
   /**
    * 获取统计分析数据
    *
    * @param btmNames 业务类型
    * @return 数据集
    */
   @Override
   public R getStatisticAnalysis(String btmNames) {
      //查询业务类型对应的数据库表
      R<List<BtmTypeVO>> listR = btmTypeClient.selectByIdCollection(Arrays.asList(btmNames.split(",")));
      if (!listR.isSuccess() || listR.getData().size() == 0) {
         throw new ServiceException("传入业务类型未查询到相应表单,请检查!");
      }
      List tableData = new ArrayList();
      for (BtmTypeVO datum : listR.getData()) {
         String sql = "select count(*) countNum, to_char(CREATETIME, 'mm') countDate\n" +
            "from " + datum.getTableName() + "\n" +
            "where CREATETIME >= to_date(EXTRACT(YEAR FROM SYSDATE) || '-01-01 00:00:00', 'yyyy-mm-dd hh24:mi:ss') AND LASTV = '1'\n" +
            "group by to_char(CREATETIME, 'mm')\n" +
            "order by to_char(CREATETIME, 'mm')";
         //查询出需要处理的数据
         List<Map> maps = commonsMapper.selectBySql(sql);
         //当年每月月份之前之和
         List<Integer> monthCount = new ArrayList<>(12);
         //当年每月的月份数据
         List<Integer> month = new ArrayList<>();
         //获取当前月的数字
         Calendar instance = Calendar.getInstance();
         int nowmonth = instance.get(Calendar.MONTH) + 1;
         if (maps.size() == 0) {
            nowmonth = 0;
         }
         //从1到12月进行处理
         for (Integer i = 1; i <= 12; i++) {
            //当前月后所有数据设置为0
            if (i > nowmonth) {
               monthCount.add(0);
               month.add(0);
               continue;
            }
            //当前月份之前之和
            Integer count = 0;
            //当前月份数据
            Integer sameMonth = 0;
            //对数据库查的数据进行处理,对当前月份进行累加
            for (Map map : maps) {
               Integer mounDate = Integer.parseInt(String.valueOf(map.get("COUNTDATE")));
               if (mounDate <= i) {
                  count += Integer.parseInt(String.valueOf(map.get("COUNTNUM")));
               }
               if (mounDate == i) {
                  sameMonth = Integer.parseInt(String.valueOf(map.get("COUNTNUM")));
               }
            }
            monthCount.add(count);
            month.add(sameMonth);
         }
         //对数据进行整合
         HashMap<String, Object> menuData = new HashMap<>();
         menuData.put("menuName", datum.getName());
         menuData.put("codeType", null);
         ArrayList monthData = new ArrayList();
         monthData.add(monthCount);
         monthData.add(month);
         menuData.put("menuData", monthData);
         tableData.add(menuData);
      }
      return R.data(tableData);
   }
   /**
@@ -679,7 +1241,7 @@
      boolean ignoreSpace = trim || trimAll;
      if (StringUtils.isBlank(value)) {
         //为空的时候,不能用QueryOperation.ISNULL,平台不知道啥时候不处理这种了
         conditionMap.put("t."+attrId, "null");
         conditionMap.put("t." + attrId, QueryOptionConstant.ISNULL);
      } else {
         if (keyRuleVO != null) {
            String queryKey = "";
@@ -711,12 +1273,16 @@
               //不忽略大小写、不去空、不忽略全半角
               temp = "%s";
            }
            queryKey = String.format(temp, "t."+attrId);
            queryValue = String.format(temp, "'" + (trim ? value.trim() : value) + "'");
            queryKey = String.format(temp, "nvl(" + "t." + attrId + ",'/')");
            queryValue = String.format(temp, "'" + (trim ? SpecialCharacterConverter.escapeSpecialCharacters(value.trim()) : SpecialCharacterConverter.escapeSpecialCharacters(value)) + "'");
            conditionMap.put(queryKey, queryValue);
         } else {
            //为空的时候不代表不校验,只是不去除相关的信息
            conditionMap.put("t."+attrId, value);
            if (StringUtils.isNotBlank(value)) {
               //为空的时候不代表不校验,只是不去除相关的信息
               conditionMap.put("nvl(" + "t." + attrId + ",'/')", "'" + SpecialCharacterConverter.escapeSpecialCharacters(value) + "'");
            } else {
               conditionMap.put("t." + attrId, QueryOptionConstant.ISNULL);
            }
         }
      }
   }
@@ -777,7 +1343,7 @@
    */
   private void copyValueToCBO(CodeClassifyFullInfoBO classifyFullInfo, BaseModel cbo,
                        CodeOrderDTO orderDTO, CodeClassifyTemplateVO templateVO,
                        boolean edit)  {
                        boolean edit) {
      String fullPath = "";
      if (!CollectionUtils.isEmpty(classifyFullInfo.getParentClassifyVOs())) {
         fullPath = classifyFullInfo.getParentClassifyVOs().stream().sorted(((o1, o2) -> o2.getDataLevel().compareTo(o1.getDataLevel())))
@@ -785,60 +1351,44 @@
      } else {
         fullPath = classifyFullInfo.getCurrentClassifyVO().getOid();
      }
//      BeanUtils.
//      BeanUtils.copyProperties(orderDTO.getData(),cbo);
//      cbo.setMaterialtype(Short.valueOf("1001"));
//      orderDTO.getData().forEach((key, value) -> {
//         if (!edit || (!checkUnAttrUnEdit(key) &&
//            !VciQueryWrapperForDO.LC_STATUS_FIELD.equalsIgnoreCase(key))) {
//            try {
//               cbo.setAttributeValue(key, value);
//            } catch (Exception e) {
//               logger.error("设置属性的值错误", e);
//            }
//         }
//      });
//      BeanMap beanMap = BeanMap.create(cbo);
//      beanMap.putAll(orderDTO.getData());
      orderDTO.getData().forEach((key, value) -> {
         if (!edit || (!checkUnAttrUnEdit(key) &&
            !VciQueryWrapperForDO.LC_STATUS_FIELD.equalsIgnoreCase(key))) {
            try {
               cbo.getData().put(cbo.getData().containsKey(key.toUpperCase()) ? key.toUpperCase() : key, value);
            } catch (Exception e) {
               logger.error("设置属性的值错误", e);
            }
         }
      });
      try {
         BeanUtilForVCI.copyPropertiesIgnoreNull(BeanUtilForVCI.convertMap(BaseModel.class,orderDTO.getData()),cbo);
         Map<String,String> data = new HashMap<>();
         data.put(CODE_CLASSIFY_OID_FIELD,classifyFullInfo.getCurrentClassifyVO().getOid());
         data.put(CODE_TEMPLATE_OID_FIELD,templateVO.getOid());
         data.put(CODE_FULL_PATH_FILED,fullPath);
         cbo.setData(data);
         cbo.setOid(VciBaseUtil.getPk());
         cbo.setCreateTime(new Date());
         Map<String, String> data = new HashMap<>();
         data.put(cbo.getData().containsKey(CODE_CLASSIFY_OID_FIELD.toUpperCase()) ? CODE_CLASSIFY_OID_FIELD.toUpperCase() : CODE_CLASSIFY_OID_FIELD, classifyFullInfo.getCurrentClassifyVO().getOid());
         data.put(cbo.getData().containsKey(CODE_TEMPLATE_OID_FIELD.toUpperCase()) ? CODE_TEMPLATE_OID_FIELD.toUpperCase() : CODE_TEMPLATE_OID_FIELD, templateVO.getOid());
         data.put(cbo.getData().containsKey(CODE_FULL_PATH_FILED.toUpperCase()) ? CODE_FULL_PATH_FILED.toUpperCase() : CODE_FULL_PATH_FILED, fullPath);
         cbo.getData().putAll(data);
         cbo.setLastModifyTime(new Date());
         cbo.setCreator(AuthUtil.getUser().getUserName());
         cbo.setLastModifier(AuthUtil.getUser().getUserName());
//         cbo.setCodeclsfid(classifyFullInfo.getCurrentClassifyVO().getOid());
//         cbo.setTemplateOid(templateVO.getOid());
//         cbo.setCodeclsfpath(fullPath);
         //cbo.setLastModifier(AuthUtil.getUser().getUserName());
         cbo.setLastModifier(AuthUtil.getUser().getAccount());
         cbo.setTs(new Date());
         if (!edit && StringUtils.isBlank(orderDTO.getLcStatus())) {
            //先写固定,后面生命周期好了在编写
            //TODO 先写固定,后面生命周期好了在编写
            if (StringUtils.isNotBlank(cbo.getLctid())) {
//               OsLifeCycleVO lifeCycleVO = lifeCycleService.getLifeCycleById(cbo.getLctid());
//               if (lifeCycleVO != null) {
//                  cbo.setLcStatus("Editing");
////                  cbo.setLcStatus(lifeCycleVO.getStartStatus());
//               } else {
               cbo.setLcStatus(CodeDefaultLC.EDITING.getValue());
               cbo.setLcStatus(CodeDefaultLC.RELEASED.getValue());
//               }
            } else {
               cbo.setLcStatus(CodeDefaultLC.EDITING.getValue());
               cbo.setLcStatus(CodeDefaultLC.RELEASED.getValue());
            }
         }
         int secret = VciBaseUtil.getInt(String.valueOf(cbo.getSecretGrade()));
         //后续看密级服务是否可用
//         if (secret == 0 || !secretService.checkDataSecret(secret)) {
         if (secret == 0 ) {
         if (secret == 0 || !secretService.checkDataSecret(secret).getData()) {
            Integer userSecret = VciBaseUtil.getCurrentUserSecret();
//            cbo.setAttributeValue(SECRET_FIELD, String.valueOf((userSecret == null || userSecret == 0) ? UserSecretEnum.NONE.getValue() : userSecret));
            cbo.setSecretGrade(userSecret == null || userSecret == 0 ? UserSecretEnum.NONE.getValue() : userSecret);
@@ -848,10 +1398,10 @@
      }
   }
   /**
    * 初始化业务类型
    * --创建人默认为当前用户,如果需要修改,可以在获取后自行处理
    *
    * @param btmName 业务类型的名称,会自动变成小写
    * @return CodeWupinEntity
    * @throws VciBaseException 初始化出错的是会抛出异常
@@ -859,84 +1409,23 @@
   @Override
   public BaseModel createCBOByBtmName(String btmName)
      throws VciBaseException {
      if(btmName!=null){
      if (btmName != null) {
         btmName = btmName.trim().toLowerCase();
      }
      try {
         String keyPrefix = BTM_INIT_CACHE.concat(StringPool.COLON).concat(AuthUtil.getTenantId()).concat(StringPool.COLON);
//         String finalBtmName = btmName;
         Cache.ValueWrapper valueWrapper = CacheUtil.getCache(keyPrefix).get(keyPrefix.concat(String.valueOf(btmName)));
         if(valueWrapper == null){
         if (valueWrapper == null) {
            CacheUtil.getCache(keyPrefix).put(keyPrefix.concat(String.valueOf(btmName)), createBaseModel(btmName));
            valueWrapper = CacheUtil.getCache(keyPrefix).get(keyPrefix.concat(String.valueOf(btmName)));
         }
         return (BaseModel) valueWrapper.get();
      } catch (Exception e) {
         logger.error("创建业务类型对象",e);
         throw new VciBaseException("initBtmError",new String[]{btmName});
         logger.error("创建业务类型对象", e);
         throw new ServiceException("initBtmError:" + "业务类型:" + btmName + ":" + e.getMessage());
      }
//      String userName = AuthUtil.getUser().getUserName();
//      CodeWupin wupinEntity = new CodeWupin();
//      wupinEntity.setOid(VciBaseUtil.getPk());
////      bo.setRevisionid((new ObjectUtility()).getNewObjectID36());
////      bo.setNameoid((new ObjectUtility()).getNewObjectID36());
//      wupinEntity.setBtmname(btmName);
//      wupinEntity.setLastR(String.valueOf(1));
//      wupinEntity.setFirstR(String.valueOf(1));
//      wupinEntity.setFirstV(String.valueOf(1));
//      wupinEntity.setLastV(String.valueOf(1));
//      wupinEntity.setCreator(userName);
//      wupinEntity.setCreateTime(new Date());
//      wupinEntity.setLastModifier(userName);
//      wupinEntity.setLastModifyTime(new Date());
//      wupinEntity.setRevisionRule("numberversionrule");
//      wupinEntity.setVersionRule("0");
////      if(StringUtils.isNotBlank(btmTypeVO.getRevisionruleid())){
//         //
////         OsRevisionRuleVO revisionRuleVO = revisionRuleService.getRevisionRuleById(btmTypeVO.getRevisionruleid());
//      wupinEntity.setRevisionValue("1");
////      }
//
//      wupinEntity.setRevisionSeq(1);
//      wupinEntity.setVersionSeq(1);
//      //插个点,需要问勇哥版本问题,展示默认为1
//      wupinEntity.setVersionValue("1");
//      wupinEntity.setLctid("wupinLC");
//      wupinEntity.setLcStatus("Editing");
//      wupinEntity.setId("");
//      wupinEntity.setName("");
//      wupinEntity.setDescription("");
//      wupinEntity.setOwner(userName);
//      wupinEntity.setCheckinby(userName);
//      wupinEntity.setCopyFromVersion("");
//      wupinEntity.setMaterialtype(1001);
//      wupinEntity.setCaigouwl("true");
//      wupinEntity.setShifoupihaoguanli("true");
//      wupinEntity.setKucunwl("true");
//      wupinEntity.setXiaoshouwl("false");
//      wupinEntity.setPassing("true");
//      this.initTypeAttributeValue(wupinEntity,btmTypeVO);
//      return wupinEntity;
//      return cbo;
   }
   /**
    * 是否为修改忽略的属性
    * @param attrName 属性的名字
    * @return true 表示应该忽略
    */
   boolean checkUnAttrUnEdit(String attrName){
      return  (VciQueryWrapperForDO.OID_FIELD.equalsIgnoreCase(attrName)
         ||"ts".equalsIgnoreCase(attrName)
         || "lastmodifier".equalsIgnoreCase(attrName)
         || "lastmodifytime".equalsIgnoreCase(attrName)
         || "createtime".equalsIgnoreCase(attrName)
         || "checkintime".equalsIgnoreCase(attrName)
         ||"checkouttime".equalsIgnoreCase(attrName));
   }
   /**
    * 保存可输可选的信息
@@ -946,21 +1435,34 @@
    */
   @Override
   public void batchSaveSelectChar(CodeClassifyTemplateVO templateVO, /*List<ClientBusinessObject> cboList*/
                           List<String> cboList) {
                           List<BaseModel> cboList) {
      if (templateVO != null && !CollectionUtils.isEmpty(cboList)) {
         //是异步的,所以直接循环
         List<CodeClassifyTemplateAttrVO> selectAttrVOs = templateVO.getAttributes().stream().filter(s -> StringUtils.isNotBlank(s.getLibraryIdentification())).collect(Collectors.toList());
         if (!CollectionUtils.isEmpty(selectAttrVOs)) {
//            SessionInfo sessionInfo = VciBaseUtil.getCurrentUserSessionInfo();
            //SessionInfo sessionInfo = VciBaseUtil.getCurrentUserSessionInfo();
            selectAttrVOs.parallelStream().forEach(attrVO -> {
               List<String> valuesList = cboList;
//               cboList.parallelStream().forEach(cbo -> {
//                  String value = cbo.get.getAttributeValue(attrVO.getId());
//                  if (StringUtils.isNotBlank(value)) {
//                     valuesList.add(value);
//                  }
//               });
               List<String> valuesList = new ArrayList<>();
               cboList.parallelStream().forEach(cbo -> {
                  //String value = cbo.get.getAttributeValue(attrVO.getId());
                  //将bean转为map,mybatis统一处理
                  Map<String, String> map = null;
                  //baseModels.stream().forEach(model-> {
                  try {
                     map = VciBaseUtil.convertBean2Map(cbo, null);
                  } catch (Exception e) {
                     throw new VciBaseException("类型转换错误:" + e.getMessage());
                  }
                  //});
                  String value = map.get(attrVO.getId());
                  if (StringUtils.isNotBlank(value)) {
                     valuesList.add(value);
                  }
               });
               if (!CollectionUtils.isEmpty(valuesList)) {
                  for (String s : valuesList) {
                     DictBiz dictBiz = new DictBiz();
@@ -974,6 +1476,27 @@
               }
            });
         }
      }
   }
   /**
    * 封装开关的内容,常用于导出
    *
    * @param dataMap    数据的内容
    * @param templateVO 模板的显示
    */
   @Override
   public void wrapperBoolean(List<Map<String, String>> dataMap, CodeClassifyTemplateVO templateVO) {
      List<String> booleanAttributes = templateVO.getAttributes().stream().filter(s -> VciFieldTypeEnum.VTBoolean.name().equalsIgnoreCase(s.getAttributeDataType())).map(s -> s.getId().toLowerCase(Locale.ROOT)).collect(Collectors.toList());
      if (!CollectionUtils.isEmpty(booleanAttributes)) {
         dataMap.stream().forEach(data -> {
            booleanAttributes.stream().forEach(attrId -> {
               if (data.containsKey(attrId)) {
                  String value = data.get(attrId);
                  data.put(attrId, BooleanEnum.TRUE.getValue().equalsIgnoreCase(value) ? "是" : "否");
               }
            });
         });
      }
   }
@@ -1005,13 +1528,16 @@
      CodeClassifyFullInfoBO classifyFullInfo = classifyService.getClassifyFullInfo(codeClassifyOid);
      List<UIFormItemVO> itemVOS = new ArrayList<>();
      Map<String, List<CodeClassifyTemplateAttrVO>> attrGroupMap = templateVO.getAttributes().stream().
         filter(s -> StringUtils.isNotBlank(s.getAttributeGroup())).collect(Collectors.groupingBy(s -> s.getAttributeGroup()));
      templateVO.getAttributes().forEach(attrVO -> {
         UIFormItemVO formItemVO = templateAttr2FormField(attrVO, templateVO.getBtmTypeId());
         itemVOS.add(formItemVO);
      });
      Map<String, List<CodeClassifyTemplateAttrVO>> attrGroupMap = new HashMap<>();
      if (Func.isNotEmpty(templateVO.getAttributes())) {
         attrGroupMap = templateVO.getAttributes().stream().
            filter(s -> StringUtils.isNotBlank(s.getAttributeGroup())).collect(Collectors.groupingBy(s -> s.getAttributeGroup()));
         templateVO.getAttributes().forEach(attrVO -> {
            UIFormItemVO formItemVO = templateAttr2FormField(attrVO, templateVO.getBtmTypeId());
            itemVOS.add(formItemVO);
         });
      }
      //处理属性分组
      if (!CollectionUtils.isEmpty(attrGroupMap)) {
         //按照分组的属性排列,找到每一个分组的第一个属性
@@ -1024,6 +1550,10 @@
            lineVO.setField(attrVO.getId() + "_line");
            lineVO.setType("line");
            lineVO.setText(key);
            List<CodeClassifyTemplateAttrVO> collect = value.stream().filter(s -> "true".equals(s.getFormDisplayFlag())).collect(Collectors.toList());
            if (collect.size() == 0) {
               continue;
            }
            //找位置
            for (int i = 0; i < itemVOS.size(); i++) {
               UIFormItemVO record = itemVOS.get(i);
@@ -1052,6 +1582,7 @@
      //查询是否有分类注入的
      return formDefineVO;
   }
   /**
    * 属性类型与js中的字段类型的映射
    */
@@ -1125,8 +1656,9 @@
         itemVO.setType("refer");
         itemVO.setShowField(itemVO.getField() + "name");
         if (StringUtils.isNotBlank(attrVO.getReferConfig())) {
            //配置的内容
            itemVO.setReferConfig(JSONObject.parseObject(attrVO.getReferConfig(), UIFormReferVO.class));
            // 配置的内容
            // itemVO.setReferConfig(JSONObject.parseObject(attrVO.getReferConfig(), UIFormReferVO.class));
            itemVO.setReferConfig(referConfigToUIUiTable(attrVO.getReferConfig()));
         } else {
            UIFormReferVO formReferVO = new UIFormReferVO();
            formReferVO.setType("default");
@@ -1174,7 +1706,7 @@
         //处理所有的列,这个模板没有合并的表头的情况
         List<UITableFieldVO> fieldVOList = new ArrayList<>();
         resembleAttrList.forEach(attrVO -> {
            UITableFieldVO tableFieldVO = templateAttr2TableField(attrVO,false);
            UITableFieldVO tableFieldVO = templateAttr2TableField(attrVO, false);
            tableFieldVO.setHidden(false);
            fieldVOList.add(tableFieldVO);
         });
@@ -1189,12 +1721,12 @@
   /**
    * 模板属性转换为表格显示的配置
    *
    * @param attrVO 模板属性
    * @param attrVO  模板属性
    * @param forEdit 是否是编辑所需
    * @return 表格的字段
    */
   @Override
   public UITableFieldVO templateAttr2TableField(CodeClassifyTemplateAttrVO attrVO,boolean forEdit) {
   public UITableFieldVO templateAttr2TableField(CodeClassifyTemplateAttrVO attrVO, boolean forEdit) {
      UITableFieldVO fieldVO = new UITableFieldVO();
      if (SECRET_FILED.equalsIgnoreCase(attrVO.getId())) {
         attrVO.setEnumId(MY_DATA_SECRET);
@@ -1205,9 +1737,9 @@
      fieldVO.setSort(true);
      fieldVO.setSortField(fieldVO.getField());
      fieldVO.setQueryField(fieldVO.getField());
      if (forEdit){
      if (forEdit) {
         fieldVO.setHidden(!VciBaseUtil.getBoolean(attrVO.getFormDisplayFlag()));
      }else {
      } else {
         fieldVO.setHidden(!VciBaseUtil.getBoolean(attrVO.getTableDisplayFlag()));
      }
      if (attrVO.getAttrTableWidth() != null && attrVO.getAttrTableWidth() > 0) {
@@ -1227,9 +1759,9 @@
            if (StringUtils.isBlank(attrVO.getEnumId())) {
               fieldVO.setComboxKey(fieldVO.getField() + "_data");
            }
         }else {
//            List<KeyValue> osEnumItemVOList= enumService.getEnum(attrVO.getEnumId());
//            fieldVO.setData(osEnumItemVOList);
         } else {
            List<KeyValue> osEnumItemVOList = VciOmdUtil.enumsToListKeyVale(EnumCache.getList(attrVO.getEnumId()));
            fieldVO.setData(osEnumItemVOList);
         }
      }
      //看是否有参照
@@ -1240,7 +1772,8 @@
         fieldVO.setShowField(fieldVO.getField());
         if (StringUtils.isNotBlank(attrVO.getReferConfig())) {
            //配置的内容
            fieldVO.setReferConfig(JSONObject.parseObject(attrVO.getReferConfig(), UIFormReferVO.class));
            // fieldVO.setReferConfig(JSONObject.parseObject(attrVO.getReferConfig(), UIFormReferVO.class));
            fieldVO.setReferConfig(referConfigToUIUiTable(attrVO.getReferConfig()));
         } else {
            UIFormReferVO formReferVO = new UIFormReferVO();
            formReferVO.setType("default");
@@ -1263,15 +1796,67 @@
         fieldVO.setTemplet(attrVO.getTableDisplayJs());
      }
      if (StringUtils.isBlank(fieldVO.getTemplet()) && VciFieldTypeEnum.VTBoolean.name().equalsIgnoreCase(attrVO.getAttributeDataType())) {
         fieldVO.setTemplet("function(d){return $webUtil.formateBoolean(d." + fieldVO.getField() + ");}");
         fieldVO.setTemplet("function(row,column){return row[column.property]=='true' || row[column.property]=='1'?'是':'否'}");
//            fieldVO.setTemplet("function(d){return $webUtil.formateBoolean(d." + fieldVO.getField() + ");}");
      }
      fieldVO.setOptionJsMap(eventJsMap);
      fieldVO.setStyle(attrVO.getTableDisplayStyle());
      fieldVO.setTableDisplayFlag(attrVO.getTableDisplayFlag());
      //列表里不允许直接编辑
      fieldVO.setDateFormate(attrVO.getCodeDateFormat());
      return fieldVO;
   }
   /**
    * 将referconfig转换为JSON格式的UIFormReferVO
    *
    * @param codeReferConfigVO
    * @return
    */
   private UIFormReferVO referConfigToUIUiTable(String codeReferConfigVO) {
      CodeReferConfigVO codeReferConfig = JSONObject.parseObject(codeReferConfigVO, CodeReferConfigVO.class);
      // 拷贝为以前的老对象
      UIFormReferVO uiFormReferVO = new UIFormReferVO();
      org.springblade.core.tool.utils.BeanUtil.copy(codeReferConfig, uiFormReferVO);
      // 表格的自定义定义
      UITableCustomDefineVO uiTableConfigVO = new UITableCustomDefineVO();
      uiTableConfigVO.setPage(new UITablePageVO(codeReferConfig.getLimit(), 1));
      // 列表的列的信息转换
      List<UITableFieldVO> uiTableFieldVOs = new ArrayList<>();
      // 快速查询列
      List<UITableFieldVO> queryColumns = new ArrayList<>();
      if (!CollectionUtils.isEmpty(codeReferConfig.getCodeShowFieldConfigVOS())) {
         codeReferConfig.getCodeShowFieldConfigVOS().stream().forEach(showField -> {
            UITableFieldVO tableColVO = new UITableFieldVO();
            org.springblade.core.tool.utils.BeanUtil.copy(showField, tableColVO);
            tableColVO.setSortField(showField.getAttrSortField());
            uiTableFieldVOs.add(tableColVO);
            if (showField.getIsQuery().equals("true")) {
               queryColumns.add(tableColVO);
            }
         });
      }
      // 显示的列
      uiTableConfigVO.setCols(uiTableFieldVOs);
      // 快速查询列
      uiTableConfigVO.setQueryColumns(queryColumns);
      //set给表格配置属性
      uiFormReferVO.setTableConfig(uiTableConfigVO);
      //字段名不一致,需要手动set
      uiFormReferVO.setMuti(StringUtils.isBlank(codeReferConfig.getIsMuti()) ? false : true);
      uiFormReferVO.setInitSort(new UIFieldSortVO(codeReferConfig.getSortField(), codeReferConfig.getSortType()));
      // 筛选条件
      HashMap<String, String> whereMap = new HashMap<>();
      if (!CollectionUtils.isEmpty(codeReferConfig.getCodeSrchCondConfigVOS())) {
         codeReferConfig.getCodeSrchCondConfigVOS().stream().forEach(srch -> {
            whereMap.put(srch.getFilterField() + srch.getFilterType(), srch.getFilterValue());
         });
      }
      uiFormReferVO.setWhere(whereMap);
      return uiFormReferVO;
   }
   /**
    * 相似项查询
@@ -1315,7 +1900,7 @@
         conditionMap.putAll(andConditionMap);
         PageHelper pageHelper = new PageHelper(-1);
         pageHelper.addDefaultDesc("id");
         return queryGrid(fullInfoBO.getTopClassifyVO().getBtmtypeid(), templateVO, conditionMap, pageHelper);
         return queryGrid(fullInfoBO.getTopClassifyVO().getBtmTypeId(), templateVO, conditionMap, pageHelper);
      }
      return new DataGrid<>();
   }
@@ -1336,11 +1921,11 @@
         //说明已经存在
         return resembleRuleService.getObjectByOid(currentClassifyVO.getCodeResembleRuleOid());
      }
      if (StringUtils.isBlank(currentClassifyVO.getParentcodeclassifyoid())) {
      if (StringUtils.isBlank(currentClassifyVO.getParentCodeClassifyOid())) {
         return null;
      }
      Map<String, CodeClassifyVO> classifyVOMap = fullInfoBO.getParentClassifyVOs().stream().collect(Collectors.toMap(s -> s.getOid(), t -> t));
      return getUseResembleRule(fullInfoBO, classifyVOMap.getOrDefault(currentClassifyVO.getParentcodeclassifyoid(), null));
      return getUseResembleRule(fullInfoBO, classifyVOMap.getOrDefault(currentClassifyVO.getParentCodeClassifyOid(), null));
   }
   /**
@@ -1362,7 +1947,7 @@
         boolean ignoreCase = VciBaseUtil.getBoolean(resembleRuleVO.getIgnorecaseflag());
         boolean ignoreWidth = VciBaseUtil.getBoolean(resembleRuleVO.getIgnorewidthflag());
         boolean trimAll = VciBaseUtil.getBoolean(resembleRuleVO.getIgnoreallspaceflag());
         boolean trim = VciBaseUtil.getBoolean(resembleRuleVO.getIgnoreallspaceflag());
         boolean trim = VciBaseUtil.getBoolean(resembleRuleVO.getIgnorecaseflag());
         String temp = "";
         if (ignoreCase && ignoreSpace && ignoreWidth) {
            //忽略大小写,且去空,忽略全半角
@@ -1396,13 +1981,12 @@
               temp = "replace(" + temp + ",'" + s + "','')";
            }
         }
         queryValue = String.format(temp, (trim ? value.trim() : value));
         temp = temp.replace("to_single_byte('%s')","to_single_byte(%s)");
         queryKey = String.format(temp, "t."+attrId);
         queryValue = String.format(temp, (trim ? "'"+value.trim()+"'" : "'"+value+"'"));
         temp = temp.replace("to_single_byte('%s')", "to_single_byte(%s)");
         queryKey = String.format(temp, "t." + attrId);
         conditionMap.put(queryKey, QueryOptionConstant.OR + queryValue);
      }
   }
   /**
    * 查询编码数据的列表
@@ -1417,7 +2001,16 @@
   public DataGrid<Map<String, String>> queryGrid(String btmType, CodeClassifyTemplateVO templateVO, Map<String, String> conditionMap, PageHelper pageHelper) {
      CodeTemplateAttrSqlBO sqlBO = getSqlByTemplateVO(btmType, templateVO, conditionMap, pageHelper);
//      List<Map> maps = boService.queryByOnlySqlForMap(sqlBO.getSqlHasPage());
      List<Map<String,String>> maps = commonsMapper.queryByOnlySqlForMap(sqlBO.getSqlHasPage());
      List<Map<String, String>> maps = null;
      try {
         maps = commonsMapper.queryByOnlySqlForMap(sqlBO.getSqlHasPage());
      } catch (Exception e) {
         String errorMessage = e.getMessage();
         if (errorMessage.contains("无法解析的成员访问表达式")) {
            throw new ServiceException("缺少" + errorMessage.substring(errorMessage.indexOf("[t.") + 1, errorMessage.indexOf("]")) + "字段");
         }
         throw new ServiceException(e.getMessage());
      }
      DataGrid<Map<String, String>> dataGrid = new DataGrid<>();
      List<Map<String, String>> dataList = new ArrayList<>();
@@ -1425,7 +2018,7 @@
         maps.stream().forEach(map -> {
            Map<String, String> data = new HashMap<>();
            for (String s : map.keySet()) {
               data.put(s.toLowerCase(Locale.ROOT), String.valueOf(map.get(s)));
               data.put(s.toLowerCase(Locale.ROOT), map.get(s) == null ? null : String.valueOf(map.get(s)));
            }
//            map.forEach((key, value) -> {
//               data.put(((String) key).toLowerCase(Locale.ROOT), String.valueOf(value));
@@ -1470,7 +2063,7 @@
    * @param dataMap              数据的映射
    * @param templateVO           模板的属性
    * @param onlySelectAttrIdList 仅仅查询的属性字段
    * @param form 表单里使用
    * @param form                 表单里使用
    */
   @Override
   public void wrapperData(List<Map<String, String>> dataMap, CodeClassifyTemplateVO templateVO,
@@ -1480,36 +2073,42 @@
      }
      //先转换一下时间格式
      List<String> finalOnlySelectAttrIdList = onlySelectAttrIdList.stream().collect(Collectors.toList());
      List<CodeClassifyTemplateAttrVO> dateFormatAttrVOs = templateVO.getAttributes().stream().filter(
         s -> StringUtils.isNotBlank(s.getCodeDateFormat()) &&
            (finalOnlySelectAttrIdList.size() == 0 || finalOnlySelectAttrIdList.contains(s.getId().toLowerCase(Locale.ROOT)))
      ).collect(Collectors.toList());
      //枚举的内容
      List<CodeClassifyTemplateAttrVO> enumAttrVOs = templateVO.getAttributes().stream().filter(
         s -> (StringUtils.isNotBlank(s.getEnumId()) || StringUtils.isNotBlank(s.getEnumString()))
            &&
            (finalOnlySelectAttrIdList.size() == 0 || finalOnlySelectAttrIdList.contains(s.getId().toLowerCase(Locale.ROOT)))
      ).collect(Collectors.toList());
      List<CodeClassifyTemplateAttrVO> dateFormatAttrVOs = new ArrayList<>();
      List<CodeClassifyTemplateAttrVO> enumAttrVOs = new ArrayList<>();
      if (Func.isNotEmpty(templateVO.getAttributes())) {
         dateFormatAttrVOs = templateVO.getAttributes().stream().filter(
            s -> StringUtils.isNotBlank(s.getCodeDateFormat()) &&
               (finalOnlySelectAttrIdList.size() == 0 || finalOnlySelectAttrIdList.contains(s.getId().toLowerCase(Locale.ROOT)))
         ).collect(Collectors.toList());
         //枚举的内容
         enumAttrVOs = templateVO.getAttributes().stream().filter(
            s -> (StringUtils.isNotBlank(s.getEnumId()) || StringUtils.isNotBlank(s.getEnumString()))
               &&
               (finalOnlySelectAttrIdList.size() == 0 || finalOnlySelectAttrIdList.contains(s.getId().toLowerCase(Locale.ROOT)))
         ).collect(Collectors.toList());
      }
      List<String> userIds = new ArrayList<>();
      List<CodeClassifyTemplateAttrVO> finalDateFormatAttrVOs = dateFormatAttrVOs;
      List<CodeClassifyTemplateAttrVO> finalEnumAttrVOs = enumAttrVOs;
      dataMap.stream().forEach(data -> {
         //处理时间
         if (!form) {
            //表单的时候只能用统一的时间格式
            wrapperDateFormat(dateFormatAttrVOs, data);
            wrapperDateFormat(finalDateFormatAttrVOs, data);
         }
         //处理枚举
         wrapperEnum(enumAttrVOs, data);
         wrapperEnum(finalEnumAttrVOs, data);
         String lcstatus = data.get(VciQueryWrapperForDO.LC_STATUS_FIELD);
         String copyFromVersion = data.getOrDefault(COPY_FROM_VERSION,"");
         String copyFromVersion = data.getOrDefault(COPY_FROM_VERSION, "");
         if ((CodeDefaultLC.EDITING.getValue().equalsIgnoreCase(lcstatus) || CodeDefaultLC.AUDITING.getValue().equalsIgnoreCase(lcstatus))
            && StringUtils.isBlank(copyFromVersion)
         ) {
            data.put(VciQueryWrapperForDO.ID_FIELD, "******");
         }
         data.put(VciQueryWrapperForDO.LC_STATUS_FIELD_TEXT.toLowerCase(Locale.ROOT), CodeDefaultLC.getTextByValue(lcstatus));
         if(CodeDefaultLC.EDITING.getValue().equalsIgnoreCase(lcstatus)
            && StringUtils.isNotBlank(copyFromVersion)){
         if (CodeDefaultLC.EDITING.getValue().equalsIgnoreCase(lcstatus)
            && StringUtils.isNotBlank(copyFromVersion)) {
            data.put(VciQueryWrapperForDO.LC_STATUS_FIELD_TEXT.toLowerCase(Locale.ROOT), "修改中");
         }
         if (data.containsKey("creator")) {
@@ -1522,12 +2121,12 @@
      if (!CollectionUtils.isEmpty(userIds)) {
         Map<String, User> userVOMap = new HashMap<>();
         for (String userId : userIds) {
            if(!StringUtils.isNumeric(userId)){
            if (!StringUtils.isNumeric(userId)) {
               continue;
            }
            User data = iUserClient.userInfoById(Long.valueOf(userId)).getData();
            if(data != null){
               userVOMap.put(String.valueOf(data.getId()),data);
            if (data != null) {
               userVOMap.put(String.valueOf(data.getId()), data);
            }
         }
//         Map<String, SmUserVO> userVOMap = Optional.ofNullable(userQueryService.listUserByUserIds(userIds)).orElseGet(() -> new ArrayList<>()).stream().collect(Collectors.toMap(s -> s.getId().toLowerCase(Locale.ROOT), t -> t));
@@ -1599,7 +2198,6 @@
      }
   }
   /**
    * 根据模板属性生成相应的sql信息
    *
@@ -1614,16 +2212,24 @@
      //因为参照不一定是在平台的属性池里面设置,所以我们得需要自行处理
      //参考VciQueryWrapper来处理
      //1. 找到所有的字段,
      Map<String, CodeClassifyTemplateAttrVO> attrVOMap = templateVO.getAttributes().stream().collect(Collectors.toMap(s -> s.getId().toLowerCase(Locale.ROOT), t -> t));
      List<String> selectFieldList = attrVOMap.keySet().stream().collect(Collectors.toList());
      Map<String, CodeClassifyTemplateAttrVO> attrVOMap = new HashMap<>();
      List<String> selectFieldList = new ArrayList<>();
      if (Func.isNotEmpty(templateVO.getAttributes())) {
         attrVOMap = templateVO.getAttributes().stream().collect(Collectors.toMap(s -> s.getId().toLowerCase(Locale.ROOT), t -> t));
         selectFieldList = attrVOMap.keySet().stream().collect(Collectors.toList());
      }
      //所有的参照的字段
      Map<String/**属性字段**/, String> joinTableList = new ConcurrentHashMap<>();
      List<CodeClassifyTemplateAttrVO> referAttrVOs = templateVO.getAttributes().stream().filter(
         s -> StringUtils.isNotBlank(s.getReferBtmId()) || StringUtils.isNotBlank(s.getReferConfig())
      ).collect(Collectors.toList());
      Map<String/**参照的属性**/, String/**实际的字段**/> referFieldMap = new HashMap<>();
      List<CodeClassifyTemplateAttrVO> referAttrVOs = null;
      if (Func.isNotEmpty(templateVO.getAttributes())) {
         referAttrVOs = templateVO.getAttributes().stream().filter(
            s -> StringUtils.isNotBlank(s.getReferBtmId()) || StringUtils.isNotBlank(s.getReferConfig())
         ).collect(Collectors.toList());
      }
      Map<String/**参照的属性**/, String/**实际的字段**/> referFieldMap = new ConcurrentHashMap<>();
      if (!CollectionUtils.isEmpty(referAttrVOs)) {
         List<String> finalSelectFieldList = selectFieldList;
         referAttrVOs.parallelStream().forEach(attrVO -> {
            UIFormReferVO referVO = null;
            if (StringUtils.isNotBlank(attrVO.getReferConfig())) {
@@ -1637,6 +2243,9 @@
            //使用传入的业务类型查询表
            R<List<BtmTypeVO>> listR = btmTypeClient.selectByIdCollection(Collections.singletonList(referVO.getReferType()));
//            String referTable = VciBaseUtil.getTableName(referVO.getReferType());
            if (!listR.isSuccess() || listR.getData().size() == 0) {
               throw new VciBaseException("传入业务类型未查询到相应表单,请检查!");
            }
            String referTable = listR.getData().get(0).getTableName();
//            String referTable = "pl_code_classify";
            String referTableNick = attrVO.getId() + "0";
@@ -1651,16 +2260,12 @@
               showFieldInSource = textFields.get(0);
            }
            referFieldMap.put(attrVO.getId(), referTableNick + "." + showFieldInSource);
            selectFieldList.add(referTableNick + "." + showFieldInSource + " as " + referShowField);
            finalSelectFieldList.add(referTableNick + "." + showFieldInSource + " as " + referShowField);
         });
      }
      R<BtmTypeVO> allAttributeByBtmId = btmTypeClient.getDefaultAttrByBtmId(btmType);
//      Optional.ofNullable(allAttributeByBtmId.getData()).orElseGet(allAttributeByBtmId.getData().getAttributes()).stream().forEach(attrId -> {
//         if (!selectFieldList.contains(attrId.getOid()) && !"secretgrade".equalsIgnoreCase(attrId.getOid())) {
//            selectFieldList.add(attrId.getOid());
//         }
//      });
      if(allAttributeByBtmId.getData() != null ){
      if (allAttributeByBtmId.getData() != null) {
         for (BtmTypeAttributeVO attribute : allAttributeByBtmId.getData().getAttributes()) {
            if (!selectFieldList.contains(attribute.getId()) && !"secretgrade".equalsIgnoreCase(attribute.getId())) {
               selectFieldList.add(attribute.getId());
@@ -1699,11 +2304,12 @@
            }
         });
         Map<String, CodeClassifyTemplateAttrVO> finalAttrVOMap = attrVOMap;
         andCondtionMap.forEach((k, v) -> {
            andSql.add(getConditionSql(k.toLowerCase(), v, referFieldMap, attrVOMap));
            andSql.add(getConditionSql(k.toLowerCase(), v, referFieldMap, finalAttrVOMap, btmType));
         });
         orConditionMap.forEach((k, v) -> {
            orSql.add(getConditionSql(k.toLowerCase(), v, referFieldMap, attrVOMap));
            orSql.add(getConditionSql(k.toLowerCase(), v, referFieldMap, finalAttrVOMap, btmType));
         });
      }
      //组合起来
@@ -1731,12 +2337,15 @@
      if (attrVOMap.keySet().contains("secretgrade")) {
         Integer userSecret = VciBaseUtil.getCurrentUserSecret();
         if (userSecret == null || userSecret == 0) {
//            userSecret = secretService.getMinUserSecret();
            userSecret = secretService.getMinUserSecret().getData();
         }
         whereSql += " and ( t.secretGrade <= " + userSecret + ") ";
      }
//      String tableName = VciBaseUtil.getTableName(btmType);
      R<List<BtmTypeVO>> listR = btmTypeClient.selectByIdCollection(Collections.singletonList(btmType));
      if (!listR.isSuccess() || listR.getData().size() == 0) {
         throw new VciBaseException("传入业务类型未查询到相应表单,请检查!");
      }
//            String referTable = VciBaseUtil.getTableName(referVO.getReferType());
      String tableName = listR.getData().get(0).getTableName();
      String sql = "select " + selectFieldList.stream().map(s -> (s.contains(".") ? s : ("t." + s))).collect(Collectors.joining(","))
@@ -1754,6 +2363,8 @@
      String sqlHasPage = pageHelper.getLimit() > 0 ? ("select * from (select A.*,rownum RN from (" + sql + whereSubfixForPage) : sql;
      String sqlCount = "select count(1) from " + tableName + SPACE + "t" + SPACE + joinTableList.values().stream().collect(Collectors.joining(SPACE))
         + (StringUtils.isBlank(whereSql) ? "" : " where ") + whereSql;
      String sqlId = "select t.ID from " + tableName + SPACE + "t" + SPACE + joinTableList.values().stream().collect(Collectors.joining(SPACE))
         + (StringUtils.isBlank(whereSql) ? "" : " where ") + whereSql;
      CodeTemplateAttrSqlBO sqlBO = new CodeTemplateAttrSqlBO();
      sqlBO.setTableName(tableName);
      sqlBO.setJoinTable(joinTableList);
@@ -1762,9 +2373,9 @@
      sqlBO.setSqlHasPage(sqlHasPage);
      sqlBO.setSqlCount(sqlCount);
      sqlBO.setSqlUnPage(sql);
      sqlBO.setSqlId(sqlId);
      return sqlBO;
   }
   /**
    * 组合查询条件的sql
@@ -1775,8 +2386,156 @@
    * @param attrVOMap     属性的映射
    * @return Sql语句
    */
   private String getConditionSql(String key, String value, Map<String/**参照的属性**/, String/**实际的属性**/> referFieldMap, Map<String, CodeClassifyTemplateAttrVO> attrVOMap) {
      if (key.endsWith("_begin")) {
   private String getConditionSql(String key, String value, Map<String/**参照的属性**/, String/**实际的属性**/> referFieldMap, Map<String, CodeClassifyTemplateAttrVO> attrVOMap, String btmType) {
      if (!Func.hasEmpty(new Object[]{key, value}) && !key.endsWith("_ignore")) {
         if (key.endsWith("_like")) {
            String field = UBCSSqlKeyword.getColumn(key, "_like");
            if (referFieldMap.containsKey(field)) {
               //说明还是参照里面的,我们默认这种情况下都是字符串吧,因为参照的属性不一定用的平台的属性池里的,所以大部分情况下,显示的属性都是字符串吧
               return referFieldMap.get(field) + SPACE + "LIKE" + SPACE + "'%" + value + "%'" + SPACE;
            } else {
               return (field.contains(".") ? "" : "t.") + field + SPACE + "LIKE " + "'%" + value + "%'" + SPACE;
            }
         } else if (key.endsWith("_notequal")) {
            String field = UBCSSqlKeyword.getColumn(key, "_notequal");
            if (referFieldMap.containsKey(field)) {
               return referFieldMap.get(field) + SPACE + " != " + value + SPACE;
            } else {
               return (field.contains(".") ? "" : "t.") + field + SPACE + " != " + getStringValueInWhere(field, value, attrVOMap);
            }
         } else if (key.endsWith("_likeleft")) {
            String field = UBCSSqlKeyword.getColumn(key, "_likeleft");
            if (referFieldMap.containsKey(field)) {
               return referFieldMap.get(field) + SPACE + "LIKE" + SPACE + "%" + value + SPACE;
            } else {
               return (field.contains(".") ? "" : "t.") + field + SPACE + "LIKE " + "%" + getStringValueInWhere(field, value, attrVOMap) + SPACE;
            }
         } else if (key.endsWith("_likeright")) {
            String field = UBCSSqlKeyword.getColumn(key, "_likeright");
            if (referFieldMap.containsKey(field)) {
               return referFieldMap.get(field) + SPACE + "LIKE" + SPACE + value + "%" + SPACE;
            } else {
               return (field.contains(".") ? "" : "t.") + field + SPACE + "LIKE " + getStringValueInWhere(field, value, attrVOMap) + "%" + SPACE;
            }
         } else if (key.endsWith("_notlike")) {
            String field = UBCSSqlKeyword.getColumn(key, "_notlike");
            if (referFieldMap.containsKey(field)) {
               return referFieldMap.get(field) + SPACE + "NO LIKE" + SPACE + "%" + value + "%" + SPACE;
            } else {
               return (field.contains(".") ? "" : "t.") + field + SPACE + "NO LIKE " + "%" + getStringValueInWhere(field, value, attrVOMap) + "%" + SPACE;
            }
         } else if (key.endsWith("_ge")) {
            String field = UBCSSqlKeyword.getColumn(key, "_ge");
            if (referFieldMap.containsKey(field)) {
               return referFieldMap.get(field) + SPACE + " >= " + value + SPACE;
            } else {
               return (field.contains(".") ? "" : "t.") + field + SPACE + " >= " + getStringValueInWhere(field, value, attrVOMap) + SPACE;
            }
         } else if (key.endsWith("_le")) {
            //说明是<=的。我们需要先获取一下
            String field = UBCSSqlKeyword.getColumn(key, "_le");
            if (referFieldMap.containsKey(field)) {
               return referFieldMap.get(field) + SPACE + " <= " + value + "" + SPACE;
            } else {
               return (field.contains(".") ? "" : "t.") + field + SPACE + " <= " + getStringValueInWhere(field, value, attrVOMap) + SPACE;
            }
         } else if (key.endsWith("_gt")) {
            String field = UBCSSqlKeyword.getColumn(key, "_gt");
            if (referFieldMap.containsKey(field)) {
               return referFieldMap.get(field) + SPACE + "> " + value + SPACE;
            } else {
               return (field.contains(".") ? "" : "t.") + field + SPACE + "> " + getStringValueInWhere(field, value, attrVOMap) + SPACE;
            }
         } else if (key.endsWith("_lt")) {
            String field = UBCSSqlKeyword.getColumn(key, "_lt");
            if (referFieldMap.containsKey(field)) {
               return referFieldMap.get(field) + SPACE + "< " + value + SPACE;
            } else {
               return (field.contains(".") ? "" : "t.") + field + SPACE + "< " + getStringValueInWhere(field, value, attrVOMap) + SPACE;
            }
         } else if (key.endsWith("_datege")) {
            String field = UBCSSqlKeyword.getColumn(key, "_datege");
            if (referFieldMap.containsKey(field)) {
               return referFieldMap.get(field) + SPACE + ">= '" + DateUtil.parse(String.valueOf(value), "yyyy-MM-dd HH:mm:ss") + "'" + SPACE;
            } else {
               return (field.contains(".") ? "" : "t.") + field + SPACE + ">= '" + DateUtil.parse(String.valueOf(getStringValueInWhere(field, value, attrVOMap)), "yyyy-MM-dd HH:mm:ss") + "'" + SPACE;
            }
         } else if (key.endsWith("_dategt")) {
            String field = UBCSSqlKeyword.getColumn(key, "_dategt");
            if (referFieldMap.containsKey(field)) {
               return referFieldMap.get(field) + SPACE + "> '" + DateUtil.parse(String.valueOf(value), "yyyy-MM-dd HH:mm:ss") + "'" + SPACE;
            } else {
               return (field.contains(".") ? "" : "t.") + field + SPACE + "> '" + DateUtil.parse(String.valueOf(getStringValueInWhere(field, value, attrVOMap)), "yyyy-MM-dd HH:mm:ss") + "'" + SPACE;
            }
         } else if (key.endsWith("_dateequal")) {
            String field = UBCSSqlKeyword.getColumn(key, "_dateequal");
            if (referFieldMap.containsKey(field)) {
               return referFieldMap.get(field) + SPACE + "= '" + DateUtil.parse(String.valueOf(value), "yyyy-MM-dd HH:mm:ss") + "'" + SPACE;
            } else {
               return (field.contains(".") ? "" : "t.") + field + SPACE + "= '" + DateUtil.parse(String.valueOf(getStringValueInWhere(field, value, attrVOMap)), "yyyy-MM-dd HH:mm:ss") + "'" + SPACE;
            }
         } else if (key.endsWith("_datele")) {
            String field = UBCSSqlKeyword.getColumn(key, "_datele");
            if (referFieldMap.containsKey(field)) {
               return referFieldMap.get(field) + SPACE + "<= '" + DateUtil.parse(String.valueOf(value), "yyyy-MM-dd HH:mm:ss") + "'" + SPACE;
            } else {
               return (field.contains(".") ? "" : "t.") + field + SPACE + "<= '" + DateUtil.parse(String.valueOf(getStringValueInWhere(field, value, attrVOMap)), "yyyy-MM-dd HH:mm:ss") + "'" + SPACE;
            }
         } else if (key.endsWith("_datelt")) {
            String field = UBCSSqlKeyword.getColumn(key, "_datelt");
            if (referFieldMap.containsKey(field)) {
               return referFieldMap.get(field) + SPACE + "< '" + DateUtil.parse(String.valueOf(value), "yyyy-MM-dd HH:mm:ss") + "'" + SPACE;
            } else {
               return (field.contains(".") ? "" : "t.") + field + SPACE + "< '" + DateUtil.parse(String.valueOf(getStringValueInWhere(field, value, attrVOMap)), "yyyy-MM-dd HH:mm:ss") + "'" + SPACE;
            }
         } else if (key.endsWith("_null")) {
            String field = UBCSSqlKeyword.getColumn(key, "_null");
            if (referFieldMap.containsKey(field)) {
               return referFieldMap.get(field) + SPACE + "IS NULL" + SPACE;
            } else {
               return (field.contains(".") ? "" : "t.") + field + SPACE + "IS NULL" + SPACE;
            }
         } else if (key.endsWith("_notnull")) {
            String field = UBCSSqlKeyword.getColumn(key, "_null");
            if (referFieldMap.containsKey(field)) {
               return referFieldMap.get(field) + SPACE + "IS NOT NULL" + SPACE;
            } else {
               return (field.contains(".") ? "" : "t.") + field + SPACE + "IS NOT NULL" + SPACE;
            }
         } else if (key.endsWith("_dateequal")) {
            String field = UBCSSqlKeyword.getColumn(key, "_dateequal");
            if (referFieldMap.containsKey(field)) {
               return referFieldMap.get(field) + SPACE + "= '" + DateUtil.parse(String.valueOf(value), "yyyy-MM-dd HH:mm:ss") + "'" + SPACE;
            } else {
               return (field.contains(".") ? "" : "t.") + field + SPACE + "= '" + DateUtil.parse(String.valueOf(getStringValueInWhere(field, value, attrVOMap)), "yyyy-MM-dd HH:mm:ss") + "'" + SPACE;
            }
         } else if (key.endsWith("_equal")) {
            String field = UBCSSqlKeyword.getColumn(key, "_equal");
            if (referFieldMap.containsKey(field)) {
               return referFieldMap.get(field) + SPACE + "= '" + value + "'" + SPACE;
            } else {
               return (field.contains(".") ? "" : "t.") + field + SPACE + "= " + getStringValueInWhere(field, value, attrVOMap) + "" + SPACE;
            }
         } else if (key.endsWith("_in")) {
            String field = UBCSSqlKeyword.getColumn(key, "_in");
            if (referFieldMap.containsKey(field)) {
               return VciBaseUtil.toInSql(referFieldMap.get(field), value);  //referFieldMap.get(field) + SPACE + "= '" + value + "'" + SPACE;
            } else {
               return (field.contains(".") ? "" : "t.") + field + SPACE + "= " + getStringValueInWhere(field, value, attrVOMap) + "" + SPACE;
            }
         } else {
//                if (referFieldMap.containsKey(key)) {
//                    //说明是参照的,我们参照的查询都认为是字符串,如果是时间格式的查询肯定有问题,
//                    String selectKey = referFieldMap.get(key);
//                    return getSqlByValue(selectKey, value, null, btmType);
//                } else {
            return getSqlByValue(key, value, attrVOMap, btmType);
//                }
         }
      }
      return "";
      /*if (key.endsWith("_begin")) {
         //说明是>=的。我们需要先获取一下
         String field = (key.substring(0, key.length() - 6).toLowerCase().trim());
         if (referFieldMap.containsKey(field)) {
@@ -1798,12 +2557,11 @@
         if (referFieldMap.containsKey(key)) {
            //说明是参照的,我们参照的查询都认为是字符串,如果是时间格式的查询肯定有问题,
            String selectKey = referFieldMap.get(key);
            return getSqlByValue(selectKey, value, null);
            return getSqlByValue(selectKey, value, null,btmType);
         } else {
            return getSqlByValue(key, value, attrVOMap);
            return getSqlByValue(key, value, attrVOMap,btmType);
         }
      }
      }*/
   }
   /**
@@ -1838,12 +2596,24 @@
            }
            DateConverter dateConverter = new DateConverter();
            if (VciFieldTypeEnum.VTDateTime.equals(fieldTypeEnum)) {
               //实际上,数据库都是timestamp的类型.
               dateConverter.setAsText(value);
               return "to_date('" + dateConverter.getAsText(VciDateUtil.DateTimeFormat) + "','" + DATETIME_FORMAT + "')";
               //实际上,数据库都是timestamp的类型. TODO:虽然没能解决查询日期的问题,但是能暂时解决报错问题
               if (value.contains("*")) {
                  value = value.replace("*", "%");
                  return "'" + value + "'";
               } else {
                  value = value.replace("*", "");
                  dateConverter.setAsText(value);
                  return "to_date('" + dateConverter.getAsText(VciDateUtil.DateTimeFormat) + "','" + DATETIME_FORMAT + "')";
               }
            } else if (VciFieldTypeEnum.VTDate.equals(fieldTypeEnum)) {
               dateConverter.setAsText(value);
               return "to_date('" + dateConverter.getAsText(VciDateUtil.DateFormat) + "','" + DATE_FORMAT + "')";
               if (value.contains("*")) {
                  value = value.replace("*", "%");
                  return "'" + value + "'";
               } else {
                  value = value.replace("*", "");
                  dateConverter.setAsText(value);
                  return "to_date('" + dateConverter.getAsText(VciDateUtil.DateFormat) + "','" + DATE_FORMAT + "')";
               }
            } else if (VciFieldTypeEnum.VTDouble.equals(fieldTypeEnum)
               || VciFieldTypeEnum.VTLong.equals(fieldTypeEnum)
               || VciFieldTypeEnum.VTInteger.equals(fieldTypeEnum)) {
@@ -1862,6 +2632,25 @@
   }
   /**
    * 查看是否默认属性
    *
    * @param selectKey
    * @param btmType
    * @return
    */
   private boolean isDefaultAttr(String selectKey, String btmType) {
      if (StringUtils.isBlank(btmType)) {
         return false;
      }
      R<BtmTypeVO> r = btmTypeClient.getDefaultAttrByBtmId(btmType);
      List<BtmTypeAttributeVO> attributes = r.getData().getAttributes();
      if (!r.isSuccess() || attributes.isEmpty()) {
         return false;
      }
      return attributes.stream().anyMatch(item -> item.getId().equals(selectKey));
   }
   /**
    * 封装最终的sql语句中的值部分
    *
    * @param selectKey 查询的字段
@@ -1869,20 +2658,28 @@
    * @param attrVOMap 属性的显示对象映射
    * @return sql里的值
    */
   private String getSqlByValue(String selectKey, String value, Map<String, CodeClassifyTemplateAttrVO> attrVOMap) {
   private String getSqlByValue(String selectKey, String value, Map<String, CodeClassifyTemplateAttrVO> attrVOMap, String btmType) {
      StringBuilder sql = new StringBuilder();
      //待完善
//      if (!selectKey.contains(".") && (attrVOMap.containsKey(selectKey.toLowerCase(Locale.ROOT)) || attributeService.isDefaultAttr(selectKey) || selectKey.matches(RegExpConstant.LETTER))) {
//         sql.append("t.");
//      }
      // TODO 已完善
      if (!selectKey.contains(".") && (attrVOMap.containsKey(selectKey.toLowerCase(Locale.ROOT)) || isDefaultAttr(selectKey, btmType) || selectKey.matches(RegExpConstant.LETTER))) {
         sql.append("t.");
      }
      if (value.startsWith(QueryOptionConstant.IN)) {
         sql.append(selectKey)
            .append(SPACE)
            .append("in")
            .append(SPACE)
            .append("(")
            .append(value.replace(QueryOptionConstant.IN, ""))
            .append(")");
         if (value.startsWith(QueryOptionConstant.IN + "('") && value.endsWith("')")) {
            sql.append(selectKey)
               .append(SPACE)
               .append("in")
               .append(SPACE)
               .append(value.replace(QueryOptionConstant.IN, ""));
         } else {
            sql.append(selectKey)
               .append(SPACE)
               .append("in")
               .append(SPACE)
               .append("(")
               .append(value.replace(QueryOptionConstant.IN, ""))
               .append(")");
         }
      } else if (value.startsWith(QueryOptionConstant.NOTIN)) {
         sql.append(selectKey)
            .append(SPACE)
@@ -1953,7 +2750,7 @@
            //  .append("'")
            .append(SPACE);
      } else {
         value= value.replace(SPECIAL_CHAR,REQUIRED_CHAR);
         value = value.replace(SPECIAL_CHAR, REQUIRED_CHAR);
         value = getStringValueInWhere(selectKey, value, attrVOMap);
         sql.append(selectKey)
@@ -1978,19 +2775,15 @@
//      CodeClassifyFullInfoBO classifyFullInfo = classifyService.getClassifyFullInfo(orderDTO.getCodeClassifyOid());
      CodeClassifyFullInfoBO classifyFullInfo = classifyService.getClassifyFullInfo(orderDTO.getCodeClassifyOid());
      //找业务类型,然后使用主键去获取数据库里的数据
//      List<ClientBusinessObject> cbos = boService.queryCBO(classifyFullInfo.getTopClassifyVO().getBtmtypeid(), WebUtil.getOidQuery(orderDTO.getOid()));
      List<BaseModel> cbos = selectByTypeAndOid(classifyFullInfo.getTopClassifyVO().getBtmTypeId(), orderDTO.getOid());
      QueryWrapper<CodeWupin> btmWrapper = new QueryWrapper<>();
      btmWrapper.eq("OID",orderDTO.getOid());
      CodeWupin cbo = codeWupinMapper.selectOne(btmWrapper);
//      CodeClstemplateVO templateVO = templateService.getObjectHasAttrByOid(orderDTO.getTemplateOid());
//      CodeRuleVO ruleVO = ruleService.getObjectHasSecByOid(orderDTO.getCodeRuleOid());
      if (cbo != null) {
      if (CollectionUtils.isEmpty(cbos)) {
         throw new VciBaseException(DATA_OID_NOT_EXIST);
      }
//      ClientBusinessObject cbo = cbos.get(0);
      BaseModel cbo = cbos.get(0);
      if (cbo == null) {
         throw new VciBaseException(DATA_OID_NOT_EXIST);
      }
      if (!cbo.getTs().toString().contains(VciDateUtil.date2Str(orderDTO.getTs(), VciDateUtil.DateTimeFormat))) {
         throw new VciBaseException("数据不是最新的,可能他人已经修改,请刷新后再试");
      }
@@ -2000,8 +2793,15 @@
      //注意模板不能使用数据存储的时候的模板,因为可能会变化
      //1. 判断必输项
      String codeClassifyOid = cbo.getData().get(CODE_CLASSIFY_OID_FIELD.toUpperCase());
      orderDTO.setCodeClassifyOid(codeClassifyOid);
//      CodeClassifyFullInfoBO classifyFullInfo = classifyService.getClassifyFullInfo(orderDTO.getCodeClassifyOid());
//      CodeClassifyTemplateVO templateVO= this.getUsedTemplateByClassifyOid(orderDTO.getCodeClassifyOid());
      CodeClassifyTemplateVO templateVO = templateService.getObjectHasAttrByOid(orderDTO.getTemplateOid());
      orderDTO.setTemplateOid(templateVO.getOid());
      //1. 判断必输项
      checkRequiredAttrOnOrder(templateVO, orderDTO);
      //2.先注入,再组合,最后校验
      switchClassifyLevelOnOrder(templateVO, classifyFullInfo, orderDTO);
@@ -2019,46 +2819,22 @@
      copyValueToCBO(classifyFullInfo, cbo, orderDTO, templateVO, true);
      //企业码和集团码的不修改
      cbo.setDescription(orderDTO.getDescription());
      cbo.setName(orderDTO.getName());
//        cbo.setName(orderDTO.getName());
      try {
         cbo.setDescription(orderDTO.getDescription());
         cbo.setDescription(StringUtils.isBlank(orderDTO.getDescription()) ? "" : orderDTO.getDescription());
         cbo.setName(orderDTO.getName());
////         cbo.setAttributeValueWithNoCheck("description", orderDTO.getDescription());
//         cbo.setAttributeValue("name", orderDTO.getName());
      } catch (Exception e) {
         e.printStackTrace();
      }
//      cbo.getData().putAll(orderDTO.getData());
      cbo.setLastModifyTime(new Date());
      cbo.setLastModifier(AuthUtil.getUser().getUserName());
      codeWupinMapper.updateById(cbo);
//
//      List<CodeWupinEntity> cboList = new ArrayList<>();
//
//      //备注
//      cbo.setDescription(orderDTO.getDescription());
//      cboList.add(cbo);
////
////      cboList.add(cbo);
//      List<String> codeList = productCodeService.productCodeAndSaveData(classifyFullInfo, templateVO, ruleVO, orderDTO.getSecDTOList(),cboList);
//
//
//      List<String> charList = new ArrayList<>();
//      for (CodeWupinEntity wupinEntity : cboList) {
//         charList.add(wupinEntity.getId());
//      }
//      batchSaveSelectChar(templateVO, charList);
//      return codeList.size() > 0 ? codeList.get(0) : "";
      cbo.setLastModifier(String.valueOf(AuthUtil.getUser().getAccount()));
      R r = updateBatchByBaseModel(classifyFullInfo.getTopClassifyVO().getBtmTypeId(), Collections.singletonList(cbo));
      //修改的时候,编码是不变的
//      BatchCBO batchCBO = new BatchCBO();
//      batchCBO.getUpdateCbos().add(cbo);
//      List<ClientBusinessObject> cboList = new ArrayList<>();
//      cboList.add(cbo);
//      boService.persistenceBatch(batchCBO);
      batchSaveSelectChar(templateVO, Arrays.asList(cbo.getId()));
      if (!r.isSuccess()) {
         throw new ServiceException(r.getMsg());
      }
      batchSaveSelectChar(templateVO, Collections.singletonList(cbo));
   }
   /**
@@ -2072,34 +2848,35 @@
         deleteBatchDTO.getCodeClassifyOid(), "主题库分类的主键");
      CodeClassifyFullInfoBO classifyFullInfo = classifyService.getClassifyFullInfo(deleteBatchDTO.getCodeClassifyOid());
      //找业务类型,然后使用主键去获取数据库里的数据
      Collection<String> oidCollection = null;
      Collection<String> oidCollection = new ArrayList<>();
      for (Collection<String> strings : VciBaseUtil.switchCollectionForOracleIn(deleteBatchDTO.getOidList())) {
         oidCollection.addAll(strings);
      }
      List<CodeWupin> cboList = codeWupinMapper.selectBatchIds(oidCollection);
      //      List<ClientBusinessObject> cboList = new ArrayList<>();
//      oidCollection.stream().forEach(oids -> {
//         Map<String, String> conditionMap = new HashMap<>();
//      List<CodeWupin> cboList = codeWupinMapper.selectBatchIds(oidCollection);
      List<BaseModel> cboList = new ArrayList<>();
      oidCollection.stream().forEach(oids -> {
         Map<String, String> conditionMap = new HashMap<>();
//         conditionMap.put("oid", QueryOptionConstant.IN + "(" + VciBaseUtil.toInSql(oids.toArray(new String[0])) + ")");
//         List<ClientBusinessObject> cbos = boService.queryCBO(classifyFullInfo.getTopClassifyVO().getBtmtypeid(), conditionMap);
//         cboList.addAll(cbos);
//      });
         List<BaseModel> cbos = selectByTypeAndOid(classifyFullInfo.getTopClassifyVO().getBtmTypeId(), oids);
//            boService.queryCBO(classifyFullInfo.getTopClassifyVO().getBtmtypeid(), conditionMap);
         cboList.addAll(cbos);
      });
      if (CollectionUtils.isEmpty(cboList)) {
         throw new VciBaseException("数据全部在系统中不存在");
      }
      List<CodeWupin> editCBOs = cboList.stream().filter(s -> !CodeDefaultLC.EDITING.getValue().equalsIgnoreCase(s.getLcStatus())).collect(Collectors.toList());
      List<BaseModel> editCBOs = cboList.stream().filter(s -> !CodeDefaultLC.EDITING.getValue().equalsIgnoreCase(s.getLcStatus())).collect(Collectors.toList());
      if (!CollectionUtils.isEmpty(editCBOs)) {
         CodeWupin cbo = editCBOs.get(0);
         BaseModel cbo = editCBOs.get(0);
         throw new VciBaseException("编码为{0}等共{1}条数据的状态不是[{2}],不允许删除", new String[]{cbo.getId(), String.valueOf(editCBOs.size()), CodeDefaultLC.EDITING.getText()});
      }
      //只能删除自己创建的数据
      String userId = AuthUtil.getUser().getUserName();
      for (CodeWupin clientBusinessObject:cboList){
      String userId = String.valueOf(AuthUtil.getUser().getAccount());
      for (BaseModel clientBusinessObject : cboList) {
         String creator = clientBusinessObject.getCreator();
         if(!userId.equalsIgnoreCase(creator)){
            throw new VciBaseException("编码为"+clientBusinessObject.getId()+"的数据不是当前用户创建,不能删除!");
         if (!userId.equalsIgnoreCase(creator)) {
            throw new VciBaseException("编码为" + clientBusinessObject.getId() + "的数据不是当前用户创建,不能删除!");
         }
      }
@@ -2107,8 +2884,15 @@
//      batchCBO.getDeleteCbos().addAll(cboList);
//      WebUtil.setPersistence(false);
//      batchCBO.copyFromOther(
      productCodeService.recycleCode(classifyFullInfo.getCurrentClassifyVO().getBtmtypeid(), deleteBatchDTO.getOidList());
      baseMapper.deleteBatchIds(cboList);
      productCodeService.recycleCode(classifyFullInfo.getTopClassifyVO().getBtmTypeId(), deleteBatchDTO.getOidList());
//      baseMapper.deleteBatchIds(cboList);
      //使用传入的业务类型查询表
      R<List<BtmTypeVO>> listR = btmTypeClient.selectByIdCollection(Collections.singletonList(classifyFullInfo.getTopClassifyVO().getBtmTypeId()));
      if (!listR.isSuccess() || listR.getData().size() == 0) {
         throw new VciBaseException("传入业务类型未查询到相应表单,请检查!");
      }
      commonsMapper.deleteByTaleAndOid(listR.getData().get(0).getTableName(),
         "'" + (StringUtils.join(cboList.stream().map(BaseModel::getOid).collect(Collectors.toSet()), "','")) + "'");
      //      );
//      WebUtil.setPersistence(true);
//      boService.persistenceBatch(batchCBO);
@@ -2127,7 +2911,6 @@
      //找阶段
      return phaseAttrService.listAttrByTemplateOidAndPhaseId(templateVO.getOid(), phase);
   }
   /**
    * 路径上包含当前分类的所有分类信息
@@ -2170,32 +2953,44 @@
      //4. 查询的时候,直接使用codeclsfpath来查询
      CodeClassifyVO topClassifyVO = classifyService.getTopClassifyVO(codeClassifyOid);
      CodeClassifyTemplateVO templateVO = templateService.getObjectHasAttrByOid(templateOid);
      if (topClassifyVO == null || StringUtils.isBlank(topClassifyVO.getBtmtypeid())) {
      if (topClassifyVO == null || StringUtils.isBlank(topClassifyVO.getBtmTypeId())) {
         throw new VciBaseException("当前主题库分类没有顶层分类,或者顶层分类没有设置业务类型");
      }
      String btmTypeId = topClassifyVO.getBtmtypeid();
      String btmTypeId = topClassifyVO.getBtmTypeId();
      if (StringUtils.isBlank(btmTypeId)) {
         return new DataGrid<>("这个分类所属顶层分类没有添加业务类型");
      }
      if (conditionMap == null) {
         conditionMap = new HashMap<>();
      }
      //pageHelper.addDefaultDesc("createTime");
      pageHelper.addDefaultDesc("id");
      pageHelper.addDefaultDesc("createTime");
//        pageHelper.addDefaultDesc("id");
      if (!classifyService.checkHasChild(codeClassifyOid)) {
         conditionMap.put("t."+CODE_CLASSIFY_OID_FIELD, codeClassifyOid);
         conditionMap.put("t." + CODE_CLASSIFY_OID_FIELD, codeClassifyOid);
      } else {
//         conditionMap.put(CODE_CLASSIFY_OID_FIELD, QueryOptionConstant.IN + "(select oid from " + VciBaseUtil.getTableName(MdmBtmTypeConstant.CODE_CLASSIFY)
         conditionMap.put("t."+CODE_CLASSIFY_OID_FIELD, QueryOptionConstant.IN + "(select oid from "+
            btmTypeClient.selectByIdCollection(Collections.singletonList(MdmBtmTypeConstant.CODE_CLASSIFY))
               .getData().get(0).getTableName() +" where lcstatus='" + FrameWorkDefaultValueConstant
         List<BtmTypeVO> classifyData = btmTypeClient.selectByIdCollection(Collections.singletonList(MdmBtmTypeConstant.CODE_CLASSIFY)).getData();
         if (Func.isEmpty(classifyData)) {
            throw new ServiceException("业务类型中英文名称和查询条件配置不一致,请修改业务类型中分类表英文名称为" + MdmBtmTypeConstant.CODE_CLASSIFY);
         }
         conditionMap.put("t." + CODE_CLASSIFY_OID_FIELD, QueryOptionConstant.IN + "(select oid from " +
            classifyData.get(0).getTableName() + " where lcstatus='" + FrameWorkDefaultValueConstant
            .FRAMEWORK_DATA_ENABLED + "' start with parentCodeClassifyOid = '" + codeClassifyOid +
            "' CONNECT BY PRIOR OID = parentCodeClassifyOid )");
      }
      conditionMap.put("t.lastr", "1");
      conditionMap.put("t.lastv", "1");
      return queryGrid(btmTypeId, templateVO, conditionMap, pageHelper);
      DataGrid<Map<String, String>> mapDataGrid = queryGrid(btmTypeId, templateVO, conditionMap, pageHelper);
      //处理返回数据与模板数据配置的字段不一样问题
      templateVO.getAttributes().stream().forEach(e -> {
         for (Map<String, String> datum : mapDataGrid.getData()) {
            if (datum.containsKey(e.getId().toLowerCase()) && !datum.containsKey(e.getId())) {
               datum.put(e.getId(), datum.get(e.getId().toLowerCase()));
               datum.remove(e.getId().toLowerCase());
            }
         }
      });
      return mapDataGrid;
//        List<String> selectFieldList = templateVO.getAttributes().stream().map(CodeClassifyTemplateAttrVO::getId).collect(Collectors.toList());
//        //参照让平台直接查询就行
//        List<String> finalSelectFieldList = selectFieldList;
@@ -2226,67 +3021,64 @@
    */
   @Override
   public R batchUpdateCode(List<CodeOrderDTO> orderDTOList) {
//      VciBaseUtil.alertNotNull(orderDTOList,"编码申请相关的属性内容");
//      orderDTOList.forEach(orderDTO -> {
//         VciBaseUtil.alertNotNull(orderDTO, "编码申请相关的属性的内容都为空", orderDTO.getOid(), "数据主键",
//            orderDTO.getCodeClassifyOid(), "主题库分类的主键");
//      });
//      Map<String, CodeOrderDTO> orderDTOMap = orderDTOList.stream().filter(orderDTO -> orderDTO != null && StringUtils.isNotBlank(orderDTO.getOid())).collect(Collectors.toList()).stream().collect(Collectors.toMap(s -> s.getOid(), t -> t));
//      List<ClientBusinessObject> updateList = new ArrayList<>();
//      // 应该都是一个分类下的业务数据,找第一条的就行
//      CodeClassifyFullInfoBO classifyFullInfo = classifyService.getClassifyFullInfo(orderDTOList.get(0).getCodeClassifyOid());
//      Map<String,String> cboOidMap = new HashMap<>();
//      if (CollectionUtils.isEmpty(orderDTOMap.keySet())){
//         throw new VciBaseException(DATA_OID_NOT_EXIST);
//      }
//      cboOidMap.put("oid",QueryOptionConstant.IN + "(" + VciBaseUtil.toInSql(orderDTOMap.keySet().toArray(new String[0])) + ")");
//      List<ClientBusinessObject> cboList = boService.queryCBO(classifyFullInfo.getTopClassifyVO().getBtmtypeid(), cboOidMap);
//      if (CollectionUtils.isEmpty(cboList)){
//         throw new VciBaseException(DATA_OID_NOT_EXIST);
//      }
//      BatchCBO batchCBO = new BatchCBO();
//      CodeClassifyTemplateVO firstTemplateVO = templateService.getObjectHasAttrByOid(orderDTOMap.values().stream().findFirst().get().getTemplateOid());
//      Map<String, ClientBusinessObject> cboMap = cboList.stream().filter(cbo -> cbo != null).collect(Collectors.toList()).stream().collect(Collectors.toMap(s -> s.getOid(), t -> t));
//      orderDTOMap.keySet().stream().forEach(oid -> {
//         CodeOrderDTO orderDTO = orderDTOMap.get(oid);
//         ClientBusinessObject cbo = cboMap.get(oid);
//         if (!cbo.getTs().contains(VciDateUtil.date2Str(orderDTO.getTs(), VciDateUtil.DateTimeFormat))) {
//            throw new VciBaseException("数据不是最新的,可能他人已经修改,请刷新后再试");
//         }
//         if (!CodeDefaultLC.EDITING.getValue().equalsIgnoreCase(cbo.getLcStatus()) && !orderDTO.isEditInProcess()) {
//            throw new VciBaseException("数据不是{0}的状态,不允许修改", new String[]{CodeDefaultLC.EDITING.getText()});
//         }
//         //1. 判断必输项
//         CodeClassifyTemplateVO templateVO = templateService.getObjectHasAttrByOid(orderDTO.getTemplateOid());
//         checkRequiredAttrOnOrder(templateVO, orderDTO);
//         //2.先注入,再组合,最后校验
//         switchClassifyLevelOnOrder(templateVO, classifyFullInfo, orderDTO);
//         //3.处理组合规则。组合规则不能使用编码的属性,因为编码的生成可能是需要属性的
//         switchComponentAttrOnOrder(templateVO, orderDTO);
//         //4.校验规则
//         checkVerifyOnOrder(templateVO, orderDTO);
//         //5.判断关键属性
//         checkKeyAttrOnOrder(classifyFullInfo, templateVO, orderDTO);
//         //6.校验枚举的内容是否正确
//         checkEnumOnOrder(templateVO, orderDTO);
//         //7.处理时间格式,在数据库里面不论是字符串还是日期格式,都使用相同的格式存储
//         switchDateAttrOnOrder(templateVO, orderDTO);
//         //默认的内容不能变,所以只需要拷贝自定义的相关属性即可
//         copyValueToCBO(classifyFullInfo, cbo, orderDTO, templateVO, true);
//         //企业码和集团码的不修改
//         cbo.setDescription(orderDTO.getDescription());
//         cbo.setName(orderDTO.getName());
//         try {
//            cbo.setAttributeValueWithNoCheck("description", orderDTO.getDescription());
//            cbo.setAttributeValue("name", orderDTO.getName());
//         } catch (VCIError e) {
//            e.printStackTrace();
//         }
//         batchCBO.getUpdateCbos().add(cbo);
//         updateList.add(cbo);
//      });
//      boService.persistenceBatch(batchCBO);
//      batchSaveSelectChar(firstTemplateVO, cboList);
      VciBaseUtil.alertNotNull(orderDTOList, "编码申请相关的属性内容");
      orderDTOList.forEach(orderDTO -> {
         VciBaseUtil.alertNotNull(orderDTO, "编码申请相关的属性的内容都为空", orderDTO.getOid(), "数据主键",
            orderDTO.getCodeClassifyOid(), "主题库分类的主键");
      });
      Map<String, CodeOrderDTO> orderDTOMap = orderDTOList.stream().filter(orderDTO -> orderDTO != null && StringUtils.isNotBlank(orderDTO.getOid())).collect(Collectors.toList()).stream().collect(Collectors.toMap(s -> s.getOid(), t -> t));
      List<BaseModel> updateList = new ArrayList<>();
      // 应该都是一个分类下的业务数据,找第一条的就行
      CodeClassifyFullInfoBO topClassifyFullInfo = classifyService.getClassifyFullInfo(orderDTOList.get(0).getCodeClassifyOid());
      if (CollectionUtils.isEmpty(orderDTOMap.keySet())) {
         throw new VciBaseException(DATA_OID_NOT_EXIST);
      }
      List<BaseModel> cboList = selectByTypeAndOid(topClassifyFullInfo.getTopClassifyVO().getBtmTypeId(), VciBaseUtil.array2String(orderDTOMap.keySet().toArray(new String[0])));
      if (CollectionUtils.isEmpty(cboList)) {
         throw new VciBaseException(DATA_OID_NOT_EXIST);
      }
      Map<String, BaseModel> cboMap = cboList.stream().filter(cbo -> cbo != null).collect(Collectors.toList()).stream().collect(Collectors.toMap(s -> s.getOid(), t -> t));
      orderDTOMap.keySet().stream().forEach(oid -> {
         CodeOrderDTO orderDTO = orderDTOMap.get(oid);
         CodeClassifyFullInfoBO classifyFullInfo = classifyService.getClassifyFullInfo(orderDTO.getCodeClassifyOid());
         CodeClassifyTemplateVO firstTemplateVO = templateService.getObjectHasAttrByOid(orderDTOMap.values().stream().findFirst().get().getTemplateOid());
         BaseModel cbo = cboMap.get(oid);
         String code = cbo.getId();
         if (!cbo.getTs().toString().contains(VciDateUtil.date2Str(orderDTO.getTs(), VciDateUtil.DateTimeFormat))) {
            throw new VciBaseException("数据不是最新的,可能他人已经修改,请刷新后再试");
         }
         if (!CodeDefaultLC.EDITING.getValue().equalsIgnoreCase(cbo.getLcStatus()) && !orderDTO.isEditInProcess()) {
            throw new VciBaseException("数据不是{0}的状态,不允许修改", new String[]{CodeDefaultLC.EDITING.getText()});
         }
         //1. 判断必输项
         CodeClassifyTemplateVO templateVO = templateService.getObjectHasAttrByOid(orderDTO.getTemplateOid());
         checkRequiredAttrOnOrder(templateVO, orderDTO);
         //2.先注入,再组合,最后校验
         switchClassifyLevelOnOrder(templateVO, classifyFullInfo, orderDTO);
         //3.处理组合规则。组合规则不能使用编码的属性,因为编码的生成可能是需要属性的
         switchComponentAttrOnOrder(templateVO, orderDTO);
         //4.校验规则
         checkVerifyOnOrder(templateVO, orderDTO);
         //5.判断关键属性
         checkKeyAttrOnOrder(classifyFullInfo, templateVO, orderDTO);
         //6.校验枚举的内容是否正确
         checkEnumOnOrder(templateVO, orderDTO);
         //7.处理时间格式,在数据库里面不论是字符串还是日期格式,都使用相同的格式存储
         switchDateAttrOnOrder(templateVO, orderDTO);
         //默认的内容不能变,所以只需要拷贝自定义的相关属性即可
         copyValueToCBO(classifyFullInfo, cbo, orderDTO, templateVO, true);
         //企业码和集团码的不修改
         cbo.setDescription(StringUtils.isBlank(orderDTO.getDescription()) ? "" : orderDTO.getDescription());
         cbo.setName(orderDTO.getName());
         cbo.setId(code);
         cbo.setDescription(StringUtils.isBlank(orderDTO.getDescription()) ? "" : orderDTO.getDescription());
         cbo.setName(orderDTO.getName());
         updateList.add(cbo);
         batchSaveSelectChar(firstTemplateVO, cboList);
      });
      updateBatchByBaseModel(topClassifyFullInfo.getTopClassifyVO().getBtmTypeId(), updateList);
      return R.success("操作成功!");
   }
@@ -2301,20 +3093,19 @@
   @Override
   public R markDataPassing(String oid, String btmName, Boolean pass) {
      VciBaseUtil.alertNotNull(oid, "业务数据主键", btmName, "业务类型", pass, "标记类型");
      boolean flag = false;
      boolean flag = true;
      try {
//         QueryWrapper<CodeWupinEntity> wrapper = new QueryWrapper<>();
//         wrapper.eq("oid",oid);
         CodeWupin data = baseMapper.selectById(oid);
         //         ClientBusinessObjectOperation operation = new ClientBusinessObjectOperation();
//         ClientBusinessObject data = operation.readBusinessObjectById(oid, btmName);
         if (data == null || StringUtils.isBlank(data.getOid())) {
         List<BaseModel> datas = selectByTypeAndOid(btmName, oid);
         if (datas.size() == 0) {
            return R.fail(DATA_OID_NOT_EXIST);
         }
         data.setPassing(String.valueOf(pass));
         flag = SqlHelper.retBool(baseMapper.updateById(data));
//         flag = operation.updateBuinessObject(data);
         datas.stream().forEach(data -> data.getData().put("PASSING", String.valueOf(pass)));
         R r = updateBatchByBaseModel(btmName, datas);
         if (!r.isSuccess()) {
            flag = false;
         }
      } catch (Exception e) {
         flag = false;
         e.printStackTrace();
      }
      if (flag) {
@@ -2369,64 +3160,83 @@
    */
   @Override
   public void upSaveCode(CodeOrderDTO orderDTO) {
      VciBaseUtil.alertNotNull(orderDTO, "编码数据所在业务类名称", orderDTO.getBtmname());
      String btmName = orderDTO.getBtmname();
      //找业务类型,然后使用主键去获取数据库里的数据
      List<BaseModel> cbos = selectByTypeAndOid(btmName, orderDTO.getCopyFromVersion());
      if (CollectionUtils.isEmpty(cbos)) {
         throw new VciBaseException(DATA_OID_NOT_EXIST);
      }
      BaseModel oldCbo = cbos.get(0);
      if (!CodeDefaultLC.RELEASED.getValue().equalsIgnoreCase(oldCbo.getLcStatus())) {
         throw new VciBaseException("数据不是{0}的状态,不允许数据更改", new String[]{CodeDefaultLC.RELEASED.getText()});
      }
      //根据数据获取分类oid
      String codeClassifyOid = oldCbo.getData().get(CODE_CLASSIFY_OID_FIELD.toUpperCase());
      orderDTO.setCodeClassifyOid(codeClassifyOid);
      CodeClassifyFullInfoBO classifyFullInfo = classifyService.getClassifyFullInfo(orderDTO.getCodeClassifyOid());
      CodeClassifyTemplateVO templateVO = this.getUsedTemplateByClassifyOid(orderDTO.getCodeClassifyOid());
      orderDTO.setTemplateOid(templateVO.getOid());
      VciBaseUtil.alertNotNull(orderDTO, "编码申请相关的属性的内容为空", orderDTO.getCopyFromVersion(), "原始数据的主键",
         orderDTO.getCodeClassifyOid(), "主题库分类的主键");
      CodeClassifyFullInfoBO classifyFullInfo = classifyService.getClassifyFullInfo(orderDTO.getCodeClassifyOid());
      //找业务类型,然后使用主键去获取数据库里的数据
//      List<ClientBusinessObject> cbos = boService.queryCBO(classifyFullInfo.getTopClassifyVO().getBtmtypeid(), WebUtil.getOidQuery(orderDTO.getCopyFromVersion()));
//      if (CollectionUtils.isEmpty(cbos)) {
//         throw new VciBaseException(DATA_OID_NOT_EXIST);
//      }
//      ClientBusinessObject oldCbo = cbos.get(0);
//      if (!CodeDefaultLC.RELEASED.getValue().equalsIgnoreCase(oldCbo.getLcStatus())) {
//         throw new VciBaseException("数据不是{0}的状态,不允许数据更改", new String[]{CodeDefaultLC.RELEASED.getText()});
//      }
//      //需要升版
//      ClientBusinessObjectOperation cboOperation = new ClientBusinessObjectOperation();
//      ClientBusinessObject cbo = null;
//      try {
//         //cbo = cboOperation.createBusinessObjectVersion(oldCbo,VciBaseUtil.getCurrentUserId());
//         cbo = cboOperation.reviseBusinessObject(oldCbo, "");
//      } catch (VCIError e) {
//         throw new VciBaseException("初始化相关的内容出现了错误", new String[0], e);
//      }
//      //1. 判断必输项
//      CodeClassifyTemplateVO templateVO = templateService.getObjectHasAttrByOid(orderDTO.getTemplateOid());
//      checkRequiredAttrOnOrder(templateVO, orderDTO);
//      //2.先注入,再组合,最后校验
//      switchClassifyLevelOnOrder(templateVO, classifyFullInfo, orderDTO);
//      //3.处理组合规则。组合规则不能使用编码的属性,因为编码的生成可能是需要属性的
//      switchComponentAttrOnOrder(templateVO, orderDTO);
//      //4.校验规则
//      checkVerifyOnOrder(templateVO, orderDTO);
//      //5.判断关键属性
//      checkKeyAttrOnOrder(classifyFullInfo, templateVO, orderDTO);
//      //6.校验枚举的内容是否正确
//      checkEnumOnOrder(templateVO, orderDTO);
//      //7.处理时间格式,在数据库里面不论是字符串还是日期格式,都使用相同的格式存储
//      switchDateAttrOnOrder(templateVO, orderDTO);
//      //默认的内容不能变,所以只需要拷贝自定义的相关属性即可
//      copyValueToCBO(classifyFullInfo, cbo, orderDTO, templateVO, true);
//      //企业码和集团码的不修改
//      cbo.setDescription(orderDTO.getDescription());
//      cbo.setName(orderDTO.getName());
//      try {
//         cbo.setAttributeValueWithNoCheck("description", orderDTO.getDescription());
//         cbo.setAttributeValue("name", orderDTO.getName());
//      } catch (VCIError e) {
//         e.printStackTrace();
//      }
//      //数据的时候,编码是不变的
//      cbo.setCreateTime(DateUtils.convert2String(new Date(Long.parseLong(cbo.getCreateTime())), "yyyy-MM-dd HH:mm:ss"));
//      cbo.setLastModifyTime(DateUtils.convert2String(new Date(Long.parseLong(cbo.getLastModifyTime())), "yyyy-MM-dd HH:mm:ss"));
//      List<ClientBusinessObject> cboList = new ArrayList<>();
//      cboList.add(cbo);
//      try {
//         cboOperation.saveRevisionBuinessObject(cbo);
//      } catch (VCIError vciError) {
//         throw new VciBaseException("数据更改保存出错了", new String[0], vciError);
//      }
//      batchSaveSelectChar(templateVO, cboList);
      //需要升版
      BaseModel cbo = null;
      cbo = reviseBusinessObject(oldCbo);
      //1. 判断必输项
      checkRequiredAttrOnOrder(templateVO, orderDTO);
      //2.先注入,再组合,最后校验
      switchClassifyLevelOnOrder(templateVO, classifyFullInfo, orderDTO);
      //3.处理组合规则。组合规则不能使用编码的属性,因为编码的生成可能是需要属性的
      switchComponentAttrOnOrder(templateVO, orderDTO);
      //4.校验规则
      checkVerifyOnOrder(templateVO, orderDTO);
      //5.判断关键属性
      checkKeyAttrOnOrder(classifyFullInfo, templateVO, orderDTO);
      //6.校验枚举的内容是否正确
      checkEnumOnOrder(templateVO, orderDTO);
      //7.处理时间格式,在数据库里面不论是字符串还是日期格式,都使用相同的格式存储
      switchDateAttrOnOrder(templateVO, orderDTO);
      //默认的内容不能变,所以只需要拷贝自定义的相关属性即可
      copyValueToCBO(classifyFullInfo, cbo, orderDTO, templateVO, true);
      //企业码和集团码的不修改
      cbo.setDescription(StringUtils.isBlank(orderDTO.getDescription()) ? "" : orderDTO.getDescription());
      cbo.setName(orderDTO.getName());
      cbo.setDescription(StringUtils.isBlank(orderDTO.getDescription()) ? "" : orderDTO.getDescription());
      cbo.setName(orderDTO.getName());
      //数据的时候,编码是不变的
      cbo.setCreateTime(cbo.getCreateTime());
      cbo.setCreator(cbo.getCreator());
      cbo.setLastModifyTime(cbo.getLastModifyTime());
      cbo.setTenantId(AuthUtil.getTenantId());
      oldCbo.setLastV("0");
      oldCbo.setLastModifier(String.valueOf(AuthUtil.getUser().getAccount()));
      oldCbo.setLastModifyTime(new Date());
      try {
         // 修改版次号
         updateBatchByBaseModel(oldCbo.getBtmname(), Collections.singletonList(oldCbo));
         // 插入新的数据
         insertBatchByType(cbo.getBtmname(), Collections.singletonList(cbo));
         //处理码值表,对码值表进行处理替换创建数据的oid
         QueryWrapper<CodeAllCode> wrapper = new QueryWrapper<>();
         wrapper.eq("CREATECODEOID", orderDTO.getCopyFromVersion());
         CodeAllCode codeAllCode = codeAllCodeService.getOne(wrapper);
         codeAllCode.setCreateCodeOid(cbo.getOid());
         codeAllCode.setLastModifyTime(new Date());
         codeAllCode.setTs(new Date());
         codeAllCode.setLastModifier(AuthUtil.getUser().getUserName());
         codeAllCodeService.updateById(codeAllCode);
         // 记录数据更改日志
         saveLogUtil.operateLog("数据更改", false, StringUtil.format("{}\n修改为:\n{}", JSON.toJSONString(Collections.singletonList(oldCbo)), JSON.toJSONString(Collections.singletonList(cbo))));
      } catch (Exception vciError) {
         // 记录数据更改报错时的日志
         saveLogUtil.operateLog("数据更改", true, vciError.toString());
         throw new VciBaseException("数据更改保存出错了", new String[0], vciError);
      }
      batchSaveSelectChar(templateVO, Collections.singletonList(cbo));
   }
   /**
@@ -2451,14 +3261,105 @@
   public CodeRuleVO getCodeRuleByClassifyOid(String codeClassifyOid) {
      VciBaseUtil.alertNotNull(codeClassifyOid, "分类的主键");
      CodeClassifyVO classifyVO = classifyService.getObjectByOid(codeClassifyOid);
      String codeRuleOid = classifyVO.getCoderuleoid();
      String codeRuleOid = classifyVO.getCodeRuleOid();
      if (StringUtils.isBlank(codeRuleOid)) {
         //往上找
         CodeClassifyFullInfoBO fullInfo = classifyService.getClassifyFullInfo(codeClassifyOid);
         return getCodeRuleByClassifyFullInfo(fullInfo);
         CodeRuleVO classifyFullInfoCodeRule = getCodeRuleByClassifyFullInfo(classifyService.getClassifyFullInfo(codeClassifyOid));
         return toCodeValueApplyStatus(classifyFullInfoCodeRule);
      }
      //我们查询编码规则
      return ruleService.getObjectHasSecByOid(codeRuleOid);
      //查询编码规则
      CodeRuleVO objectHasSecByOid = ruleService.getObjectHasSecByOid(codeRuleOid);
      return toCodeValueApplyStatus(objectHasSecByOid);
   }
   /**
    * 编码申请表单,隐藏、可输、只读转换
    *
    * @param codeRuleVO
    * @return
    */
   private CodeRuleVO toCodeValueApplyStatus(CodeRuleVO codeRuleVO) {
      if (codeRuleVO.getSecVOList().isEmpty()) {
         return codeRuleVO;
      }
      // 可输码段类型
      List<String> inputTypes = Arrays.asList(
         CodeSecTypeEnum.CODE_FIXED_SEC.getValue(),
         CodeSecTypeEnum.CODE_VARIABLE_SEC.getValue(),
         CodeSecTypeEnum.CODE_CLASSIFY_SEC.getValue(),
         CodeSecTypeEnum.CODE_REFER_SEC.getValue(),
         CodeSecTypeEnum.CODE_DATE_SEC.getValue()
      );
      // 只读码段类型
      List<String> readOnlyTypes = Arrays.asList(
         CodeSecTypeEnum.CODE_LEVEL_SEC.getValue(),
         CodeSecTypeEnum.CODE_ATTR_SEC.getValue()
      );
      // 隐藏码段类型
      /*List<String> hideType = Arrays.asList(
         CodeSecTypeEnum.CODE_SERIAL_SEC.getValue()
      );*/
      // 当前规则的所有类型码段
      List<String> secTypeList = codeRuleVO.getSecVOList().stream().map(CodeBasicSecVO::getSecType).collect(Collectors.toList());
      // 情况一 全部是只读的码段类型
      boolean hasAllReadOnlyType = secTypeList.stream().allMatch(item -> readOnlyTypes.stream().anyMatch(item1 -> item.equals(item1)));
      // 全部是只读的码段类型
      if (hasAllReadOnlyType) {
         List<CodeBasicSecVO> basicSecVOS = codeRuleVO.getSecVOList().stream().map(secVO -> {
            secVO.setCodeValueApplyStatus(3);
            // 日期码段设置默认值
            if (secVO.getSecType().equals(CodeSecTypeEnum.CODE_DATE_SEC.getValue())) {
               try {
                  secVO.setCodeDateValue(Func.format(new Date(), secVO.getCodeDateFormatStr()));
               } catch (Exception e) {
                  throw new ServiceException("日期码段日期格式配置有误,导致转换出错:" + e.getMessage());
               }
            }
            return secVO;
         }).collect(Collectors.toList());
         codeRuleVO.setSecVOList(basicSecVOS);
         return codeRuleVO;
      }
      // 情况二 全部都是可输入类型的
      boolean hasAllInputType = secTypeList.stream().allMatch(item -> inputTypes.stream().anyMatch(item1 -> item.equals(item1)));
      if (hasAllInputType) {
         List<CodeBasicSecVO> basicSecVOS = codeRuleVO.getSecVOList().stream().map(secVO -> {
            secVO.setCodeValueApplyStatus(1);
            // 日期码段设置默认值
            if (secVO.getSecType().equals(CodeSecTypeEnum.CODE_DATE_SEC.getValue())) {
               try {
                  secVO.setCodeDateValue(Func.format(new Date(), secVO.getCodeDateFormatStr()));
               } catch (Exception e) {
                  throw new ServiceException("日期码段日期格式配置有误,导致转换出错:" + e.getMessage());
               }
            }
            return secVO;
         }).collect(Collectors.toList());
         codeRuleVO.setSecVOList(basicSecVOS);
         return codeRuleVO;
      }
      // 情况三包含人为选择的码段,又有只读类型码段的,所有码段都要显示出来,可输设置为1,只读设置为2,隐藏设置为3
      List<CodeBasicSecVO> basicSecVOS = codeRuleVO.getSecVOList().stream().map(secVO -> {
         if (inputTypes.contains(secVO.getSecType())) {
            secVO.setCodeValueApplyStatus(1);
         } else if (readOnlyTypes.contains(secVO.getSecType())) {
            secVO.setCodeValueApplyStatus(2);
         } else {
            secVO.setCodeValueApplyStatus(3);
         }
         // 日期码段设置默认值
         if (secVO.getSecType().equals(CodeSecTypeEnum.CODE_DATE_SEC.getValue())) {
            try {
               secVO.setCodeDateValue(Func.format(new Date(), secVO.getCodeDateFormatStr()));
            } catch (Exception e) {
               throw new ServiceException("日期码段日期格式配置有误,导致转换出错:" + e.getMessage());
            }
         }
         return secVO;
      }).collect(Collectors.toList());
      codeRuleVO.setSecVOList(basicSecVOS);
      codeRuleVO.setIsShowHideStatus(hasAllReadOnlyType ? "readOnly" : (hasAllInputType ? "input" : "readAndInput"));
      return codeRuleVO;
   }
   /**
@@ -2471,24 +3372,24 @@
   public CodeRuleVO getCodeRuleByClassifyFullInfo(CodeClassifyFullInfoBO fullInfoBO) {
      //往上找
      String codeRuleOid = "";
      if (StringUtils.isNotBlank(fullInfoBO.getCurrentClassifyVO().getCoderuleoid())) {
         codeRuleOid = fullInfoBO.getCurrentClassifyVO().getCoderuleoid();
      if (StringUtils.isNotBlank(fullInfoBO.getCurrentClassifyVO().getCodeRuleOid())) {
         codeRuleOid = fullInfoBO.getCurrentClassifyVO().getCodeRuleOid();
      } else {
         if (CollectionUtils.isEmpty(fullInfoBO.getParentClassifyVOs())) {
            //说明已经是最高层级,
            throw new VciBaseException("当前主题库分类,以及它的所有的上级分类都没有设置编码规则");
            throw new ServiceException("当前主题库分类,以及它的所有的上级分类都没有设置编码规则");
         }
         List<CodeClassifyVO> parentClassifyVOList = fullInfoBO.getParentClassifyVOs().stream().sorted((o1, o2) -> o1.getDataLevel().compareTo(o2.getDataLevel())).collect(Collectors.toList());
         //从最高的level开始获取
         for (int i = 0; i < parentClassifyVOList.size(); i++) {
         for (int i = parentClassifyVOList.size() - 1; i >= 0; i--) {
            CodeClassifyVO record = parentClassifyVOList.get(i);
            if (StringUtils.isNotBlank(record.getCoderuleoid())) {
               codeRuleOid = record.getCoderuleoid();
            if (StringUtils.isNotBlank(record.getCodeRuleOid())) {
               codeRuleOid = record.getCodeRuleOid();
               break;
            }
         }
         if (StringUtils.isBlank(codeRuleOid)) {
            throw new VciBaseException("当前主题库分类,以及它的所有的上级分类都没有设置编码规则");
            throw new ServiceException("当前主题库分类,以及它的所有的上级分类都没有设置编码规则");
         }
      }
      return ruleService.getObjectHasSecByOid(codeRuleOid);
@@ -2506,18 +3407,18 @@
      CodeClassifyTemplateVO templateVO = templateService.getObjectHasAttrByOid(templateOid);
      //为了防止模板上的业务类型与分类上不对应
      CodeClassifyVO topClassifyVO = classifyService.getTopClassifyVO(templateVO.getCodeclassifyoid());
      String btmId = topClassifyVO.getBtmtypeid();
      String btmId = topClassifyVO.getBtmTypeId();
      //查询数据
      Map<String, String> conditionMap = new HashMap<>();
      conditionMap.put("t.oid",oid);
      conditionMap.put("t.oid", oid);
      CodeTemplateAttrSqlBO sqlBO = getSqlByTemplateVO(btmId, templateVO, conditionMap, new PageHelper(-1));
      //我们使用和业务类型的来查询
      List<Map> cbosB = commonsMapper.selectBySql(sqlBO.getSqlUnPage());
      List<Map<String,String>> cbos = new ArrayList<>();
      List<Map<String, String>> cbos = new ArrayList<>();
      cbosB.stream().forEach(map -> {
         Map<String, String> data = new HashMap<>();
         for (Object o : map.keySet()) {
            data.put(((String) o).toLowerCase(Locale.ROOT), String.valueOf(map.get(o)));
            data.put(((String) o).toLowerCase(Locale.ROOT), map.get(o) == null ? "" : String.valueOf(map.get(o)));
         }
         cbos.add(data);
      });
@@ -2527,48 +3428,59 @@
         throw new VciBaseException("数据在系统中不存在,是否因为修改过业务类型?");
      }
//      Map<String, String> data = new HashMap<>();
      Map<String,String> cbo = cbos.get(0);
      Map<String, String> cbo = cbos.get(0);
//      WebUtil.copyValueToMapFromCbos(cbo, data);
      List<Map<String, String>> dataList = new ArrayList<>();
      dataList.add(cbo);
      wrapperData(dataList, templateVO, sqlBO.getSelectFieldList(), true);
      R<List<Map<String, String>>> result = R.data(Collections.singletonList(cbo));
      //处理返回数据与模板数据配置的字段不一样问题
      templateVO.getAttributes().stream().forEach(e -> {
         for (Map<String, String> datum : result.getData()) {
            if (datum.containsKey(e.getId().toLowerCase()) && !datum.containsKey(e.getId())) {
               datum.put(e.getId(), datum.get(e.getId().toLowerCase()));
               datum.remove(e.getId().toLowerCase());
            }
         }
      });
      //我们要看是否不是升版的,升版的话,需要对比不相等的属性
      String copy = cbo.get("copyfromversion");
/*        String copy = cbo.get("copyfromversion");
//      if (StringUtils.isBlank(copy)) {
//         copy = cbo.getAttributeValue("copyfromversion");
//      }
      if (StringUtils.isNotBlank(copy)) {
         //说明有变更的内容
        if (StringUtils.isNotBlank(copy)) {
            //说明有变更的内容
         CodeTemplateAttrSqlBO oldSqlBO = getSqlByTemplateVO(btmId, templateVO, WebUtil.getOidQuery(copy), new PageHelper(-1));
         //我们使用和业务类型的来查询
            CodeTemplateAttrSqlBO oldSqlBO = getSqlByTemplateVO(btmId, templateVO, WebUtil.getOidQuery(copy), new PageHelper(-1));
            //我们使用和业务类型的来查询
//         List<Map> cbos = commonsMapper.selectBySql(sqlBO.getSqlUnPage());
         List<Map> oldCbos = commonsMapper.selectBySql(oldSqlBO.getSqlUnPage());
         if (!CollectionUtils.isEmpty(oldCbos)) {
            List<Map> oldCbos = commonsMapper.selectBySql(oldSqlBO.getSqlUnPage());
            if (!CollectionUtils.isEmpty(oldCbos)) {
//            Map<String, String> newData = new HashMap<>();
//            WebUtil.copyValueToMapFromCbos(cbo, newData);
            Map<String, String> oldData = new HashMap<>();
            oldData = oldCbos.get(0);
            Map<String, String> difFieldMap = new HashMap<>();
            Map<String, String> finalOldData = oldData;
            cbo.forEach((key, value) -> {
               String oldValue = finalOldData.getOrDefault(key, "");
               if (value == null) {
                  value = "";
               }
               if (oldValue == null) {
                  oldValue = "";
               }
               if (!value.equalsIgnoreCase(oldValue)) {
                  difFieldMap.put(key, oldValue);
               }
            });
            List<Map<String, String>> difFieldList = new ArrayList<>();
            difFieldList.add(difFieldMap);
            result.setData(difFieldList);
         }
      }
                Map<String, String> oldData = new HashMap<>();
                oldData = oldCbos.get(0);
                Map<String, String> difFieldMap = new HashMap<>();
                Map<String, String> finalOldData = oldData;
                cbo.forEach((key, value) -> {
               // 这儿oldmap中的全是大写,而cbo中的全是小写所以会拿不到只,这儿直接处理成小写拿不到就用大写拿
               String oldValue = String.valueOf(finalOldData.getOrDefault(key.toUpperCase(Locale.ROOT), finalOldData.getOrDefault(key, "")));
               if (value == null || value == "null") {
                        value = "";
                    }
                    if (oldValue == null || oldValue == "null") {
                        oldValue = "";
                    }
                    if (!value.equalsIgnoreCase(oldValue)) {
                        difFieldMap.put(key, oldValue);
                    }
                });
                List<Map<String, String>> difFieldList = new ArrayList<>();
                difFieldList.add(difFieldMap);
                result.setData(difFieldList);
            }
        }*/
      return result;
   }
@@ -2587,7 +3499,7 @@
         executionId = executionId.substring(0, executionId.lastIndexOf("."));
      }
      String sql = "select wm_concat(distinct (t.codetempattrOidArr)) codetempattroidarr\n" +
         "from pl_code_wupin t\n" +
         "from pl_code_clsflowtemp t\n" +
         "join PLFLOWINSTANCE plfi on t.ID = plfi.PLTEMPLATEPUID\n" +
         "where plfi.PLEXECUTIONID = '" + executionId + "' and t.CLASSIFYTEMPLATEOID = '" + templateOid + "' and t.CODEPROCESSUSE = '" + processUse + "'";
//      List<ClientBusinessObject> tempAttrOidArr = boService.queryByOnlySql(sql);
@@ -2595,8 +3507,9 @@
      if (CollectionUtils.isEmpty(tempAttrOidArr) || StringUtils.isBlank((CharSequence) tempAttrOidArr.get(0).get("codetempattroidarr"))) {
         return new ArrayList<>();
      }
      return VciBaseUtil.str2List(tempAttrOidArr.get(0).get("codetempattroidarr").toString());
      return VciBaseUtil.str2List(tempAttrOidArr.get(0).get("CODETEMPATTROIDARR").toString());
   }
   /**
    * 使用分类的主键获取业务数据
    *
@@ -2619,39 +3532,23 @@
         throw new VciBaseException("业务数据主键不能为空");
      }
      List<String> oidList = VciBaseUtil.str2List(conditionMap.get("oid"));
      Map<String, String> oidMap = new HashMap<>();
      QueryWrapper<CodeWupin> wrapper = new QueryWrapper();
      if (conditionMap.get("oid").contains(",")) {
//         oidMap.put("oid", QueryOptionConstant.IN +"("+ VciBaseUtil.toInSql(oidList.toArray(new String[0])) + ")");
         wrapper.in("oid",oidList);
      } else {
//         oidMap.put("oid", conditionMap.get("oid"));
         wrapper.in("oid",conditionMap.get("oid"));
      }
      if (CollectionUtils.isEmpty(oidMap)) {
         throw new VciBaseException("业务数据主键不能为空");
      }
//      List<ClientBusinessObject> cbos = boService.queryCBO(btmType, oidMap);
      List<CodeWupin> cbos = baseMapper.selectList(wrapper);
      List<BaseModel> cbos = selectByTypeAndOid(btmType, conditionMap.get("oid"));
      if (CollectionUtils.isEmpty(cbos)) {
         throw new VciBaseException("未找到业务数据");
      }
      CodeWupin cbo = cbos.get(0);
      String templateOid = cbo.getCodetemplateoid();
//      Map<String, String> templateOidMap = new HashMap<>();
//      templateOidMap.put("oid", templateOid);
      BaseModel cbo = cbos.get(0);
      String templateOid = cbo.getData().get("CODETEMPLATEOID");
      QueryWrapper<CodeClassifyTemplate> codeClassifyTemplateWrapper = new QueryWrapper<>();
      codeClassifyTemplateWrapper.eq("oid", templateOid);
      List<CodeClassifyTemplate> templateDOList = templateService.list(codeClassifyTemplateWrapper);
//      List<CodeClassifyTemplate> templateDOList = boService.queryObject(CodeClassifyTemplate.class, templateOidMap);
      QueryWrapper<CodeClassifyTemplateAttr> codeClassifyTemplateAttrWrapper = new QueryWrapper<>();
      codeClassifyTemplateAttrWrapper.eq("CLASSIFYTEMPLATEOID", templateOid);
//      templateOidMap.clear();
//      templateOidMap.put("CLASSIFYTEMPLATEOID",templateOid);
      List<CodeClassifyTemplateAttr> attrDOList = codeClassifyTemplateAttrService.list(codeClassifyTemplateAttrWrapper);
//         boService.queryObject(CodeClassifyTemplateAttr.class, templateOidMap);
      if (CollectionUtils.isEmpty(templateDOList)) {
         logger.error("找不到业务数据关联的模板,模板主键:" + templateOid);
         throw new VciBaseException("找不到业务数据关联的模板");
@@ -2659,18 +3556,18 @@
      CodeClassifyTemplateVO templateVO = templateService.codeClassifyTemplateDO2VO(templateDOList.get(0));
      templateVO.setAttributes(codeClassifyTemplateAttrService.codeClassifyTemplateAttrDO2VOs(attrDOList));
      try {
         if (oidList.size() > 1){
            DataGrid<Map<String,String>> allDataGrid = new DataGrid<>();
            List<Map<String,String>> allData = new ArrayList<>();
         if (oidList.size() > 1) {
            DataGrid<Map<String, String>> allDataGrid = new DataGrid<>();
            List<Map<String, String>> allData = new ArrayList<>();
            oidList.forEach(oid -> {
               Map<String,String> condition = new HashMap<>();
               condition.put("oid",oid);
               Map<String, String> condition = new HashMap<>();
               condition.put("oid", oid);
               DataGrid<Map<String, String>> dataGrid = queryGrid(btmType, templateVO, condition, pageHelper);
               allData.addAll(dataGrid.getData());
            });
            allDataGrid.setData(allData);
            return allDataGrid;
         }else {
         } else {
            return queryGrid(btmType, templateVO, conditionMap, pageHelper);
         }
      } catch (Exception e) {
@@ -2678,6 +3575,7 @@
         return null;
      }
   }
   /**
    * 使用分类的主键获取表格的定义
    *
@@ -2690,20 +3588,20 @@
      MdmUIInfoVO uiInfoVO = new MdmUIInfoVO();
      CodeClassifyTemplateVO templateVO = getUsedTemplateByClassifyOid(codeClassifyOid);
      uiInfoVO.setTemplateVO(templateVO);
      UITableDefineVO uiTableDefineVO = wrapperTableDefineByTemplate(templateVO,true);
      UITableDefineVO uiTableDefineVO = wrapperTableDefineByTemplate(templateVO, true);
      List<String> phaseAttrIdList = listPhaseAttrByClassifyOid(codeClassifyOid, phase);
      uiTableDefineVO.getCols().stream().forEach(list -> {
         List<UITableFieldVO> visiableTableField=new ArrayList<>();
         if(StringUtils.isNotBlank(phase)) {
         List<UITableFieldVO> visiableTableField = new ArrayList<>();
         if (StringUtils.isNotBlank(phase)) {
            visiableTableField = list.stream().filter(col ->
               phaseAttrIdList.stream().anyMatch(s -> StringUtils.equalsIgnoreCase(col.getField(), s) ||
                  (StringUtils.equalsIgnoreCase(col.getFieldType(), "combox") && StringUtils.equalsIgnoreCase(col.getSortField(), s))
                  || (StringUtils.equalsIgnoreCase(col.getFieldType(), "refer") && StringUtils.equalsIgnoreCase(col.getQueryField(), s))
               )).collect(Collectors.toList());
         }else{
            visiableTableField=  list.stream().filter(col ->
         } else {
            visiableTableField = list.stream().filter(col ->
               templateVO.getAttributes().stream().anyMatch(s ->
                  (!s.getReadOnlyFlag().equalsIgnoreCase("true")&& StringUtils.equalsIgnoreCase(col.getField(), s.getId())) ||
                  (!s.getReadOnlyFlag().equalsIgnoreCase("true") && StringUtils.equalsIgnoreCase(col.getField(), s.getId())) ||
                     (StringUtils.equalsIgnoreCase(col.getFieldType(), "combox") && StringUtils.equalsIgnoreCase(col.getSortField(), s.getId()))
                     || (StringUtils.equalsIgnoreCase(col.getFieldType(), "refer") && StringUtils.equalsIgnoreCase(col.getQueryField(), s.getId()))
               )).collect(Collectors.toList());
@@ -2715,9 +3613,55 @@
               setReferConfig2EditConfig(vo);
            } else if ("combox".equalsIgnoreCase(vo.getFieldType())) {
               setComboxConfig2EditConfig(vo);
            } else if (StringUtils.isNotBlank(vo.getDateFormate())){
            } else if (StringUtils.isNotBlank(vo.getDateFormate())) {
               vo.setEdit("date");
            }else {
            } else {
               vo.setEdit(vo.getFieldType());
            }
         });
      });
      uiInfoVO.setTableDefineVO(uiTableDefineVO);
      wrapperResemble(templateVO, uiInfoVO);
      return uiInfoVO;
   }
   /**
    * 使用分类的主键获取表格的定义-ubcs后修改获取流程阶段熟悉获取方法
    *
    * @param codeClassifyOid
    * @param templateId
    * @param taskId
    * @param modelKey
    * @return
    */
   public MdmUIInfoVO getTableDefineByClassifyOid_v2(String codeClassifyOid, String templateId, String taskId, String modelKey) {
      MdmUIInfoVO uiInfoVO = new MdmUIInfoVO();
      CodeClassifyTemplateVO templateVO = getUsedTemplateByClassifyOid(codeClassifyOid);
      uiInfoVO.setTemplateVO(templateVO);
      UITableDefineVO uiTableDefineVO = wrapperTableDefineByTemplate(templateVO, true);
      R<List<ProcessStageAttrVO>> r = imdmiFlowAttrClient.ssslist(templateId, modelKey, taskId);
      List<ProcessStageAttrVO> stageAttrVOS = r.getData();
      List<String> attrList = new ArrayList<>();
      stageAttrVOS.stream().forEach(attr -> {
         attrList.add(attr.getAttrId());
      });
      uiTableDefineVO.getCols().stream().forEach(list -> {
         List<UITableFieldVO> visiableTableField = new ArrayList<>();
         visiableTableField = list.stream().filter(col ->
            attrList.stream().anyMatch(s -> StringUtils.equalsIgnoreCase(col.getField(), s) ||
               (StringUtils.equalsIgnoreCase(col.getFieldType(), "combox") && StringUtils.equalsIgnoreCase(col.getSortField(), s))
               || (StringUtils.equalsIgnoreCase(col.getFieldType(), "refer") && StringUtils.equalsIgnoreCase(col.getQueryField(), s))
            )).collect(Collectors.toList());
         visiableTableField.stream().forEach(vo -> {
            uiTableDefineVO.setHasEditor(true);
            if ("refer".equalsIgnoreCase(vo.getFieldType())) {
               setReferConfig2EditConfig(vo);
            } else if ("combox".equalsIgnoreCase(vo.getFieldType())) {
               setComboxConfig2EditConfig(vo);
            } else if (StringUtils.isNotBlank(vo.getDateFormate())) {
               vo.setEdit("date");
            } else {
               vo.setEdit(vo.getFieldType());
            }
         });
@@ -2731,10 +3675,10 @@
    * 模板属性转换为表格定义的信息
    *
    * @param templateVO 模板的显示对象
    * @param forEdit 是否是编辑所需
    * @param forEdit    是否是编辑所需
    * @return 表格的信息
    */
   private UITableDefineVO wrapperTableDefineByTemplate(CodeClassifyTemplateVO templateVO,boolean forEdit) {
   private UITableDefineVO wrapperTableDefineByTemplate(CodeClassifyTemplateVO templateVO, boolean forEdit) {
      //封装信息
      UITableDefineVO tableDefineVO = new UITableDefineVO();
      tableDefineVO.setOid(templateVO.getOid());
@@ -2746,38 +3690,43 @@
      List<UITableFieldVO> fieldVOList = new ArrayList<>();
      Map<String, String> comboxOrReferFieldMap = new HashMap<>();
      templateVO.getAttributes().forEach(attrVO -> {
         UITableFieldVO tableFieldVO = templateAttr2TableField(attrVO,forEdit);
         if ("combox".equalsIgnoreCase(tableFieldVO.getFieldType())) {
            comboxOrReferFieldMap.put(tableFieldVO.getSortField(), tableFieldVO.getField());
         }
         if ("refer".equalsIgnoreCase(tableFieldVO.getFieldType())) {
            comboxOrReferFieldMap.put(tableFieldVO.getSortField(), tableFieldVO.getField());
         }
         if(StringUtils.isNotBlank(tableFieldVO.getEdit())){
            tableDefineVO.setHasEditor(true);
         }
         fieldVOList.add(tableFieldVO);
      });
      if (Func.isNotEmpty(templateVO.getAttributes())) {
         templateVO.getAttributes().forEach(attrVO -> {
            UITableFieldVO tableFieldVO = templateAttr2TableField(attrVO, forEdit);
            if ("combox".equalsIgnoreCase(tableFieldVO.getFieldType())) {
               comboxOrReferFieldMap.put(tableFieldVO.getSortField(), tableFieldVO.getField());
            }
            if ("refer".equalsIgnoreCase(tableFieldVO.getFieldType())) {
               comboxOrReferFieldMap.put(tableFieldVO.getSortField(), tableFieldVO.getField());
            }
            if (StringUtils.isNotBlank(tableFieldVO.getEdit())) {
               tableDefineVO.setHasEditor(true);
            }
            fieldVOList.add(tableFieldVO);
         });
      }
      List<List<UITableFieldVO>> cols = new ArrayList<>();
      cols.add(fieldVOList);
      tableDefineVO.setCols(cols);
      Map<String, UITableFieldVO> fieldVOMap = fieldVOList.stream().collect(Collectors.toMap(s -> s.getField().toLowerCase(Locale.ROOT), t -> t));
      //查询属性
      List<CodeClassifyTemplateAttrVO> queryAttrVOs = templateVO.getAttributes().stream().filter(s -> BooleanEnum.TRUE.getValue().equalsIgnoreCase(s.getQueryAttrFlag())).collect(Collectors.toList());
      if (!CollectionUtils.isEmpty(queryAttrVOs)) {
         List<UITableFieldVO> queryFieldVOs = new ArrayList<>();
         queryAttrVOs.stream().forEach(attrVO -> {
            String attrId = attrVO.getId().toLowerCase(Locale.ROOT);
            attrId = comboxOrReferFieldMap.getOrDefault(attrId, attrVO.getId()).toLowerCase(Locale.ROOT);
            if (fieldVOMap.containsKey(attrId)) {
               queryFieldVOs.add(fieldVOMap.get(attrId));
            }
         });
         tableDefineVO.setQueryColumns(queryFieldVOs);
      List<CodeClassifyTemplateAttrVO> seniorQueryAttrVOs = null;
      if (Func.isNotEmpty(templateVO.getAttributes())) {
         //查询属性
         List<CodeClassifyTemplateAttrVO> queryAttrVOs = templateVO.getAttributes().stream().filter(s -> BooleanEnum.TRUE.getValue().equalsIgnoreCase(s.getQueryAttrFlag())).collect(Collectors.toList());
         if (!CollectionUtils.isEmpty(queryAttrVOs)) {
            List<UITableFieldVO> queryFieldVOs = new ArrayList<>();
            queryAttrVOs.stream().forEach(attrVO -> {
               String attrId = attrVO.getId().toLowerCase(Locale.ROOT);
               attrId = comboxOrReferFieldMap.getOrDefault(attrId, attrVO.getId()).toLowerCase(Locale.ROOT);
               if (fieldVOMap.containsKey(attrId)) {
                  queryFieldVOs.add(fieldVOMap.get(attrId));
               }
            });
            tableDefineVO.setQueryColumns(queryFieldVOs);
         }
         //高级属性
         seniorQueryAttrVOs = templateVO.getAttributes().stream().filter(s -> BooleanEnum.TRUE.getValue().equalsIgnoreCase(s.getSeniorQueryAttrFlag())).collect(Collectors.toList());
      }
      //高级属性
      List<CodeClassifyTemplateAttrVO> seniorQueryAttrVOs = templateVO.getAttributes().stream().filter(s -> BooleanEnum.TRUE.getValue().equalsIgnoreCase(s.getSeniorQueryAttrFlag())).collect(Collectors.toList());
      if (!CollectionUtils.isEmpty(seniorQueryAttrVOs)) {
         List<UITableFieldVO> queryFieldVOs = new ArrayList<>();
         seniorQueryAttrVOs.stream().forEach(attrVO -> {
@@ -2794,29 +3743,30 @@
   /**
    * 加载成参照的修改配置
    *
    * @param vo 表格字段显示对象
    */
   private void setReferConfig2EditConfig(UITableFieldVO vo) {
      if (!CollectionUtils.isEmpty(vo.getReferConfig().getWhere())){
      if (!CollectionUtils.isEmpty(vo.getReferConfig().getWhere())) {
         vo.getReferConfig().getWhere().keySet().forEach(key -> {
            vo.getReferConfig().getWhere().put(key, "'" + vo.getReferConfig().getWhere().get(key) + "'");
         });
      }
      if (StringUtils.isNotBlank(vo.getReferConfig().getParentValue())){
      if (StringUtils.isNotBlank(vo.getReferConfig().getParentValue())) {
         String parentValue = vo.getReferConfig().getParentValue();
         parentValue ="\\" +  parentValue.replaceAll("'","{vci-quote}").replaceAll("=","{vci-equals}");
         parentValue = "\\" + parentValue.replaceAll("'", "{vci-quote}").replaceAll("=", "{vci-equals}");
         vo.getReferConfig().setParentValue(parentValue);
      }
      String referConfig = vo.getReferConfig().toString()
         .replaceAll("=",":")
         .replaceAll("UITableCustomDefineVO","")
         .replaceAll("UIFieldSortVO","")
         .replaceAll("UITablePageVO","")
         .replaceAll("UITableFieldVO","")
         .replaceAll("UIFormReferVO","")
         .replaceAll("\\{vci-equals}","=")
         .replaceAll("\\{vci-quote}","\\\\'")
         .replaceAll("'null'","null");
         .replaceAll("=", ":")
         .replaceAll("UITableCustomDefineVO", "")
         .replaceAll("UIFieldSortVO", "")
         .replaceAll("UITablePageVO", "")
         .replaceAll("UITableFieldVO", "")
         .replaceAll("UIFormReferVO", "")
         .replaceAll("\\{vci-equals}", "=")
         .replaceAll("\\{vci-quote}", "\\\\'")
         .replaceAll("'null'", "null");
      referConfig = referConfig + ",fieldMap:{" + vo.getQueryField() + ":'" + vo.getReferConfig().getValueField() + "'}";
      vo.setEditConfig("{referConfig:" + referConfig + "}");
      vo.setEdit(vo.getFieldType());
@@ -2824,20 +3774,21 @@
   /**
    * 加载成下拉框的修改配置
    *
    * @param vo 表格字段显示对象
    */
   private void setComboxConfig2EditConfig(UITableFieldVO vo) {
      vo.setEditConfig("{editable:true,comboxKey:'" + vo.getComboxKey() + "'");
      if (!CollectionUtils.isEmpty(vo.getData())){
         vo.setEditConfig(vo.getEditConfig()+", comboxConfig:");
      if (!CollectionUtils.isEmpty(vo.getData())) {
         vo.setEditConfig(vo.getEditConfig() + ", comboxConfig:");
         for (int i = 0; i < vo.getData().size(); i++) {
            KeyValue data = vo.getData().get(i);
            if (i == vo.getData().size() -1){
               vo.setEditConfig(vo.getEditConfig() + "{attributes:"+data.getAttributes()+",key:'"+data.getKey()+"',value:'"+data.getValue()+"'}]}");
            }else if (i == 0){
               vo.setEditConfig(vo.getEditConfig() + "{data:[{attributes:"+data.getAttributes()+",key:'"+data.getKey()+"',value:'"+data.getValue()+"'},");
            }else{
               vo.setEditConfig(vo.getEditConfig() + "{attributes:"+data.getAttributes()+",key:'"+data.getKey()+"',value:'"+data.getValue()+"'},");
            if (i == vo.getData().size() - 1) {
               vo.setEditConfig(vo.getEditConfig() + "{attributes:" + data.getAttributes() + ",key:'" + data.getKey() + "',value:'" + data.getValue() + "'}]}");
            } else if (i == 0) {
               vo.setEditConfig(vo.getEditConfig() + "{data:[{attributes:" + data.getAttributes() + ",key:'" + data.getKey() + "',value:'" + data.getValue() + "'},");
            } else {
               vo.setEditConfig(vo.getEditConfig() + "{attributes:" + data.getAttributes() + ",key:'" + data.getKey() + "',value:'" + data.getValue() + "'},");
            }
         }
         vo.setEditConfig(vo.getEditConfig() + ",valueField:'" + vo.getQueryField() + "'");
@@ -2855,7 +3806,7 @@
   @Override
   public MdmUIInfoVO getFormDefineByClassifyIdPath(String idPath) {
      CodeClassifyVO classifyVO = classifyService.getObjectByIdPath(idPath);
      if(classifyVO !=null){
      if (classifyVO != null) {
         return getFormDefineByClassifyOid(classifyVO.getOid());
      }
      return null;
@@ -2888,7 +3839,6 @@
      return getTableDefineByTemplateVO(templateService.getObjectHasAttrByOid(templateOid));
   }
   /**
    * 使用模板显示对象转换为表格的信息(包含扩展的按钮)
    *
@@ -2900,7 +3850,7 @@
      MdmUIInfoVO uiInfoVO = new MdmUIInfoVO();
      uiInfoVO.setTemplateVO(templateVO);
      //我们需要将模板转换为表格相关的显示信息
      uiInfoVO.setTableDefineVO(wrapperTableDefineByTemplate(uiInfoVO.getTemplateVO(),false));
      uiInfoVO.setTableDefineVO(wrapperTableDefineByTemplate(uiInfoVO.getTemplateVO(), false));
      //需要去看扩展的按钮,只有列表里面本身才添加进去,工具栏上的单独获取
      List<CodeClassifyTemplateButtonVO> buttonVOS = templateButtonService.listButtonByTemplateOid(templateVO.getOid(), true);
      if (!CollectionUtils.isEmpty(buttonVOS)) {
@@ -2939,8 +3889,8 @@
   @Override
   public MdmUIInfoVO getUIInfoByClassifyIdPath(String codeClassifyIdPath, String functionId) {
      CodeClassifyVO classifyVO = classifyService.getObjectByIdPath(codeClassifyIdPath);
      if(classifyVO !=null){
         return getUIInfoByClassifyOid(classifyVO.getOid(),functionId);
      if (classifyVO != null) {
         return getUIInfoByClassifyOid(classifyVO.getOid(), functionId);
      }
      return null;
   }
@@ -2958,15 +3908,13 @@
      MdmUIInfoVO uiInfoVO = getTableDefineByTemplateVO(getUsedTemplateByClassifyOid(codeClassifyOid));
      uiInfoVO.setLeaf(classifyService.countChildrenByClassifyOid(codeClassifyOid) == 0);
      if (StringUtils.isNotBlank(functionId) && !"~".equalsIgnoreCase(functionId)) {
         List<Menu> buttonVOS = iSysClient.getMenuButtonByType(uiInfoVO.getTemplateVO().getBtmTypeId()).getData();
         //功能按钮服务还未实现,等实现了,在进行调用
//         List<SmOperationVO> operationVOS = operationService.listButtonByFunctionId(functionId);
//         if (operationVOS == null) {
//            operationVOS = new ArrayList<>();
//         }
//         //查询扩展按钮
//         List<CodeButtonVO> buttonVOS = listButtonInToolbarByClassifyOid(codeClassifyOid);
         List<Menu> buttonVOS = iSysClient.getMenuButtonByType(codeClassifyOid, uiInfoVO.getTemplateVO().getBtmTypeId(), "data_auth").getData();
         //         List<SmOperationVO> operationVOS = operationService.listButtonByFunctionId(functionId);
         //         if (operationVOS == null) {
         //            operationVOS = new ArrayList<>();
         //         }
         //         //查询扩展按钮
         //         List<CodeButtonVO> buttonVOS = listButtonInToolbarByClassifyOid(codeClassifyOid);
         List<SmOperationVO> operationVOS = new ArrayList<>();
         if (!CollectionUtils.isEmpty(buttonVOS)) {
            for (int i = 0; i < buttonVOS.size(); i++) {
@@ -2983,6 +3931,34 @@
            }
         }
         uiInfoVO.setButtons(operationVOS);
      }
      return uiInfoVO;
   }
   @Override
   public MdmUIInfoVO getFlowUIInfoByClassifyOid(String codeClassifyOid, String functionId, String templateId, String taskId, String modelKey) {
//      MdmUIInfoVO uiInfoVO = getTableDefineByClassifyOid_v2(codeClassifyOid,templateId,taskId,modelKey);
      MdmUIInfoVO uiInfoVO = getTableDefineByTemplateVO(getUsedTemplateByClassifyOid(codeClassifyOid));
      R<List<ProcessStageAttrVO>> r = imdmiFlowAttrClient.ssslist(templateId, modelKey, taskId);
      List<ProcessStageAttrVO> stageAttrVOS = r.getData();
      Set<String> attrSet = new HashSet<>();
      stageAttrVOS.stream().forEach(attr -> {
         attrSet.add(attr.getAttrId());
      });
      try {
         UITableDefineVO tableDefineVO = uiInfoVO.getTableDefineVO();
         List<List<UITableFieldVO>> tableFieldVOs = tableDefineVO.getCols();
         List<UITableFieldVO> uiTableFieldVOS = tableFieldVOs.get(0);
         uiTableFieldVOS.stream().forEach(ui -> {
//            if(!attrSet.contains(ui.getField())){
//               ui.setEdit(null);
//               ui.setEditConfig(null);
//            }
         });
      } catch (Exception e) {
         throw new ServiceException("模板没有定义属性,读取表头失败!");
      }
      return uiInfoVO;
   }
@@ -3025,42 +4001,151 @@
   /**
    * 传入业务类型以及相关数据进行批量插入操作
    *
    * @param btmType 业务类型
    * @param baseModels      处理数据
    * @param btmType    业务类型
    * @param baseModels 处理数据
    * @return 处理成功数据条数
    */
   @Override
   public Integer insertBatchByType(String btmType, List<BaseModel> baseModels) {
      //使用传入的业务类型查询表
      R<List<BtmTypeVO>> listR = btmTypeClient.selectByIdCollection(Collections.singletonList(btmType));
      if(listR.getData().size() == 0){
      if (!listR.isSuccess() || listR.getData().size() == 0) {
         throw new VciBaseException("传入业务类型未查询到相应表单,请检查!");
      }
      //获取当前业务类型所有字段用来做对比
      R<BtmTypeVO> allAttributeByBtmId = btmTypeClient.getAllAttributeByBtmId(btmType);
      if (!allAttributeByBtmId.isSuccess() || allAttributeByBtmId.getData().getAttributes().size() == 0) {
         throw new VciBaseException("传入业务类型未查询到相应字段信息,请检查!");
      }
      Set<String> existFild = allAttributeByBtmId.getData().getAttributes().stream().map(btmTypeAttributeVO -> {
         return btmTypeAttributeVO.getId().toLowerCase();
      }).collect(Collectors.toSet());
      //将bean转为map,mybatis统一处理
      List<Map<String,String>> maps = new ArrayList<>();
      baseModels.stream().forEach(model-> {
      List<Map<String, String>> maps = new ArrayList<>();
      baseModels.stream().forEach(model -> {
         try {
            maps.add(VciBaseUtil.convertBean2Map(model));
            maps.add(VciBaseUtil.convertBean2Map(model, existFild));
         } catch (Exception e) {
            throw new VciBaseException("类型转换错误:" + e.toString());
         }
      });
      return commonsMapper.insertByBaseModel(listR.getData().get(0).getTableName(), maps.get(0), maps);
      // 是否开启多线程执行插入语句
      if (IS_THREAD_IMPORT) {
         try {
            threadBactchExecuteInsert(listR.getData().get(0).getTableName(), maps);
         } catch (Exception e) {
            throw new ServiceException("分批执行insert语句报错:" + e.getMessage());
         }
      } else {
         bacthExcecuteInsert(listR.getData().get(0).getTableName(), maps);
      }
      return maps.size();
   }
   /**
    * 多线程方式分批执行insert语句
    *
    * @param tableName
    * @param maps
    * @throws ServiceException
    */
   private void threadBactchExecuteInsert(String tableName, List<Map<String, String>> maps) throws ServiceException {
      ExecutorService executor = Executors.newFixedThreadPool(THREAD_NUM); // 创建一个固定大小的线程池
      List<Map<String, String>> threadSafeMaps = new CopyOnWriteArrayList<>(maps);
      for (int i = 0; i < threadSafeMaps.size(); i += MAX_IMPORT_NUM) {
         final int startIndex = i;
         final int endIndex = Math.min(i + MAX_IMPORT_NUM, threadSafeMaps.size());
         try {
            executor.execute(() -> {
               List<Map<String, String>> subList = threadSafeMaps.subList(startIndex, endIndex);
               // 调用插入数据库的方法
               commonsMapper.insertByBaseModel(tableName, threadSafeMaps.get(0), subList);
            });
         } catch (Throwable e) {
            throw new ServiceException(e.getMessage());
         }
      }
      // 关闭线程池
      executor.shutdown();
      try {
         // 等待所有任务执行完成
         executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
      } catch (InterruptedException e) {
         // 处理异常
         throw new ServiceException("多线程方式执行批量插入时产生错误:" + e.getMessage());
      }
   }
   /**
    * 单线程方式分批执行
    *
    * @param tableName
    * @param maps
    */
   private void bacthExcecuteInsert(String tableName, List<Map<String, String>> maps) {
      for (int i = 0; i < maps.size(); i += MAX_IMPORT_NUM) {
         final int startIndex = i;
         final int endIndex = Math.min(i + MAX_IMPORT_NUM, maps.size());
         List<Map<String, String>> subList = maps.subList(startIndex, endIndex);
         // 调用插入数据库的方法
         commonsMapper.insertByBaseModel(tableName, maps.get(0), subList);
      }
   }
   /**
    * 传入业务类型以及ID查询业务表数据是否重复
    *
    * @param btmType 业务类型
    * @param ids     处理数据
    * @return 查询到数据的总数
    */
   @Override
   public Integer selectIdsCounts(String btmType, List<String> ids) {
      //使用传入的业务类型查询表
      R<List<BtmTypeVO>> listR = btmTypeClient.selectByIdCollection(Collections.singletonList(btmType));
      if (!listR.isSuccess() || listR.getData().size() == 0) {
         throw new VciBaseException("传入业务类型未查询到相应表单,请检查!");
      }
      return commonsMapper.queryCountBySql("select count(*) from " +
         listR.getData().get(0).getTableName() + " where id in (" + ids.stream().map(s -> "'" + s + "'").collect(Collectors.joining(",")) + ")");
   }
   /**
    * 传入业务类型以及ID、OID查询业务表数据是否重复
    *
    * @param btmType 业务类型
    * @param id      处理数据id
    * @param oid     处理数据oid
    * @return 查询到数据的总数
    */
   @Override
   public Integer selectIdAndOidCounts(String btmType, String id, String oid) {
      //使用传入的业务类型查询表
      R<List<BtmTypeVO>> listR = btmTypeClient.selectByIdCollection(Collections.singletonList(btmType));
      if (!listR.isSuccess() || listR.getData().size() == 0) {
         throw new VciBaseException("传入业务类型未查询到相应表单,请检查!");
      }
      return commonsMapper.queryCountBySql("select count(*) from " +
         listR.getData().get(0).getTableName() + " where id ='" + id + "' and oid <> '" + oid + "'");
   }
   /**
    * 传入业务类型以及相oid集合查询数据进行返回
    *
    * @param btmType 业务类型
    * @param oids      需要查询的oid集合 逗号分开
    * @param oids    需要查询的oid集合 逗号分开
    * @return 查询出的数据
    */
   @Override
   public List<BaseModel> selectByTypeAndOid(String btmType, String oids)  {
   public List<BaseModel> selectByTypeAndOid(String btmType, String oids) {
      //使用传入的业务类型查询表
      R<List<BtmTypeVO>> listR = btmTypeClient.selectByIdCollection(Collections.singletonList(btmType));
      if(listR.getData().size() == 0){
      if (!listR.isSuccess() || listR.getData().size() == 0) {
         throw new VciBaseException("传入业务类型未查询到相应表单,请检查!");
      }
      //查询数据
@@ -3069,7 +4154,7 @@
      List<BaseModel> baseModels = new ArrayList<>();
      //将查询到的数据转换为basemodel,使用的反射方式来进行创建的
      try{
      try {
         for (Map map : maps) {
            Object obj = BaseModel.class.newInstance();
            BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
@@ -3078,46 +4163,53 @@
               Method setter = property.getWriteMethod();
               if (setter != null) {
                  //oracle的时间为TIMESTAMP的,需要进行转换成data,否则将报错
                  if(map.get(property.getName().toUpperCase()) instanceof TIMESTAMP){
                  if (map.get(property.getName().toUpperCase()) instanceof TIMESTAMP) {
                     LocalDateTime localDateTime = ((TIMESTAMP) map.get(property.getName().toUpperCase())).toLocalDateTime();
                     ZoneId zoneId = ZoneId.systemDefault();
                     ZonedDateTime zdt = localDateTime.atZone(zoneId);
                     Date date = Date.from(zdt.toInstant());
                     setter.invoke(obj,date);
                     setter.invoke(obj, date);
                     map.remove(property.getName().toUpperCase());
                  } //oracle的数字为BigDecimal的,需要进行转换成Integer,否则将报错
                  else if (map.get(property.getName().toUpperCase()) instanceof BigDecimal
                     && ("Integer").equals(setter.getParameterTypes()[0].getSimpleName())){
                     setter.invoke(obj, ((BigDecimal)map.get(property.getName().toUpperCase())).intValue());
                     && ("Integer").equals(setter.getParameterTypes()[0].getSimpleName())) {
                     setter.invoke(obj, ((BigDecimal) map.get(property.getName().toUpperCase())).intValue());
                     map.remove(property.getName().toUpperCase());
                  }else if(map.get(property.getName().toUpperCase()) != null){
                     setter.invoke(obj, map.get(property.getName().toUpperCase()));
                  } else if (map.containsKey(property.getName().toUpperCase())) {
                     if (setter.getParameterTypes()[0].getSimpleName().equals("String")) {
                        setter.invoke(obj, map.get(property.getName().toUpperCase()) == null ? null : String.valueOf(map.get(property.getName().toUpperCase())));
                     } else {
                        setter.invoke(obj, map.get(property.getName().toUpperCase()));
                     }
                     map.remove(property.getName().toUpperCase());
                  }
               }
            }
            for (Object key : map.keySet()) {
               map.put(key,String.valueOf(map.get(key)));
               map.put(key, map.get(key) == null ? null : String.valueOf(map.get(key)));
            }
            ((BaseModel) obj).setData(map);
            baseModels.add((BaseModel) obj);
         }
      }catch (Exception e){
      } catch (Exception e) {
         throw new VciBaseException("查询失败:" + e.getMessage());
      }
      return baseModels;
   }
   /**
    * 根据业务类型名称创建业务数据源对象
    *
    * @param boName 业务类型名称
    * @return 业务数据对象
    */
   public BaseModel createBaseModel(String boName)  {
   public BaseModel createBaseModel(String boName) {
      R<List<BtmTypeVO>> listR = btmTypeClient.selectByIdCollection(Collections.singletonList(boName));
      String userName = AuthUtil.getUser().getUserName();
      if (!listR.isSuccess() || listR.getData().size() == 0) {
         throw new VciBaseException("传入业务类型未查询到相应表单,请检查!");
      }
//        String userName = String.valueOf(AuthUtil.getUser().getUserId());
      BaseModel bo = new BaseModel();
//      bo.setOid(VciBaseUtil.getPk());
//      bo.setRevisionid(VciBaseUtil.getPk());
@@ -3127,16 +4219,16 @@
      bo.setFirstR("1");
      bo.setFirstV("1");
      bo.setLastV("1");
      bo.setCreator(userName);
      bo.setCreateTime(new Date());
      bo.setLastModifier(userName);
      bo.setLastModifyTime(new Date());
      bo.setRevisionRule(listR.getData().get(0).getRevisionRuleId());
      bo.setVersionRule(String.valueOf(listR.getData().get(0).getVersionRule()));
      if(StringUtils.isNotBlank(listR.getData().get(0).getRevisionRuleId())){
      bo.setVersionRule("".equals(listR.getData().get(0).getVersionRule()) ? "1" : listR.getData().get(0).getVersionRule());
      if (StringUtils.isNotBlank(listR.getData().get(0).getRevisionRuleId())) {
         R<List<RevisionRuleVO>> revisionRuleVO = revisionRuleClient
            .selectByIdCollection(Collections.singletonList(listR.getData().get(0).getRevisionRuleId()));
         bo.setRevisionValue(revisionRuleVO.getData().get(0).getStartCode());
            .selectByIdCollection(Collections.singletonList(listR.getData().get(0).getRevisionRuleId().toLowerCase()));
         if (revisionRuleVO.getData().size() != 0) {
            bo.setRevisionValue(revisionRuleVO.getData().get(0).getStartCode());
         } else {
            bo.setRevisionValue("1");
         }
      }
      bo.setRevisionSeq(1);
      bo.setVersionSeq(1);
@@ -3149,7 +4241,7 @@
      bo.setId("");
      bo.setName("");
      bo.setDescription("");
      bo.setOwner(userName);
      bo.setOwner(AuthUtil.getUser().getUserId().toString());
//      bo.setCheckinby(userName);
      bo.setCopyFromVersion("");
//      this.initTypeAttributeValue(bo,btmTypeVO);
@@ -3158,6 +4250,7 @@
   /**
    * 获取版次的值
    *
    * @param verRuleName 版次的规则
    * @return 版次的值,没有规则则为空
    */
@@ -3175,23 +4268,31 @@
   /**
    * 传入业务类型以及相关数据进行批量更新操作
    *
    * @param btmType 业务类型
    * @param baseModels      处理数据
    * @param btmType    业务类型
    * @param baseModels 处理数据
    * @return 处理状态
    */
   @Override
   public R updateBatchByBaseModel(String btmType, List<BaseModel> baseModels) {
      //使用传入的业务类型查询表
      R<List<BtmTypeVO>> listR = btmTypeClient.selectByIdCollection(Collections.singletonList(btmType));
      if(listR.getData().size() == 0){
      if (!listR.isSuccess() || listR.getData().size() == 0) {
         throw new VciBaseException("传入业务类型未查询到相应表单,请检查!");
      }
      //获取当前业务类型所有字段用来做对比
      R<BtmTypeVO> allAttributeByBtmId = btmTypeClient.getAllAttributeByBtmId(btmType);
      if (!allAttributeByBtmId.isSuccess() || allAttributeByBtmId.getData().getAttributes().size() == 0) {
         throw new VciBaseException("传入业务类型未查询到相应字段信息,请检查!");
      }
      Set<String> existFild = allAttributeByBtmId.getData().getAttributes().stream().map(btmTypeAttributeVO -> {
         return btmTypeAttributeVO.getId();
      }).collect(Collectors.toSet());
      //将bean转为map,mybatis统一处理
      List<Map<String,String>> maps = new ArrayList<>();
      List<Map<String, String>> maps = new ArrayList<>();
      baseModels.stream().forEach(model-> {
      baseModels.stream().forEach(model -> {
         try {
            maps.add(VciBaseUtil.convertBean2Map(model));
            maps.add(VciBaseUtil.convertBean2Map(model, existFild));
         } catch (Exception e) {
            throw new VciBaseException("类型转换错误:" + e.getMessage());
         }
@@ -3199,10 +4300,420 @@
      try {
         //注意此处更新成功是返回的-1
         commonsMapper.updateBatchByBaseModel(listR.getData().get(0).getTableName(), maps);
      }catch (Exception e){
         return R.fail("更新失败!"+e.getMessage());
      } catch (Exception e) {
         return R.fail("更新失败!" + e.getMessage());
      }
      return R.success("更新成功!");
   }
   /**
    * 更新业务数据同时对码值表数据操作接口
    *
    * @param btmType    业务类型
    * @param baseModels 处理数据
    * @return 处理状态
    */
   @Transactional(rollbackFor = VciBaseException.class)
   @Override
   public R<Integer> updateBatchBtypeDatas(String btmType, List<BaseModel> baseModels) {
      //使用传入的业务类型查询表
      R<List<BtmTypeVO>> listR = btmTypeClient.selectByIdCollection(Collections.singletonList(btmType));
      if (!listR.isSuccess() || listR.getData().size() == 0) {
         throw new VciBaseException("传入业务类型未查询到相应表单,请检查!");
      }
      //获取当前业务类型所有字段用来做对比
      R<BtmTypeVO> allAttributeByBtmId = btmTypeClient.getAllAttributeByBtmId(btmType);
      if (!allAttributeByBtmId.isSuccess() || allAttributeByBtmId.getData().getAttributes().size() == 0) {
         throw new VciBaseException("传入业务类型未查询到相应字段信息,请检查!");
      }
      Set<String> existFild = allAttributeByBtmId.getData().getAttributes().stream().map(btmTypeAttributeVO -> {
         return btmTypeAttributeVO.getId();
      }).collect(Collectors.toSet());
      if (!CollectionUtils.isEmpty(baseModels)) {
         List<String> oidList = baseModels.stream().filter(data -> com.baomidou.mybatisplus.core.toolkit.StringUtils.isNotBlank(data.getOid())).map(BaseModel::getOid).distinct().collect(Collectors.toList());
         LambdaQueryWrapper<CodeAllCode> lqw = new LambdaQueryWrapper<>();
         lqw.in(CodeAllCode::getCreateCodeOid, oidList);
         List<CodeAllCode> codeAllCodeList = codeAllCodeService.selectByWrapper(lqw);
         Map<String, CodeAllCode> cboMap = codeAllCodeList.stream().filter(cbo -> cbo != null).collect(Collectors.toList()).stream().collect(Collectors.toMap(s -> s.getCreateCodeOid(), t -> t));
         List<CodeAllCode> newCodeAllCodeList = new ArrayList<>();
         //将bean转为map,mybatis统一处理
         List<Map<String, String>> maps = new ArrayList<>();
         try {
            baseModels.stream().forEach(baseModel -> {
               String oid = baseModel.getOid();
               try {
                  maps.add(VciBaseUtil.convertBean2Map(baseModel, existFild));
               } catch (Exception e) {
                  throw new VciBaseException("类型转换错误:" + e.getMessage());
               }
               if (cboMap.containsKey(oid)) {
                  CodeAllCode codeAllCode = cboMap.get(oid);
                  codeAllCode.setId(baseModel.getId());
                  // codeAllCode.setLastModifier(AuthUtil.getUser().getUserName());
                  codeAllCode.setLastModifier(AuthUtil.getUser().getAccount());
                  codeAllCode.setLastModifyTime(new Date());
                  codeAllCode.setLcStatus(baseModel.getLcStatus());
                  newCodeAllCodeList.add(codeAllCode);
               }
            });
            commonsMapper.updateBatchByBaseModel(listR.getData().get(0).getTableName(), maps);
            codeAllCodeService.saveOrUpdateBatch(newCodeAllCodeList);
         } catch (Exception e) {
            throw new VciBaseException("类型转换错误:" + e.getMessage());
         }
      }
      return R.success("更新成功!");
   }
   /**
    * 获取参照的信息
    *
    * @param referConfigVO 参照的配置
    * @return 列表数据
    */
   @Override
   public IPage<BaseModelVO> referDataGrid(UIFormReferVO referConfigVO, BaseQueryObject baseQueryObject) throws VciBaseException {
      //checkReferConfig(referConfigVO);
      //使用业务类型查询
      R<BtmTypeVO> allAttributeByBtmId = btmTypeClient.getAllAttributeByBtmId(referConfigVO.getReferType());
      if (!allAttributeByBtmId.isSuccess()) {
         throw new ServiceException("业务类型feign接口调用错误;" + allAttributeByBtmId.getMsg());
      }
      if (Func.isEmpty(allAttributeByBtmId.getData())) {
         throw new VciBaseException("传入业务类型未查询到相应表单,请检查!");
      }
      BtmTypeVO btmTypeVO = allAttributeByBtmId.getData();
      /**
       * 加上查询最新版次
       */
      baseQueryObject.getConditionMap().put("lastr", "1");
      baseQueryObject.getConditionMap().put("lastv", "1");
      if (VciBaseUtil.containsKeyUnCaseForMap(baseQueryObject.getConditionMap(), VciQueryWrapperForDO.LC_STATUS_FIELD) &&
         BtmTypeLcStatusConstant.FRAME_WORK_LIFE_CYCLE_NAME.equalsIgnoreCase(btmTypeVO.getLifeCycleId())) {
         baseQueryObject.getConditionMap().put(VciQueryWrapperForDO.LC_STATUS_FIELD, FrameworkDataLCStatus.ENABLED.getValue());
      }
      if (VciBaseUtil.containsKeyUnCaseForMap(baseQueryObject.getConditionMap(), VciQueryWrapperForDO.LC_STATUS_FIELD) &&
         BtmTypeLcStatusConstant.RELEASE_LIFE_CYCLE.equalsIgnoreCase(btmTypeVO.getLifeCycleId())) {
         baseQueryObject.getConditionMap().put(VciQueryWrapperForDO.LC_STATUS_FIELD, CodeDefaultLC.RELEASED.getValue());
      }
      R<List<BtmTypeVO>> listR = btmTypeClient.selectByIdCollection(Collections.singletonList(referConfigVO.getReferType()));
      if (!listR.isSuccess()) {
         throw new ServiceException(Func.isNotBlank(listR.getMsg()) ? listR.getMsg() : "业务类型feign接口调用错误!");
      }
      if (listR.getData().isEmpty()) {
         throw new VciBaseException("传入业务类型未查询到相应表单,请检查!");
      }
      // TODO:参照配置的模糊查询过滤条件暂未处理
      /*        String namesql = "";
            if (StringUtils.isNotBlank(baseQueryObject.getConditionMap().get("name"))) {
               String s = baseQueryObject.getConditionMap().get("name");
               s = "%" + s + "%";
               namesql = "and name like" + VciBaseUtil.toInSql(s);
            }
            String codesql = "";
            if (StringUtils.isNotBlank(baseQueryObject.getConditionMap().get("id"))) {
               String s = baseQueryObject.getConditionMap().get("id");
               s = "%" + s + "%";
               codesql = "and id like" + VciBaseUtil.toInSql(s);
            }
            String lcstatusSql = "";
            if (StringUtils.isNotBlank(baseQueryObject.getConditionMap().get("lcstatus"))) {
               lcstatusSql = "and lcstatus =" + VciBaseUtil.toInSql(baseQueryObject.getConditionMap().get("lcstatus"));
            }*/
      //        String where = "";
      //        if (StringUtils.isNotBlank(codesql) || StringUtils.isNotBlank(lcstatusSql) || StringUtils.isNotBlank(namesql)) {
      //            where = "where ";
      //        }
      String whereSqlByMap = UBCSCondition.getWhereSqlByMap(baseQueryObject.getConditionMap());
      String num1 = baseQueryObject.getPage() * baseQueryObject.getLimit() + "";
      String num2 = ((baseQueryObject.getPage()) - 1) * baseQueryObject.getLimit() + 1 + "";
      List<Map> maps = commonsMapper.selectBySql("select * from (select rownum rn, t.* from (select * from " + listR.getData().get(0).getTableName() + SPACE
         + (StringUtils.isNotBlank(listR.getData().get(0).getRevisionRuleId()) ? (" where lastr = " + VciBaseUtil.toInSql(baseQueryObject.getConditionMap().get("lastr").toString())
         + " and lastv =" + VciBaseUtil.toInSql(baseQueryObject.getConditionMap().get("lastv").toString())) + " and" : "where") + SPACE + "1=1 "
         + (Func.isNotBlank(whereSqlByMap) ? "and " + whereSqlByMap : "") + ") t " + (baseQueryObject.getLimit() == -1 ? ")" : ("where rownum <=" + num1 + ") where rn >=" + num2)
      ));
      List<BaseModel> baseModels = new ArrayList<>();
      //将查询到的数据转换为basemodel,使用的反射方式来进行创建的
      try {
         for (Map map : maps) {
            Object obj = BaseModel.class.newInstance();
            BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            for (PropertyDescriptor property : propertyDescriptors) {
               Method setter = property.getWriteMethod();
               if (setter != null) {
                  //oracle的时间为TIMESTAMP的,需要进行转换成data,否则将报错
                  if (map.get(property.getName().toUpperCase()) instanceof TIMESTAMP) {
                     LocalDateTime localDateTime = ((TIMESTAMP) map.get(property.getName().toUpperCase())).toLocalDateTime();
                     ZoneId zoneId = ZoneId.systemDefault();
                     ZonedDateTime zdt = localDateTime.atZone(zoneId);
                     Date date = Date.from(zdt.toInstant());
                     setter.invoke(obj, date);
                     //map.remove(property.getName().toUpperCase());
                  } //oracle的数字为BigDecimal的,需要进行转换成Integer,否则将报错
                  else if (map.get(property.getName().toUpperCase()) instanceof BigDecimal
                     && ("Integer").equals(setter.getParameterTypes()[0].getSimpleName())) {
                     setter.invoke(obj, ((BigDecimal) map.get(property.getName().toUpperCase())).intValue());
                     //map.remove(property.getName().toUpperCase());
                  } else if (map.get(property.getName().toUpperCase()) != null) {
                     if (setter.getParameterTypes()[0].getSimpleName().equals("String")) {
                        setter.invoke(obj, map.get(property.getName().toUpperCase()) == null ? null : String.valueOf(map.get(property.getName().toUpperCase())));
                     } else {
                        setter.invoke(obj, map.get(property.getName().toUpperCase()));
                     }
                     //map.remove(property.getName().toUpperCase());
                  }
               }
            }
            for (Object key : map.keySet()) {
               map.put(key, String.valueOf(map.get(key)));
            }
            Map<String, String> newMap = new HashMap<>();
            map.forEach((key, value) -> newMap.put(String.valueOf(key).toLowerCase(), String.valueOf(value)));
            ((BaseModel) obj).setData(newMap);
            baseModels.add((BaseModel) obj);
         }
      } catch (Exception e) {
         throw new VciBaseException("查询失败:" + e.getMessage());
      }
      int total = commonsMapper.queryCountBySql("select count(*) from " + listR.getData().get(0).getTableName() + SPACE
         + (StringUtils.isNotBlank(listR.getData().get(0).getRevisionRuleId()) ? (" where lastr = " + VciBaseUtil.toInSql(baseQueryObject.getConditionMap().get("lastr").toString())
         + "and lastv = " + VciBaseUtil.toInSql(baseQueryObject.getConditionMap().get("lastv").toString())) + " and" : "where") + SPACE + "1=1 "
         + (Func.isNotBlank(whereSqlByMap) ? "and " + whereSqlByMap : "")
      );
      IPage<BaseModelVO> objectDataGrid = new Page<>();
      objectDataGrid.setPages(baseQueryObject.getPage());
      objectDataGrid.setCurrent(baseQueryObject.getPage());
      objectDataGrid.setRecords(BaseMdodelWrapper.build().listVO(baseModels));
      objectDataGrid.setSize(baseQueryObject.getLimit());
      objectDataGrid.setTotal(total);
      return objectDataGrid;
   }
   /**
    * 获取树形的参照
    *
    * @param referConfigVO 参照的配置
    * @return 树形的数据
    */
   @Override
   public List<Tree> referTree(UIFormReferVO referConfigVO, TreeQueryObject queryObject) {
      if (queryObject.getConditionMap() == null) {
         queryObject.setConditionMap(new HashMap<>());
      }
      if (queryObject.getParentOid() == null) {
         LambdaQueryWrapper<CodeClassify> lqw = new LambdaQueryWrapper<>();
         String parentValue = referConfigVO.getParentValue().substring(3);
         lqw.inSql(CodeClassify::getOid, parentValue);
         List<String> codeClassifies = classifyService.select1(lqw);
         String oid = codeClassifies.get(0);
         queryObject.setParentOid(oid);
      }
      String oidFieldName = StringUtils.isNotBlank(referConfigVO.getParentUsedField()) ? referConfigVO.getParentUsedField() : referConfigVO.getValueField();
      if (queryObject.isQueryAllLevel()) {
         String parentOidSql = "";
         if (StringUtils.isNotBlank(referConfigVO.getParentValue())) {
            String temp = referConfigVO.getParentValue();
            if (temp.startsWith(QueryOptionConstant.IN)) {
               temp = temp.substring((QueryOptionConstant.IN).length()).trim();
               parentOidSql = " in " + ((temp.startsWith("(") && temp.endsWith(")")) ? temp : "(" + temp + ")");
            } else if (temp.startsWith(QueryOptionConstant.NOTIN)) {
               parentOidSql = " not in " + ((temp.startsWith("(") && temp.endsWith(")")) ? temp : "(" + temp + ")");
            } else if (temp.startsWith(QueryOptionConstant.NOTEQUAL)) {
               temp = temp.substring((QueryOptionConstant.NOTEQUAL).length()).trim();
               parentOidSql = QueryOptionConstant.NOTEQUAL + " " + ((temp.startsWith("'") && temp.endsWith("'")) ? temp : "'" + temp + "'");
            } else if (temp.startsWith(QueryOptionConstant.MORETHAN)) {
               temp = temp.substring((QueryOptionConstant.MORETHAN).length()).trim();
               parentOidSql = QueryOptionConstant.MORETHAN + " " + ((temp.startsWith("'") && temp.endsWith("'")) ? temp : "'" + temp + "'");
            } else if (temp.startsWith(QueryOptionConstant.MORE)) {
               temp = temp.substring((QueryOptionConstant.MORE).length()).trim();
               parentOidSql = QueryOptionConstant.MORE + " " + ((temp.startsWith("'") && temp.endsWith("'")) ? temp : "'" + temp + "'");
            } else if (temp.startsWith(QueryOptionConstant.LESSTHAN)) {
               temp = temp.substring((QueryOptionConstant.LESSTHAN).length()).trim();
               parentOidSql = QueryOptionConstant.LESSTHAN + " " + ((temp.startsWith("'") && temp.endsWith("'")) ? temp : "'" + temp + "'");
            } else if (temp.startsWith(QueryOptionConstant.LESS)) {
               temp = temp.substring((QueryOptionConstant.LESS).length()).trim();
               parentOidSql = QueryOptionConstant.LESS + " " + ((temp.startsWith("'") && temp.endsWith("'")) ? temp : "'" + temp + "'");
            } else if (temp.startsWith(QueryOptionConstant.ISNOTNULL)) {
               parentOidSql = " is not null";
            } else if (temp.startsWith(QueryOptionConstant.ISNULL)) {
               parentOidSql = " is  null";
            } else if (temp.contains("*")) {
               parentOidSql = " like " + ((temp.startsWith("'") && temp.endsWith("'")) ? temp : "'" + temp + "'").replace("*", "%");
            } else {
               parentOidSql = " = " + ((temp.startsWith("'") && temp.endsWith("'")) ? temp : "'" + temp + "'");
            }
         }
         //查询全部的信息
         queryObject.getConditionMap().put("oid", QueryOptionConstant.IN + "(select oid from " +
            getTableName(referConfigVO.getReferType()) +
            " START WITH " + referConfigVO.getParentFieldName() + " " +
            parentOidSql +
            " CONNECT BY PRIOR " + oidFieldName + " = " + referConfigVO.getParentFieldName() + ")");
      } else {
         if (StringUtils.isNotBlank(referConfigVO.getParentFieldName()) && StringUtils.isNotBlank(queryObject.getParentOid())) {
            queryObject.getConditionMap().put(referConfigVO.getParentFieldName(), queryObject.getParentOid());
            //查询全部的信息
            String parentOidSql = "";
            if (StringUtils.isNotBlank(referConfigVO.getParentValue())) {
               String temp = referConfigVO.getParentValue();
               if (temp.startsWith(QueryOptionConstant.IN)) {
                  temp = temp.substring((QueryOptionConstant.IN).length()).trim();
                  parentOidSql = " in " + "('" + queryObject.getParentOid() + "')";
               } else if (temp.startsWith(QueryOptionConstant.NOTIN)) {
                  parentOidSql = " not in " + "('" + queryObject.getParentOid() + "')";
               } else if (temp.startsWith(QueryOptionConstant.NOTEQUAL)) {
                  temp = temp.substring((QueryOptionConstant.NOTEQUAL).length()).trim();
                  parentOidSql = QueryOptionConstant.NOTEQUAL + " " + ((temp.startsWith("'") && temp.endsWith("'")) ? temp : "'" + temp + "'");
               } else if (temp.startsWith(QueryOptionConstant.MORETHAN)) {
                  temp = temp.substring((QueryOptionConstant.MORETHAN).length()).trim();
                  parentOidSql = QueryOptionConstant.MORETHAN + " " + ((temp.startsWith("'") && temp.endsWith("'")) ? temp : "'" + temp + "'");
               } else if (temp.startsWith(QueryOptionConstant.MORE)) {
                  temp = temp.substring((QueryOptionConstant.MORE).length()).trim();
                  parentOidSql = QueryOptionConstant.MORE + " " + ((temp.startsWith("'") && temp.endsWith("'")) ? temp : "'" + temp + "'");
               } else if (temp.startsWith(QueryOptionConstant.LESSTHAN)) {
                  temp = temp.substring((QueryOptionConstant.LESSTHAN).length()).trim();
                  parentOidSql = QueryOptionConstant.LESSTHAN + " " + ((temp.startsWith("'") && temp.endsWith("'")) ? temp : "'" + temp + "'");
               } else if (temp.startsWith(QueryOptionConstant.LESS)) {
                  temp = temp.substring((QueryOptionConstant.LESS).length()).trim();
                  parentOidSql = QueryOptionConstant.LESS + " " + ((temp.startsWith("'") && temp.endsWith("'")) ? temp : "'" + temp + "'");
               } else if (temp.startsWith(QueryOptionConstant.ISNOTNULL)) {
                  parentOidSql = " is not null";
               } else if (temp.startsWith(QueryOptionConstant.ISNULL)) {
                  parentOidSql = " is  null";
               } else if (temp.contains("*")) {
                  parentOidSql = " like " + ((temp.startsWith("'") && temp.endsWith("'")) ? temp : "'" + temp + "'").replace("*", "%");
               } else {
                  parentOidSql = " = " + ((temp.startsWith("'") && temp.endsWith("'")) ? temp : "'" + temp + "'");
               }
            }
            //查询全部的信息
            queryObject.getConditionMap().put("oid", QueryOptionConstant.IN + "(select oid from " +
               getTableName(referConfigVO.getReferType()) +
               " START WITH " + referConfigVO.getParentFieldName() + " " +
               parentOidSql +
               " CONNECT BY PRIOR " + oidFieldName + " = " + referConfigVO.getParentFieldName() + ")");
         }
      }
      LambdaQueryWrapper<CodeClassify> lqw = new LambdaQueryWrapper<>();
      String sql = queryObject.getConditionMap().get("oid").substring(3);
      lqw.inSql(CodeClassify::getOid, sql);
      List<CodeClassify> codeClassifies = classifyService.selectByWrapper(lqw);
      TreeWrapperOptions treeWrapperOptions = new TreeWrapperOptions(referConfigVO.getParentFieldName());
      treeWrapperOptions.setOidFieldName(oidFieldName);
      treeWrapperOptions.setTextFieldName(referConfigVO.getTextField());
      treeWrapperOptions.setMultipleSelect(referConfigVO.isMuti());
      treeWrapperOptions.setParentOid(queryObject.getParentOid());
      return revisionModelUtil.doList2Trees(codeClassifies, treeWrapperOptions, null);
   }
   @Override
   public boolean checkUnAttrUnEdit(String attrName) {
      return (VciQueryWrapperForDO.OID_FIELD.equalsIgnoreCase(attrName)
         || "ts".equalsIgnoreCase(attrName)
         || "lastmodifier".equalsIgnoreCase(attrName)
         || "lastmodifytime".equalsIgnoreCase(attrName)
         || "createtime".equalsIgnoreCase(attrName)
         || "checkintime".equalsIgnoreCase(attrName)
         || "checkouttime".equalsIgnoreCase(attrName));
   }
   private String getTableName(String refertype) {
      if ("codeclassify".equals(refertype)) {
         return "pl_code_classify";
      }
      if ("table".equals(refertype)) {
         return "pl_code_test_table";
      }
      if ("testBtmType".equals(refertype)) {
         return "PLBT_code_testBtmType";
      }
      return "pl_code_" + refertype.trim().toLowerCase();
   }
   public BaseModel reviseBusinessObject(BaseModel fromBo) {
      BaseModel toBo = new BaseModel();
      toBo.setOid(VciBaseUtil.getPk());
      toBo.setRevisionOid(VciBaseUtil.getPk());
      toBo.setNameOid(fromBo.getNameOid());
      toBo.setBtmname(fromBo.getBtmname());
      toBo.setLastR(String.valueOf(1));
      // 升版将FirstR修改为0
      toBo.setFirstR(String.valueOf(0));
      toBo.setFirstV(String.valueOf(1));
      toBo.setLastV(String.valueOf(1));
      // 数据升版不需要重新设置创建人,只对最后修改人做更新就可以了
      //toBo.setCreator(String.valueOf(AuthUtil.getUser().getUserId()));
      toBo.setCreateTime(fromBo.getCreateTime());
      // toBo.setLastModifier(String.valueOf(AuthUtil.getUser().getUserId()));
      toBo.setLastModifier(String.valueOf(AuthUtil.getUser().getAccount()));
      toBo.setLastModifyTime(new Date());
      toBo.setRevisionRule(fromBo.getRevisionRule());
      toBo.setVersionRule(fromBo.getVersionRule());
      //查询业务类型信息,可以获取到版本规则信息(revisionRuleId)
      R<List<BtmTypeVO>> listR = btmTypeClient.selectByIdCollection(Collections.singletonList(fromBo.getBtmname()));
      if (!listR.isSuccess() || listR.getData().size() == 0) {
         throw new VciBaseException("传入业务类型未查询到相应表单,请检查!");
      }
      //Map<String, Object> nextRevision = commonsMapper.getNextRevision(listR.getData().get(0).getTableName(), fromBo.getNameOid());
      /*
         TODO:这是一个待后期完善的功能,目前实现方式是,先查询出当前数据的大版本规则,
            然后再查询业务表使用的规则的步长是多少然后计算出该升版为多少
      */
      Map<String, Object> nextRevision = commonsMapper.getCurrentRevision(listR.getData().get(0).getTableName(), fromBo.getNameOid());
      R<RevisionRuleVO> revisionRuleVOR = revisionRuleClient.selectById(listR.getData().get(0).getRevisionRuleId());
      String revisionval = nextRevision.get("REVISIONVAL").toString();
      // 未查询到版本规则,默认直接给大版本加一
      if (!revisionRuleVOR.isSuccess() || Func.isEmpty(revisionRuleVOR.getData())) {
         revisionval = String.valueOf((Integer.parseInt(revisionval) + 1));
      } else {
         revisionval = String.valueOf(Integer.parseInt(revisionval) + revisionRuleVOR.getData().getSerialStep());
      }
      toBo.setRevisionValue(revisionval);
      toBo.setRevisionSeq(Integer.parseInt(nextRevision.get("REVISIONSEQ").toString()));
      toBo.setVersionSeq(Integer.valueOf(nextRevision.get("VERSIONSEQ").toString()));
      toBo.setVersionValue(nextRevision.get("VERSIONVAL").toString());
      toBo.setLctid(fromBo.getLctid());
      //toBo.setLcStatus("Editing");
      toBo.setLcStatus(CodeDefaultLC.RELEASED.getValue());
      toBo.setId(fromBo.getId());
      toBo.setName(fromBo.getName());
      toBo.setDescription(fromBo.getDescription());
      toBo.setOwner(String.valueOf(AuthUtil.getUser().getUserId()));
      toBo.setCopyFromVersion(fromBo.getOid());
      toBo.getData().putAll(fromBo.getData());
      toBo.getData().put("CHECKINBY", String.valueOf(AuthUtil.getUser().getUserId()));
      return toBo;
   }
   /**
    * 流程中变更状态值
    *
    * @param flowDTO
    * @return
    */
   @Override
   public R processChangeStatus(FlowStatusDTO flowDTO) {
      flowDTO.getOids().forEach(s -> {
         BaseModelDTO baseModel = new BaseModelDTO();
         baseModel.setOid(s);
         baseModel.setBtmname(flowDTO.getBtmType());
         baseModel.setLcStatus(String.valueOf(flowDTO.getVariableMap().getOrDefault("statusValue", "Auditing")));
         changeStatus(baseModel);
      });
      return R.success("成功");
   }
}