ludc
2023-12-01 bce3fcf05020405e33199706c3d91e9b9a71bd39
Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/service/impl/MdmEngineServiceImpl.java
@@ -1,5 +1,6 @@
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;
@@ -9,8 +10,10 @@
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.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.*;
@@ -22,6 +25,7 @@
import com.vci.ubcs.code.vo.pagemodel.UITablePageVO;
import com.vci.ubcs.code.vo.pagemodel.*;
import com.vci.ubcs.code.wrapper.BaseMdodelWrapper;
import com.vci.ubcs.code.wrapper.CodeAllcodeWrapper;
import com.vci.ubcs.flow.core.dto.FlowStatusDTO;
import com.vci.ubcs.flow.core.feign.IMDMIFlowAttrClient;
import com.vci.ubcs.flow.core.vo.ProcessStageAttrVO;
@@ -39,6 +43,8 @@
import com.vci.ubcs.starter.revision.model.TreeWrapperOptions;
import com.vci.ubcs.starter.revision.service.RevisionModelUtil;
import com.vci.ubcs.starter.util.MdmBtmTypeConstant;
import com.vci.ubcs.starter.util.SaveLogUtil;
import com.vci.ubcs.starter.util.SpecialCharacterConverter;
import com.vci.ubcs.starter.util.UBCSSqlKeyword;
import com.vci.ubcs.starter.web.constant.QueryOptionConstant;
import com.vci.ubcs.starter.web.constant.RegExpConstant;
@@ -59,13 +65,16 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springblade.core.cache.utils.CacheUtil;
import org.springblade.core.log.annotation.OperateLog;
import org.springblade.core.log.exception.ServiceException;
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;
@@ -81,7 +90,7 @@
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.*;
import java.util.stream.Collectors;
import static com.vci.ubcs.code.constant.FrameWorkLangCodeConstant.DATA_OID_NOT_EXIST;
@@ -97,12 +106,72 @@
@Service
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;
    private ICodeClstemplateService templateService;
    /**
     * 生成编码的服务
@@ -135,6 +204,11 @@
     */
    @Resource
    IEnumClient enumClient;
   /**
    * 版本规则服务
    */
   @Resource
   private IRevisionRuleClient revisionRuleClient;
    /**
     * 公式的服务
@@ -142,13 +216,11 @@
    @Autowired
    private FormulaServiceImpl formulaService;
    /**
     * 对omd中提供的feign接口进行调用,以及处理相关逻辑
     */
    @Autowired
    ICodeReferBtmTypeService codeReferBtmTypeService;
    /**
     * 相似项查询规则
@@ -172,17 +244,12 @@
     */
    @Autowired
    private IBtmTypeClient btmTypeClient;
    /**
     * 版本规则的服务
     */
    @Resource
    private IRevisionRuleClient revisionRuleClient;
//
    /**
     * 通用查询
     */
    @Resource
    CommonsMapper commonsMapper;
    private CommonsMapper commonsMapper;
    /**
     * 编码规则的服务
@@ -284,8 +351,15 @@
    */
   @Autowired
   private IMDMIFlowAttrClient imdmiFlowAttrClient;
//   @Autowired
//   private CodeOsbtmtypeMapper codeOsbtmtypeMapper;----
   //   @Autowired
   //   private CodeOsbtmtypeMapper codeOsbtmtypeMapper;
   /**
    * 日志保存工具类
    */
   @Autowired
   private SaveLogUtil saveLogUtil;
    /**
@@ -348,40 +422,75 @@
    @Transactional
    @Override
    public void changeStatus(BaseModelDTO baseModelDTO) {
        VciBaseUtil.alertNotNull(baseModelDTO, "数据信息", baseModelDTO.getOid(), "主键", baseModelDTO.getBtmname(), "业务类型", baseModelDTO.getLcStatus(), "目标状态");
        List<String> oids = VciBaseUtil.str2List(baseModelDTO.getOid());
        List<BaseModel> baseModels = new ArrayList<>();
        baseModels = selectByTypeAndOid(baseModelDTO.getBtmname(), baseModelDTO.getOid());
        if (baseModels.size() == 0) {
            throw new VciBaseException("未查询到相关数据。");
        }
        //还需要修改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());
      try {
         VciBaseUtil.alertNotNull(baseModelDTO, "数据信息", baseModelDTO.getOid(), "主键", baseModelDTO.getBtmname(), "业务类型", baseModelDTO.getLcStatus(), "目标状态");
         List<String> oids = VciBaseUtil.str2List(baseModelDTO.getOid());
         List<BaseModel> baseModels = new ArrayList<>();
         baseModels = selectByTypeAndOid(baseModelDTO.getBtmname(), baseModelDTO.getOid());
         if (baseModels.size() == 0) {
            throw new VciBaseException("未查询到相关数据。");
         }
         //还需要修改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());
            }
         }
         for (CodeAllCode codeCbo : codeCbos) {
            codeCbo.setLcStatus(baseModelDTO.getLcStatus());
         }
         codeAllCodeService.updateBatchById(codeCbos);
         //记录日志信息
         saveLogUtil.operateLog(
            CodeDefaultLC.getTextByValue(baseModelDTO.getLcStatus()),
            false,
            JSON.toJSONString(baseModels)
         );
      }catch (Exception e){
         // 插入更改日志记录
         saveLogUtil.operateLog(CodeDefaultLC.getTextByValue(baseModelDTO.getLcStatus()),true,e.getMessage());
         throw e;
      }
        for (CodeAllCode codeCbo : codeCbos) {
            codeCbo.setLcStatus(baseModelDTO.getLcStatus());
        }
        codeAllCodeService.updateBatchById(codeCbos);
    }
   /**
    * 申请单一编码
    *
    * @param orderDTO 申请的信息,需要包含属性的内容和码段相关的内容
    * @return 返回编码的内容
    */
   @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);
   }
    /**
     * 申请单一编码
@@ -389,8 +498,7 @@
     * @param orderDTO 申请的信息,需要包含属性的内容和码段相关的内容
     * @return 返回编码的内容
     */
    @Override
    public String addSaveCode(CodeOrderDTO orderDTO) throws Exception {
   private String addSaveCode(CodeOrderDTO orderDTO, boolean authUser) throws Exception {
        VciBaseUtil.alertNotNull(orderDTO, "编码申请相关的属性和码段的内容都为空", orderDTO.getCodeClassifyOid(), "主题库分类的主键",
                orderDTO.getTemplateOid(), "模板的主键", orderDTO.getCodeRuleOid(), "编码规则的主键");
        CodeClassifyFullInfoBO classifyFullInfo = classifyService.getClassifyFullInfo(orderDTO.getCodeClassifyOid());
@@ -412,26 +520,33 @@
        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);
      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()));
      cbo.setLastModifier(String.valueOf(AuthUtil.getUser().getUserId()));
      //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里。增加一个单独处理,以后再看要不要调整
      //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<>();
        //备注
@@ -466,7 +581,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);
@@ -487,7 +602,6 @@
            });
        }
    }
    /**
     * 判断编码的码段是否输入或者选择了码值
@@ -654,14 +768,16 @@
        //没有限制分类,但是一个模板只可能在一个业务类型里面,所以直接查询这个业务类型即可
        if (!CollectionUtils.isEmpty(conditionMap)) {
         conditionMap.put("CODETEMPLATEOID","'" + orderDTO.getTemplateOid() + "'");
         // 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()));
//            String referTable = VciBaseUtil.getTableName(referVO.getReferType());
            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 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) -> {
            if(StringUtils.isBlank(value)||value.equals(QueryOptionConstant.ISNULL)) {
               sql[0] += " and " + key + " is null";
@@ -676,11 +792,17 @@
                sql[0] += " and oid != '" + orderDTO.getCopyFromVersion() + "'";
            }
            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);
            }
        }
    }
@@ -725,7 +847,11 @@
         }
         final String[] sql = {"select * 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())) {
            //修改的时候,需要排除自己
@@ -753,7 +879,7 @@
    */
   @Override
   public R checkGroupCode(Map<String, String> parameter) {
      List<CodeClassify> codeClassifyList = classifyService.selectAllLevelParents(parameter.get("oid"));
      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--) {
@@ -766,6 +892,255 @@
//         }
      }
      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);
   }
   /**
@@ -819,13 +1194,13 @@
                    //不忽略大小写、不去空、不忽略全半角
                    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 {
            if(StringUtils.isNotBlank(value)) {
               //为空的时候不代表不校验,只是不去除相关的信息
               conditionMap.put("t." + attrId, "'" + value + "'");
               conditionMap.put("nvl("+ "t." + attrId+",'/')", "'" + SpecialCharacterConverter.escapeSpecialCharacters(value) + "'");
            }else{
               conditionMap.put("t." + attrId, QueryOptionConstant.ISNULL);
            }
@@ -914,7 +1289,8 @@
            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.setLastModifier(AuthUtil.getUser().getUserName());
            //cbo.setLastModifier(AuthUtil.getUser().getUserName());
         cbo.setLastModifier(AuthUtil.getUser().getAccount());
            cbo.setTs(new Date());
            if (!edit && StringUtils.isBlank(orderDTO.getLcStatus())) {
                //TODO 先写固定,后面生命周期好了在编写
@@ -924,10 +1300,10 @@
//                  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());
                }
            }
@@ -942,7 +1318,6 @@
            logger.error("设置默认的属性的值错误", e);
        }
    }
    /**
     * 初始化业务类型
@@ -987,22 +1362,22 @@
            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 = new ArrayList<>();
                    cboList.parallelStream().forEach(cbo -> {
//                  String value = cbo.get.getAttributeValue(attrVO.getId());
                  //String value = cbo.get.getAttributeValue(attrVO.getId());
                        //将bean转为map,mybatis统一处理
                        Map<String, String> map = null;
//                  baseModels.stream().forEach(model-> {
                  //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)) {
@@ -1387,6 +1762,10 @@
      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())){
@@ -1527,7 +1906,6 @@
            conditionMap.put(queryKey, QueryOptionConstant.OR + queryValue);
        }
    }
    /**
     * 查询编码数据的列表
@@ -1739,7 +2117,6 @@
        }
    }
    /**
     * 根据模板属性生成相应的sql信息
     *
@@ -1905,6 +2282,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);
@@ -1913,9 +2292,9 @@
        sqlBO.setSqlHasPage(sqlHasPage);
        sqlBO.setSqlCount(sqlCount);
        sqlBO.setSqlUnPage(sql);
      sqlBO.setSqlId(sqlId);
        return sqlBO;
    }
    /**
     * 组合查询条件的sql
@@ -1934,7 +2313,7 @@
                    //说明还是参照里面的,我们默认这种情况下都是字符串吧,因为参照的属性不一定用的平台的属性池里的,所以大部分情况下,显示的属性都是字符串吧
                    return referFieldMap.get(field) + SPACE + "LIKE" + SPACE + "'%" + value + "%'" + SPACE;
                } else {
                    return (field.contains(".") ? "" : "t.") + field + SPACE + "LIKE " + "'%" + getStringValueInWhere(field, value, attrVOMap) + "%'" + SPACE;
                    return (field.contains(".") ? "" : "t.") + field + SPACE + "LIKE " + "'%" + value + "%'" + SPACE;
                }
            } else if (key.endsWith("_notequal")) {
                String field = UBCSSqlKeyword.getColumn(key, "_notequal");
@@ -1969,7 +2348,7 @@
                if (referFieldMap.containsKey(field)) {
                    return referFieldMap.get(field) + SPACE + " >= " + value + SPACE;
                } else {
                    return (field.contains(".") ? "" : "t.") + field + SPACE + " >= " + getStringValueInWhere(value, field, attrVOMap) + SPACE;
                    return (field.contains(".") ? "" : "t.") + field + SPACE + " >= " + getStringValueInWhere(field, value, attrVOMap) + SPACE;
                }
            } else if (key.endsWith("_le")) {
                //说明是<=的。我们需要先获取一下
@@ -2054,7 +2433,7 @@
                if (referFieldMap.containsKey(field)) {
                    return referFieldMap.get(field) + SPACE + "= '" + value + "'" + SPACE;
                } else {
                    return (field.contains(".") ? "" : "t.") + field + SPACE + "= '" + getStringValueInWhere(field, value, attrVOMap) + "'" + SPACE;
                    return (field.contains(".") ? "" : "t.") + field + SPACE + "= " + getStringValueInWhere(field, value, attrVOMap) + "" + SPACE;
                }
            } else {
//                if (referFieldMap.containsKey(key)) {
@@ -2095,7 +2474,6 @@
            return getSqlByValue(key, value, attrVOMap,btmType);
         }
      }*/
    }
    /**
@@ -2350,9 +2728,13 @@
        }
//      cbo.getData().putAll(orderDTO.getData());
        cbo.setLastModifyTime(new Date());
        cbo.setLastModifier(String.valueOf(AuthUtil.getUser().getUserId()));
        updateBatchByBaseModel(classifyFullInfo.getTopClassifyVO().getBtmTypeId(), Collections.singletonList(cbo));
        batchSaveSelectChar(templateVO, Collections.singletonList(cbo));
        cbo.setLastModifier(String.valueOf(AuthUtil.getUser().getAccount()));
      R r = updateBatchByBaseModel(classifyFullInfo.getTopClassifyVO().getBtmTypeId(), Collections.singletonList(cbo));
      if(!r.isSuccess()){
         throw new ServiceException(r.getMsg());
      }
      batchSaveSelectChar(templateVO, Collections.singletonList(cbo));
    }
    /**
@@ -2390,7 +2772,7 @@
        }
        //只能删除自己创建的数据
        String userId = String.valueOf(AuthUtil.getUser().getUserId());
        String userId = String.valueOf(AuthUtil.getUser().getAccount());
        for (BaseModel clientBusinessObject : cboList) {
            String creator = clientBusinessObject.getCreator();
            if (!userId.equalsIgnoreCase(creator)) {
@@ -2402,10 +2784,10 @@
//      batchCBO.getDeleteCbos().addAll(cboList);
//      WebUtil.setPersistence(false);
//      batchCBO.copyFromOther(
        productCodeService.recycleCode(classifyFullInfo.getCurrentClassifyVO().getBtmTypeId(), deleteBatchDTO.getOidList());
        productCodeService.recycleCode(classifyFullInfo.getTopClassifyVO().getBtmTypeId(), deleteBatchDTO.getOidList());
//      baseMapper.deleteBatchIds(cboList);
        //使用传入的业务类型查询表
        R<List<BtmTypeVO>> listR = btmTypeClient.selectByIdCollection(Collections.singletonList(classifyFullInfo.getCurrentClassifyVO().getBtmTypeId()));
        R<List<BtmTypeVO>> listR = btmTypeClient.selectByIdCollection(Collections.singletonList(classifyFullInfo.getTopClassifyVO().getBtmTypeId()));
        if (!listR.isSuccess() || listR.getData().size() == 0) {
            throw new VciBaseException("传入业务类型未查询到相应表单,请检查!");
        }
@@ -2716,17 +3098,25 @@
        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().getUserId()));
      oldCbo.setLastModifier(String.valueOf(AuthUtil.getUser().getAccount()));
      oldCbo.setLastModifyTime(new Date());
        try {
         // 修改版次号
         updateBatchByBaseModel(oldCbo.getBtmname(), Collections.singletonList(oldCbo));
         // 插入新的数据
            insertBatchByType(cbo.getBtmname(), Collections.singletonList(cbo));
        } catch (Exception vciError) {
            throw new VciBaseException("数据更改保存出错了", new String[0], vciError);
        }
         // 记录数据更改日志
         saveLogUtil.operateLog("数据更改",false, StringUtil.format("{}\n修改为:\n{}",JSON.toJSONString(Collections.singletonList(oldCbo)),JSON.toJSONString(Collections.singletonList(cbo))));
      } catch (Exception vciError) {
         // 记录数据更改报错时的日志
         saveLogUtil.operateLog("数据更改",true,vciError.getMessage());
         throw new VciBaseException("数据更改保存出错了", new String[0], vciError);
      }
        batchSaveSelectChar(templateVO, Collections.singletonList(cbo));
    }
@@ -2800,7 +3190,7 @@
            // 日期码段设置默认值
            if (secVO.getSecType().equals(CodeSecTypeEnum.CODE_DATE_SEC.getValue())) {
               try {
                  secVO.setCodeDateFormatStr(Func.format(new Date(),secVO.getCodeDateFormatStr()));
                  secVO.setCodeDateValue(Func.format(new Date(),secVO.getCodeDateFormatStr()));
               }catch (Exception e){
                  throw new ServiceException("日期码段日期格式配置有误,导致转换出错:"+e.getMessage());
               }
@@ -2818,7 +3208,7 @@
            // 日期码段设置默认值
            if (secVO.getSecType().equals(CodeSecTypeEnum.CODE_DATE_SEC.getValue())) {
               try {
                  secVO.setCodeDateFormatStr(Func.format(new Date(),secVO.getCodeDateFormatStr()));
                  secVO.setCodeDateValue(Func.format(new Date(),secVO.getCodeDateFormatStr()));
               }catch (Exception e){
                  throw new ServiceException("日期码段日期格式配置有误,导致转换出错:"+e.getMessage());
               }
@@ -2840,7 +3230,7 @@
         // 日期码段设置默认值
         if (secVO.getSecType().equals(CodeSecTypeEnum.CODE_DATE_SEC.getValue())) {
            try {
               secVO.setCodeDateFormatStr(Func.format(new Date(),secVO.getCodeDateFormatStr()));
               secVO.setCodeDateValue(Func.format(new Date(),secVO.getCodeDateFormatStr()));
            }catch (Exception e){
               throw new ServiceException("日期码段日期格式配置有误,导致转换出错:"+e.getMessage());
            }
@@ -2871,7 +3261,7 @@
            }
            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();
@@ -2925,7 +3315,7 @@
        wrapperData(dataList, templateVO, sqlBO.getSelectFieldList(), true);
        R<List<Map<String, String>>> result = R.data(Collections.singletonList(cbo));
        //我们要看是否不是升版的,升版的话,需要对比不相等的属性
        String copy = cbo.get("copyfromversion");
/*        String copy = cbo.get("copyfromversion");
//      if (StringUtils.isBlank(copy)) {
//         copy = cbo.getAttributeValue("copyfromversion");
//      }
@@ -2944,11 +3334,12 @@
                Map<String, String> difFieldMap = new HashMap<>();
                Map<String, String> finalOldData = oldData;
                cbo.forEach((key, value) -> {
                    String oldValue = finalOldData.getOrDefault(key, "");
                    if (value == null) {
               // 这儿oldmap中的全是大写,而cbo中的全是小写所以会拿不到只,这儿直接处理成小写拿不到就用大写拿
               String oldValue = String.valueOf(finalOldData.getOrDefault(key.toUpperCase(Locale.ROOT), finalOldData.getOrDefault(key, "")));
               if (value == null || value == "null") {
                        value = "";
                    }
                    if (oldValue == null) {
                    if (oldValue == null || oldValue == "null") {
                        oldValue = "";
                    }
                    if (!value.equalsIgnoreCase(oldValue)) {
@@ -2959,7 +3350,7 @@
                difFieldList.add(difFieldMap);
                result.setData(difFieldList);
            }
        }
        }*/
        return result;
    }
@@ -3317,7 +3708,6 @@
        return getTableDefineByTemplateVO(templateService.getObjectHasAttrByOid(templateOid));
    }
    /**
     * 使用模板显示对象转换为表格的信息(包含扩展的按钮)
     *
@@ -3414,6 +3804,7 @@
        }
        return uiInfoVO;
    }
    @Override
   public MdmUIInfoVO getFlowUIInfoByClassifyOid(String codeClassifyOid, String functionId,String templateId,String taskId,String modelKey){
//      MdmUIInfoVO uiInfoVO = getTableDefineByClassifyOid_v2(codeClassifyOid,templateId,taskId,modelKey);
@@ -3501,6 +3892,7 @@
      }).collect(Collectors.toSet());
      //将bean转为map,mybatis统一处理
        List<Map<String, String>> maps = new ArrayList<>();
        baseModels.stream().forEach(model -> {
            try {
                maps.add(VciBaseUtil.convertBean2Map(model,existFild));
@@ -3508,8 +3900,106 @@
                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集合查询数据进行返回
@@ -3684,8 +4174,68 @@
        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 参照的配置
@@ -3724,6 +4274,7 @@
        if (listR.getData().isEmpty()) {
            throw new VciBaseException("传入业务类型未查询到相应表单,请检查!");
        }
      // TODO:参照配置的模糊查询过滤条件暂未处理
        String namesql = "";
        if (StringUtils.isNotBlank(baseQueryObject.getConditionMap().get("name"))) {
            String s = baseQueryObject.getConditionMap().get("name");
@@ -3966,25 +4517,44 @@
        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(new Date());
        toBo.setLastModifier(String.valueOf(AuthUtil.getUser().getUserId()));
      // 数据升版不需要重新设置创建人,只对最后修改人做更新就可以了
        //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());R<List<BtmTypeVO>> listR = btmTypeClient.selectByIdCollection(Collections.singletonList(fromBo.getBtmname()));
        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());
        toBo.setRevisionSeq(Integer.parseInt(nextRevision.get("REVISIONSEQ").toString()));
        toBo.setRevisionValue(nextRevision.get("REVISIONVAL").toString());
        //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("Editing");
      toBo.setLcStatus(CodeDefaultLC.RELEASED.getValue());
        toBo.setId(fromBo.getId());
        toBo.setName(fromBo.getName());
        toBo.setDescription(fromBo.getDescription());
@@ -3993,7 +4563,6 @@
        toBo.getData().putAll(fromBo.getData());
        toBo.getData().put("CHECKINBY", String.valueOf(AuthUtil.getUser().getUserId()));
        return toBo;
    }
   /**