ludc
2024-07-09 5acc490fa6f77a9ed7b5976ee6a2e22b070df5bf
Source/plt-web/plt-web-parent/plt-web/src/main/java/com/vci/frameworkcore/compatibility/impl/OrgDeptQueryServiceImpl.java
@@ -1,35 +1,51 @@
package com.vci.frameworkcore.compatibility.impl;
import com.vci.corba.common.PLException;
import com.vci.corba.common.data.UserEntityInfo;
import com.vci.corba.framework.data.DeptInfo;
import com.vci.corba.omd.data.BusinessObject;
import com.vci.frameworkcore.compatibility.OrgDeptQueryServiceI;
import com.vci.frameworkcore.model.dto.OrgDepartmentDTO;
import com.vci.frameworkcore.lcstatuspck.FrameworkDataLCStatus;
import com.vci.frameworkcore.model.OrgDeptForPlatform1;
import com.vci.frameworkcore.model.SmRoleForPlatform1;
import com.vci.frameworkcore.model.dto.SmUserDTO;
import com.vci.frameworkcore.model.po.OrgDeptPO;
import com.vci.frameworkcore.model.po.SmUserPO;
import com.vci.frameworkcore.pagemodel.OrgDepartmentVO;
import com.vci.frameworkcore.pagemodel.SmRoleVO;
import com.vci.frameworkcore.pagemodel.SmUserVO;
import com.vci.frameworkcore.properties.ConfigReader;
import com.vci.omd.utils.ObjectTool;
import com.vci.starter.poi.bo.ReadExcelOption;
import com.vci.starter.poi.bo.WriteExcelData;
import com.vci.starter.poi.bo.WriteExcelOption;
import com.vci.starter.poi.constant.ExcelLangCodeConstant;
import com.vci.starter.poi.util.ExcelUtil;
import com.vci.starter.revision.bo.TreeWrapperOptions;
import com.vci.starter.revision.service.RevisionModelUtil;
import com.vci.starter.web.constant.QueryOptionConstant;
import com.vci.starter.web.enumpck.UserSecretEnum;
import com.vci.starter.web.exception.VciBaseException;
import com.vci.starter.web.pagemodel.DataGrid;
import com.vci.starter.web.pagemodel.PageHelper;
import com.vci.starter.web.pagemodel.Tree;
import com.vci.starter.web.pagemodel.TreeQueryObject;
import com.vci.starter.web.util.BeanUtil;
import com.vci.starter.web.util.VciBaseUtil;
import com.vci.starter.web.pagemodel.*;
import com.vci.starter.web.util.*;
import com.vci.starter.web.wrapper.VciQueryWrapperForDO;
import com.vci.web.service.WebBoServiceI;
import com.vci.web.util.Func;
import com.vci.web.util.PlatformClientUtil;
import com.vci.web.util.WebUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.util.HSSFColor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.util.WebUtils;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
@@ -61,19 +77,60 @@
   private RevisionModelUtil revisionModelUtil;
   /**
    * 必填列
    */
   private ArrayList<Integer> ColumnNameisRed = new ArrayList<Integer>();
   /**
    * 日志
    */
   private Logger logger = LoggerFactory.getLogger(getClass());
   /**
     * 根据部门主键获取部门的信息
     * @param deptOid 部门主键
     * @return 部门的显示对象,如果部门不存在则返回null,不会抛出异常
     * @throws VciBaseException 参数为空或者数据库存在问题的时候会抛出异常
     */
   @Override
   public OrgDepartmentVO getDeptByDeptOid(String deptOid)
         throws VciBaseException {
   public OrgDepartmentVO getDeptByDeptOid(String deptOid) throws VciBaseException {
      if(StringUtils.isBlank(deptOid)){
         return null;
      }
      OrgDeptForPlatform1 deptForPlatform1 = boService.selectByOid(deptOid, OrgDeptForPlatform1.class);
      return deptDO2VO(deptForPlatform1);
      Map<String, String> conditionMap = new HashMap<>();
      conditionMap.put("pluid",deptOid);
      VciQueryWrapperForDO queryWrapper = new VciQueryWrapperForDO(conditionMap,OrgDeptForPlatform1.class);
      List<OrgDeptForPlatform1> deptForPlatform1s = boService.selectByQueryWrapper(queryWrapper, OrgDeptForPlatform1.class);
      if(Func.isEmpty(deptForPlatform1s)){
         return null;
      }
      return deptDO2VO(deptForPlatform1s.get(0));
   }
   /**
    * 根据父部门主键获取和部门名称部门的信息
    * @param parentDeptOid 父部门主键
    * @param conditionMap 部门名称
    * @return 部门的显示对象,如果部门不存在则返回null,不会抛出异常
    * @throws VciBaseException 参数为空或者数据库存在问题的时候会抛出异常
    */
   @Override
   public List<OrgDepartmentVO> getDeptByDeptPOidAndCondition(String parentDeptOid,Map<String,String> conditionMap) throws VciBaseException {
      if(Func.isEmpty(conditionMap)){
         conditionMap = new HashMap();
      }
      VciQueryWrapperForDO queryWrapper = new VciQueryWrapperForDO(conditionMap,OrgDeptForPlatform1.class);
      //父主键为空查顶层
      if(Func.isBlank(parentDeptOid)){
         queryWrapper.isNull("plparentuid");
      }else{
         queryWrapper.eq("plparentuid",parentDeptOid);
      }
      List<OrgDeptForPlatform1> roleForPlatform1s = boService.selectByQueryWrapper(queryWrapper, OrgDeptForPlatform1.class);
      if(Func.isEmpty(roleForPlatform1s)){
         return null;
      }
      return deptDO2VOs(roleForPlatform1s);
   }
   /**
@@ -98,18 +155,23 @@
      OrgDepartmentVO departmentVO = new OrgDepartmentVO();
      if(deptForPlatform1!=null){
         departmentVO.setOid(deptForPlatform1.getPluid());
         // 除部门主键外的唯一标识,长度为Dept:+8位可通过该参数反推回部门主键的hash编码
         departmentVO.setUniqueId("Dept:"+Func.oidEnHash(deptForPlatform1.getPluid()));
         departmentVO.setId(deptForPlatform1.getPlnum());
         departmentVO.setName(deptForPlatform1.getPlname());
         departmentVO.setStatus(deptForPlatform1.getPlstatus());
         if(0 == deptForPlatform1.getPlstatus()){
            departmentVO.setLcStatus(FrameworkDataLCStatus.ENABLED.getValue());
            departmentVO.setStatusText(FrameworkDataLCStatus.ENABLED.getValue());
         }else{
            departmentVO.setLcStatus(FrameworkDataLCStatus.DISABLED.getValue());
            departmentVO.setStatusText(FrameworkDataLCStatus.DISABLED.getValue());
         }
         departmentVO.setSpecialties(deptForPlatform1.getPlspecialties());
         departmentVO.setCode(deptForPlatform1.getPlcode());
         departmentVO.setPkFatherDepartment(deptForPlatform1.getPlparentuid());
         departmentVO.setDescription(deptForPlatform1.getPldesc());
         departmentVO.setCheckInTime(deptForPlatform1.getPlcreatetime());
         departmentVO.setCreateTime(new Date(deptForPlatform1.getPlcreatetime()));
         departmentVO.setCreator(deptForPlatform1.getPlcreateuser());
         departmentVO.setLastModifyTime(deptForPlatform1.getPlupdatetime());
         departmentVO.setLastModifyTime(new Date(deptForPlatform1.getPlupdatetime()));
         departmentVO.setLastModifier(deptForPlatform1.getPlupdateuser());
      }
      return departmentVO;
@@ -137,7 +199,7 @@
            depts.addAll(roleForPlatform1s);
         }
      });
      return    deptDO2VOs(depts);
      return deptDO2VOs(depts);
   }
   /**
@@ -153,6 +215,7 @@
      if(pageHelper == null){
         pageHelper = new PageHelper(-1);
      }
      //根据部门编号排序
      pageHelper.addDefaultAsc("plnum");
      VciQueryWrapperForDO queryWrapper = new VciQueryWrapperForDO(queryMap,OrgDeptForPlatform1.class,pageHelper);
      List<OrgDeptForPlatform1> deptForPlatform1s = boService.selectByQueryWrapper(queryWrapper, OrgDeptForPlatform1.class);
@@ -288,7 +351,7 @@
     * 批量根据用户的主键来获取部门
     * @param userOidCollection 用户主键集合
     * @param queryMap 查询条件,如果需要使用用户的属性来查询可以使用pkUser.xxxx
     * @return 部门的显示对象,key是用户主键,value是这个用户关联的部门
     * @return 部门的显示对象,key是用户主键,value是关联的部门
     */
   @Override
   public Map<String, List<OrgDepartmentVO>> batchListDeptByUserOids(
@@ -318,7 +381,6 @@
         //这儿应该对deptVOList做一次去重处理,因为肯定会有重复的部门被查出来
         Map<String, OrgDepartmentVO> deptVOMap = deptVOList.stream()
               .collect(Collectors.toMap(OrgDepartmentVO::getOid, Function.identity(), (existing, replacement) -> existing));
         //Map<String, OrgDepartmentVO> deptVOMap = deptVOList.stream().distinct().collect(Collectors.toMap(s -> s.getOid(), t -> t));
         Map<String, List<OrgDepartmentVO>> userDeptVOMap = new HashMap<>();
         userDeptOidMap.forEach((userOid,deptOids)->{
            List<OrgDepartmentVO> deptVOS = new ArrayList<>();
@@ -334,7 +396,63 @@
      return new HashMap<>();
   }
    /**
   /**
    * 批量根据用户的主键来获取部门名称(/间隔方式)
    * @param userOidCollection 用户主键集合
    * @param queryMap 查询条件,如果需要使用用户的属性来查询可以使用pkUser.xxxx
    * @return 部门的显示对象,key是用户主键,value是关联的部门(包含父节点如当前部门为人力资源部则值为:550/人力资源部)
    */
   @Override
   public Map<String,Map<String,String>> batchMapDeptNameByUserOids(Collection<String> userOidCollection, Map<String, String> queryMap) {
      if(CollectionUtils.isEmpty(userOidCollection)){
         return new HashMap<>();
      }
      Map<String,Map<String,String>> deptOidNameMap = new HashMap<>();
      Map<String,Map<String,String>> userDeptOidMap = new HashMap<>();
      WebUtil.switchCollectionForOracleIn(userOidCollection).stream().forEach(userOids->{
         //1、要先根据用户主键获取到关联的部门主键
         String sql = "select pluseruid,pldeptuid from pluserdept where pluseruid in (" + WebUtil.toInSql(userOids.toArray(new String[0])) + ")";
         List<BusinessObject> cbos = boService.queryBySql(sql, null);
         if(!CollectionUtils.isEmpty(cbos)){
            cbos.stream().forEach(cbo->{
               //角色主键
               String userOid = ObjectTool.getNewBOAttributeValue(cbo,"pluseruid");
               //部门主键
               String deptUid = ObjectTool.getNewBOAttributeValue(cbo, "pldeptuid");
               //2、然后根据部门主键获取到由部门名称/组成的值
               //避免多次查询,或者循环查询
               if(deptOidNameMap.containsKey(deptUid)){
                  userDeptOidMap.put(userOid,deptOidNameMap.get(deptUid));
               }else {
                  if(Func.isNotEmpty(deptUid)){
                     //2.1、查询部门oid,当前部门包含父部门
                     String queryDeptSql = "select pluid,plname from pldept START with pluid = '" +
                           deptUid + "' connect by prior plparentuid = pluid";
                     List<BusinessObject> cboDepts = boService.queryBySql(queryDeptSql, null);
                     if(!CollectionUtils.isEmpty(cboDepts)){
                        StringBuilder sb = new StringBuilder();
                        for (int i = cboDepts.size()-1; i >=0; i--) {
                           String deptName = ObjectTool.getNewBOAttributeValue(cboDepts.get(i),"plname");
                           sb.append(deptName);
                           sb.append("/");
                        }
                        //2.2、避免同一部门多次查询,这里存储在一个公共集合中,便于重复使用
                        //删除最后一个斜杠
                        sb.deleteCharAt(sb.length() - 1);
                        Map<String,String> tempMap = new HashMap<>();
                        tempMap.put(deptUid,sb.toString());
                        deptOidNameMap.put(deptUid,tempMap);
                        userDeptOidMap.put(userOid,tempMap);
                     }
                  }
               }
            });
         }
      });
      return userDeptOidMap;
   }
   /**
     * 获取某个部门的直属下级部门
     * @param pkFatherDepartmment 部门的主键
     * @param queryMap 查询条件
@@ -376,6 +494,7 @@
   public List<Tree> refTreeDept(TreeQueryObject treeQueryObject) {
      String pkFatherDepartmment=treeQueryObject.getParentOid();
      Map<String, String> conditionMap = treeQueryObject.getConditionMap();
      Map<String, String> extandParamsMap = treeQueryObject.getExtandParamsMap();
      if(conditionMap==null){
         conditionMap=new HashMap<String, String>();
      }
@@ -390,9 +509,27 @@
      TreeWrapperOptions treeWrapperOptions = new TreeWrapperOptions();
      BeanUtil.convert(treeQueryObject,treeWrapperOptions);
      treeWrapperOptions.setParentFieldName("pkFatherDepartment");
      return revisionModelUtil.doList2Trees(orgDepartmentVOList,treeWrapperOptions,dept->{
         return dept.getId() + " " + dept.getName() + (FrameworkDataLCStatus.DISABLED.getValue().equals(dept.getLcStatus())?"【停用】":"");
      List<Tree> trees = revisionModelUtil.doList2Trees(orgDepartmentVOList, treeWrapperOptions, dept -> {
         return dept.getId() + " " + dept.getName() + (FrameworkDataLCStatus.DISABLED.getValue().equals(dept.getLcStatus()) ? "【停用】" : "");
      });
      //extandParamsMap中添加"showAllDepartmentNode"为"true"时,并且parentOid为空,返回结果中会包含“所有部门”这个节点
      if(Func.isBlank(pkFatherDepartmment) && (Func.isNotEmpty(extandParamsMap) && Boolean.parseBoolean(extandParamsMap.getOrDefault("showAllDepartmentNode","false")))){
         List<Tree> treeList = new ArrayList<>();
         Tree tree = new Tree();
         tree.setLeaf(false);
         tree.setParentId(null);
         //没有实际作用只是界面上渲染使用
         tree.setOid(UUID.randomUUID().toString());
         tree.setParentName(null);
         Map<String, String> map = new HashMap<>();
         map.put("name","所有部门");
         map.put("ALLDept","ALLDept");
         tree.setAttributes(map);
         tree.setChildren(trees);
         treeList.add(tree);
         return treeList;
      }
      return trees;
   }
     /**
@@ -432,9 +569,6 @@
   @Override
   @Transactional(rollbackFor = Exception.class)
   public boolean saveUsersDept(String[] userOIds, String deptId) throws PLException {
      if(Func.isEmpty(userOIds) || Func.isBlank(deptId)){
         return false;
      }
      //先进性查重处理
      List<String> repeatUserOidList = new ArrayList<>();
      //循环进行查重,避免in大于1000
@@ -455,9 +589,345 @@
      tempList.removeAll(repeatUserOidList);
      userOIds = tempList.toArray(new String[tempList.size()]);
      if(Func.isNotEmpty(userOIds)){
         platformClientUtil.getFrameworkService().saveUserDept(userOIds, deptId,null);
         platformClientUtil.getFrameworkService().saveUserDept(userOIds, deptId,new UserEntityInfo(WebThreadLocalUtil.getCurrentUserSessionInfoInThread().getUserId(),null));
      }
      return true;
   }
   /**
    * 增加部门信息
    * @param orgDepartmentDTO
    * @return
    */
   @Override
   public boolean addDept(OrgDepartmentDTO orgDepartmentDTO) throws PLException {
      //判空
      VciBaseUtil.alertNotNull(
            orgDepartmentDTO,"添加的部门对象",
            orgDepartmentDTO.getName(),"部门名");
      //部门名和编号判重
      Map<String, String> conditionMap = new HashMap<>();
      conditionMap.put("plname",QueryOptionConstant.OR + orgDepartmentDTO.getName());
      if(Func.isNotBlank(orgDepartmentDTO.getId())){
         conditionMap.put("plnum",QueryOptionConstant.OR + orgDepartmentDTO.getId());
      }
      List<OrgDepartmentVO> departmentVOS = getDeptByDeptPOidAndCondition(orgDepartmentDTO.getPkFatherDepartment(), conditionMap);
      if(Func.isNotEmpty(departmentVOS)){
         throw new VciBaseException("同一父节点下该部门名称或编号已经存在,请修改!");
      }
      SessionInfo loginUser = WebThreadLocalUtil.getCurrentUserSessionInfoInThread();
      String userId = loginUser.getUserId();
      //生成存储的corba对象
      orgDepartmentDTO.setCreateTime(new Date());
      orgDepartmentDTO.setCreator(userId);
      orgDepartmentDTO.setLastModifier(userId);
      orgDepartmentDTO.setStatus((short) 0);
      DeptInfo deptInfo = changeOrgDeptDTOToDeptInfo(orgDepartmentDTO);
      UserEntityInfo userEntityInfo = new UserEntityInfo(userId, "");
      String oid = platformClientUtil.getFrameworkService().saveDepartment(deptInfo, userEntityInfo);
      if (Func.isEmpty(oid)) {
         return false;
      }
      return true;
   }
   /**
    * 修改部门信息
    * @param orgDepartmentDTO
    * @return
    */
   @Override
   public boolean updateDept(OrgDepartmentDTO orgDepartmentDTO) throws PLException {
      //判空
      VciBaseUtil.alertNotNull(
            orgDepartmentDTO,"修改的部门对象",
            orgDepartmentDTO.getOid(),"用户主键",
            orgDepartmentDTO.getId(),"用户名"
      );
      //按oid查询数据库中已存在的
      OrgDepartmentVO dbDepartmentVO = getDeptByDeptOid(orgDepartmentDTO.getOid());
      if(Func.isEmpty(dbDepartmentVO)){
         throw new VciBaseException("修改的部门不存在!");
      }
      //部门名和编号判重
      Map<String, String> conditionMap = new HashMap<>();
      conditionMap.put("plname",QueryOptionConstant.OR + orgDepartmentDTO.getName());
      if(Func.isNotBlank(orgDepartmentDTO.getId())){
         conditionMap.put("plnum",QueryOptionConstant.OR + orgDepartmentDTO.getId());
      }
      List<OrgDepartmentVO> repeatDepartmentVOS = getDeptByDeptPOidAndCondition(orgDepartmentDTO.getPkFatherDepartment(), conditionMap);
      repeatDepartmentVOS = repeatDepartmentVOS.stream().filter(item -> {
         if((item.getName().equals(orgDepartmentDTO.getName()) || item.getId().equals(orgDepartmentDTO.getId())) &&
               !item.getOid().equals(orgDepartmentDTO.getOid())){
            return true;
         }
         return false;
      }).collect(Collectors.toList());
      if(Func.isNotEmpty(repeatDepartmentVOS) ){
         throw new VciBaseException("同一父节点下该部门名称或编号已经存在,请修改!");
      }
      OrgDepartmentDTO departmentDTO = new OrgDepartmentDTO();
      BeanUtil.convert(dbDepartmentVO,departmentDTO);
      departmentDTO.setCode(orgDepartmentDTO.getCode());
      departmentDTO.setId(orgDepartmentDTO.getId());
      departmentDTO.setSpecialties(orgDepartmentDTO.getSpecialties());
      departmentDTO.setDescription(orgDepartmentDTO.getDescription());
      departmentDTO.setName(orgDepartmentDTO.getName());
      String loginUserId = WebThreadLocalUtil.getCurrentUserSessionInfoInThread().getUserId();
      orgDepartmentDTO.setLastModifier(loginUserId);
      DeptInfo deptInfo = changeOrgDeptDTOToDeptInfo(departmentDTO);
      boolean updateBoolean = platformClientUtil.getFrameworkService().updateDepartment(deptInfo, new UserEntityInfo(loginUserId, null));
      return updateBoolean;
   }
   /**
    * Dto对象转corb对象
    * @param orgDepartmentDTO
    * @return
    */
   public DeptInfo changeOrgDeptDTOToDeptInfo(OrgDepartmentDTO orgDepartmentDTO) {
      DeptInfo departmentInfo = new DeptInfo();
      departmentInfo.id = orgDepartmentDTO.getOid() == null ? "" : orgDepartmentDTO.getOid();
      departmentInfo.name = orgDepartmentDTO.getName() == null ? "" : orgDepartmentDTO.getName();
      departmentInfo.num = orgDepartmentDTO.getId() == null ? "" : orgDepartmentDTO.getId();
      departmentInfo.code = orgDepartmentDTO.getCode() == null ? "" : orgDepartmentDTO.getCode();
      departmentInfo.specialties = orgDepartmentDTO.getSpecialties() == null ? "" : orgDepartmentDTO.getSpecialties();
      departmentInfo.status = orgDepartmentDTO.getStatus() == 0 ? 0 : orgDepartmentDTO.getStatus();
      departmentInfo.description = orgDepartmentDTO.getDescription() == null ? "" : orgDepartmentDTO.getDescription();
      departmentInfo.parentId = orgDepartmentDTO.getPkFatherDepartment() == null ? "" : orgDepartmentDTO.getPkFatherDepartment();
      departmentInfo.createUser = orgDepartmentDTO.getCreator() == null ? "" : orgDepartmentDTO.getCreator();
      departmentInfo.createTime = orgDepartmentDTO.getCreateTime().getTime();
      departmentInfo.updateTime = System.currentTimeMillis();
      departmentInfo.updateUser = orgDepartmentDTO.getLastModifier() == null ? "" : orgDepartmentDTO.getLastModifier();
      //departmentInfo.grantor = orgDepartmentDTO.getGrantor() == null ? "" : orgDepartmentDTO.getGrantor();
      return departmentInfo;
   }
   /**
    * 删除部门
    * @param ids
    * @return
    */
   @Override
   public boolean deleteDept(String[] ids) throws PLException {
      VciBaseUtil.alertNotNull(ids,"要删除的部门主键");
      //具备连带删除的功能,如角色菜单授权表里面的授权信息
      return platformClientUtil.getFrameworkService().deleteDepartment(
            ids,
            new UserEntityInfo("developer"/*WebThreadLocalUtil.getCurrentUserSessionInfoInThread().getUserId()*/, null)
      );
   }
   /**
    * 获取所有部门的信息
    * @return key:部门由名称组成的路径(/间隔),value对应最小层级的部门信息
    */
   @Override
   public Map<String, OrgDepartmentVO> getDeptAllTreeMap() {
      List<OrgDepartmentVO> orgDepartmentVOList = listAllLevelChildrenDeptByParentOid(null, null);
      Map<String, OrgDepartmentVO> stringOrgDepartmentVOMap = convertToMap(orgDepartmentVOList);
      return stringOrgDepartmentVOMap;
   }
   /**
    * 下载导入部门的excel模板。
    * @param downloadFileName
    * @return
    */
   @Override
   public String downloadImportTemplate(String downloadFileName) {
      //界面没传名称,使用默认名称
      downloadFileName = Func.isBlank(downloadFileName) ?  "部门导入模板_" + Func.format(new Date(),"yyyy-MM-dd HHmmss.sss"):downloadFileName;
      // 设置表单列名
      List<String> columns = new ArrayList<>(Arrays.asList("ID", "名称", "编号", "代号", "专业", "父ID(部门唯一标识ID)", "描述"));
      //设置必填列
      ColumnNameisRed.clear();
      ColumnNameisRed.add(0);
      ColumnNameisRed.add(1);
      //写excel
      String excelPath = LocalFileUtil.getDefaultTempFolder() + File.separator + downloadFileName +  ".xls";
      try {
         new File(excelPath).createNewFile();
      } catch (Throwable e) {
         throw new VciBaseException(LangBaseUtil.getErrorMsg(e), new String[]{excelPath}, e);
      }
      //设置列
      List<WriteExcelData> excelDataList = new ArrayList<>();
      for (int index = 0; index < columns.size(); index++) {
         //判断是否为必填列,给必填列设置颜色
         if(ColumnNameisRed.contains(index)){
            WriteExcelData excelData = new WriteExcelData(0, index, columns.get(index));
            excelData.setFontColor(String.valueOf(HSSFColor.HSSFColorPredefined.RED.getIndex()));
            excelDataList.add(excelData);
         }else{
            excelDataList.add(new WriteExcelData(0,index, columns.get(index)));
         }
      }
      WriteExcelOption excelOption = new WriteExcelOption(excelDataList);
      ExcelUtil.writeDataToFile(excelPath, excelOption);
      return excelPath;
   }
   /**
    * 导入部门
    * @param file
    * @return
    * @throws VciBaseException
    */
   @Override
   public BaseResult importDept(File file) throws VciBaseException {
      VciBaseUtil.alertNotNull(file,"excel文件");
      if(!file.exists()){
         throw new VciBaseException("导入的excel文件不存在,{0}",new String[]{file.getPath()});
      }
      try{
         //1、读取excel中的数据,组成对象
         ReadExcelOption excelOption = new ReadExcelOption();
         //当前登录的用户账号
         //String loginUserId = WebThreadLocalUtil.getCurrentUserSessionInfoInThread().getUserId();
         String loginUserId = "developer";
         UserEntityInfo userEntityInfo = new UserEntityInfo(loginUserId,null);
         List<OrgDeptPO> poList = ExcelUtil.readDataObjectFromExcel(file, OrgDeptPO.class,excelOption,(value, po, fieldName)->{});
         //去除都是空的情况
         if(CollectionUtils.isEmpty(poList)){
            return BaseResult.fail(ExcelLangCodeConstant.IMPORT_CONTENT_NULL,new String[]{});
         }
         /*部门导入几个比较重要的情景:
            1、当前导入的数据是一个部门树结构(要判断用户手输的ID是否存在重复,输了就要判断是否在当前表格中重复,
               并且保存时不能使用用户手输的ID,要根据手输ID和实际存储OID做对应映射,
               并且不破坏表格中部门树结构,如果没手输ID就只需要关注parentId这个属性,
               并且需要注意如果有的ID有,有的没有那就需要注意,既存在和系统中,
               关联的部门树,又存在和当前表格中关联的部门树)。
            2、当前导入的数据父id关联了已存在的部门oid(要查询父id这个部门是否存在,)
         解决思路:最好是将表格中可能是部门树的给遍历成树,然后再做查重啥的处理
         */
         //2、必填判空、判重(数据库判重和excel中判重),组装成保存用的数据对象
         List<DeptInfo> deptInfoList = new ArrayList<>();
         //2.1、用以存储excel中重复的数据,三个不可重复的字段)(Name不能为空,Name、Code同一父部门下唯一)
         List<String> repeatIdList = new ArrayList<>();
         Map<String,String> repeatNameMap = new HashMap<>();
         Map<String,String> repeatNumMap = new HashMap<>();
         Map<String,String> indexMap = new HashMap<>();
         //2.2、存储用户手输的oid和实际存储oid的映射关系
         Map<String, String> oidMap = new HashMap<>();
         poList.stream().forEach(po->{
            String parentId = Func.isBlank(po.getParentId()) ? "":po.getParentId();
            //表格内判重
            //部门名称判空
            if(Func.isEmpty(po.getName())){
               throw new VciBaseException("第【"+po.getRowIndex()+"】行,depterror,Reason:Name cannot be empty");
            }else if(repeatNameMap.getOrDefault(po.getName(), "").equals(parentId)/*excel中同一部门下Name相等*/){
               //同一部门下名称判重
               throw new VciBaseException("第【"+po.getRowIndex()+"】行,deptnameerror,Reason: Names under the same department cannot be duplicated");
            }else if(Func.isNotEmpty(po.getId()) && repeatIdList.equals(po.getId())){
               throw new VciBaseException("第【"+po.getRowIndex()+"】行,deptiderror,Reason: The primary key cannot be duplicated");
            }else if(Func.isNotEmpty(po.getNum()) && repeatNumMap.getOrDefault(po.getNum(),"").equals(parentId)/*excel中同一部门下编号存在 */){
               throw new VciBaseException("第【"+po.getRowIndex()+"】行,deptnumerror,Reason: The number cannot be duplicated");
            }else{
               //2.2、查询数据库中的数据(查重ID和NUM),比较麻烦需要根据ParentID查询(所有只能单条查询进行判重)
               //组装查重条件:同一部门下(parentId相等),name或者num相等
               HashMap<String, String> conditionMap = new HashMap<>();
               conditionMap.put("plname",po.getName());
               conditionMap.put("plnum",QueryOptionConstant.OR + po.getNum());
               String pId = Func.isBlank(po.getParentId()) ? null:po.getParentId();
               List<OrgDepartmentVO> repeatOrgDept = this.getDeptByDeptPOidAndCondition(pId, conditionMap);
               //只要不为空就说明当前行数据在系统中重复
               if(Func.isNotEmpty(repeatOrgDept)){
                  throw new VciBaseException("第【"+po.getRowIndex()+"】行,deptname or deptnum error,Reason: The name or number already exists in the system");
               }
            }
            //存储校验通过的数据,以便后续excel查重
            repeatNameMap.put(po.getName(),Func.isBlank(po.getParentId()) ? "":po.getParentId());
            repeatIdList.add(po.getId());
            repeatNumMap.put(po.getNum(),po.getParentId());
            indexMap.put(po.getName(),po.getRowIndex());
            //校验数据就该组装成DTO数据对象了
            OrgDepartmentDTO dto = new OrgDepartmentDTO();
            BeanUtil.convert(po,dto);
            dto.setOid(po.getId());
            dto.setId(po.getNum());
            dto.setPkFatherDepartment(po.getParentId());
            dto.setCreateTime(new Date());
            dto.setCreator(loginUserId);
            dto.setLastModifier(loginUserId);
            dto.setStatus((short) 0);
            //2.2、过程中处理主键转换问题最好是一条一条的处理ID是否存在还有ParentID是否存在的问题
            //先判断是已存在的部门ID,还是不存在的部门ID,已存在系统中的ID就是为Dept:开头的
            String pId = dto.getPkFatherDepartment();
            //是已存在系统中的部门id
            if(pId.contains("Dept:")){
               //解析出真实的oid
               String deParentId = Func.oidDeHash(pId.replace("Dept:", "").trim());
               //解析出来的deParentId必须得在库中存在
               if(Func.isBlank(deParentId) || Func.isEmpty(this.getDeptByDeptOid(deParentId))){
                  throw new VciBaseException("第【"+ po.getRowIndex() +"】行,deptparentiderror,Reason:Parent ID resolution error or does not exist in the system");
               }
               //替换掉临时使用的部门唯一标识
               dto.setPkOrganizationName(deParentId);
            }
            //用户手输了部门oid,但是避免oid不规范需要,用规范oid进行替换,如果没输入保存时会自动生成oid
            if(Func.isNotBlank(dto.getOid())){
               String pkOid = VciBaseUtil.getPk();
               dto.setOid(pkOid);
               //oid映射关系,后续用来更新parentId
               oidMap.put(dto.getOid(),pkOid);
            }
            DeptInfo deptInfo = this.changeOrgDeptDTOToDeptInfo(dto);
            deptInfoList.add(deptInfo);
         });
         //3、处理id和parentId的映射关系:将用户手输的父ID转换成实际存储的ID
         List<DeptInfo> lastDeptInfoList = deptInfoList.stream().map(info -> {
            //parentId不为空并且没有Dept:相关的字符串,说明是用户手输的ParentId(导入的数据就是一个树结构)
            if (Func.isNotBlank(info.parentId) || info.parentId.contains("Dept:")) {
               //转换ParentId为实际要存储的部门ID
               info.parentId = oidMap.get(info.parentId);
            }
            return info;
         }).collect(Collectors.toList());
         //4、对最终处理好的部门数据保存,实现最终统一保存,避免了一部分数据进了一部分数据因为校验没过没进库的问题
         platformClientUtil.getFrameworkService().batchSaveDepart(
               lastDeptInfoList.toArray(new DeptInfo[lastDeptInfoList.size()]),
               userEntityInfo
         );
      }catch (Exception e){
         if(logger.isErrorEnabled()){
            logger.error("读取excel内容时或保存用户信息时出现了错误,具体原因:",e.getMessage());
         }
         e.printStackTrace();
         return BaseResult.fail(LangBaseUtil.getErrorMsg(e),new String[]{},e);
      }
      return BaseResult.success("部门导入成功!");
   }
   public Map<String, OrgDepartmentVO> convertToMap(List<OrgDepartmentVO> orgDepartmentVOList) {
      Map<String, OrgDepartmentVO> map = new HashMap<>();
      for (OrgDepartmentVO orgDepartmentVO : orgDepartmentVOList) {
         String key = buildKey(orgDepartmentVO, orgDepartmentVOList);
         map.put(key, orgDepartmentVO);
      }
      return map;
   }
   private String buildKey(OrgDepartmentVO orgDepartmentVO, List<OrgDepartmentVO> orgDepartmentVOList) {
      StringBuilder keyBuilder = new StringBuilder();
      OrgDepartmentVO current = orgDepartmentVO;
      while (current != null) {
         keyBuilder.insert(0, current.getName());
         keyBuilder.insert(0, "/");
         current = getParentDepartment(current.getPkFatherDepartment(), orgDepartmentVOList);
      }
      keyBuilder.deleteCharAt(0);
      return keyBuilder.toString();
   }
   private OrgDepartmentVO getParentDepartment(String pkFatherDepartment, List<OrgDepartmentVO> orgDepartmentVOList) {
      for (OrgDepartmentVO orgDepartmentVO : orgDepartmentVOList) {
         if (pkFatherDepartment != null && pkFatherDepartment.equals(orgDepartmentVO.getOid())) {
            return orgDepartmentVO;
         }
      }
      return null;
   }
}