package org.jeecg.modules.system.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.exceptions.ClientException;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.dto.message.MessageDTO;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.config.TenantContext;
import org.jeecg.common.constant.CacheConstant;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.constant.FillRuleConstant;
import org.jeecg.common.constant.SymbolConstant;
import org.jeecg.common.constant.PasswordConstant;
import org.jeecg.common.constant.enums.*;
import org.jeecg.common.desensitization.annotation.SensitiveEncode;
import org.jeecg.common.exception.JeecgBootBizTipException;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.system.vo.SysUserCacheInfo;
import org.jeecg.common.util.*;
import org.jeecg.common.util.encryption.AesEncryptUtil;
import org.jeecg.config.JeecgBaseConfig;
import org.jeecg.config.mybatis.MybatisPlusSaasConfig;
import org.jeecg.modules.base.service.BaseCommonService;
import org.jeecg.modules.message.handle.impl.SystemSendMsgHandle;
import org.jeecg.modules.system.entity.*;
import org.jeecg.modules.system.mapper.*;
import org.jeecg.modules.system.model.SysLoginModel;
import org.jeecg.modules.system.model.SysUserSysDepPostModel;
import org.jeecg.modules.system.model.SysUserSysDepartModel;
import org.jeecg.modules.system.service.*;
import org.jeecg.modules.system.util.ImportSysUserCache;
import org.jeecg.modules.system.vo.*;
import org.jeecg.modules.system.vo.lowapp.AppExportUserVo;
import org.jeecg.modules.system.vo.lowapp.DepartAndUserInfo;
import org.jeecg.modules.system.vo.lowapp.DepartInfo;
import org.jeecg.modules.system.vo.lowapp.UpdateDepartInfo;
import org.jeecgframework.poi.excel.ExcelImportUtil;
import org.jeecgframework.poi.excel.def.NormalExcelConstants;
import org.jeecgframework.poi.excel.entity.ExportParams;
import org.jeecgframework.poi.excel.entity.ImportParams;
import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
import org.jetbrains.annotations.Nullable;
import org.springframework.beans.BeanUtils;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;

import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.ModelAndView;

import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @Author: scott
 * @Date: 2018-12-20
 */
@Service
@Slf4j
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements ISysUserService {
	
	@Autowired
	private SysUserMapper userMapper;
	@Autowired
	private SysPermissionMapper sysPermissionMapper;
	@Autowired
	private SysUserRoleMapper sysUserRoleMapper;
	@Autowired
	private SysUserDepartMapper sysUserDepartMapper;
	@Autowired
	private SysDepartMapper sysDepartMapper;
	@Autowired
	private SysRoleMapper sysRoleMapper;
	@Autowired
	private SysDepartRoleUserMapper departRoleUserMapper;
	@Autowired
	private SysDepartRoleMapper sysDepartRoleMapper;
	@Resource
	private BaseCommonService baseCommonService;
	@Autowired
	private SysThirdAccountMapper sysThirdAccountMapper;
	@Autowired
	ThirdAppWechatEnterpriseServiceImpl wechatEnterpriseService;
	@Autowired
	ThirdAppDingtalkServiceImpl dingtalkService;
	@Autowired
	ISysRoleIndexService sysRoleIndexService;
	@Autowired
	SysTenantMapper sysTenantMapper;
	@Autowired
    private SysUserTenantMapper relationMapper;
	@Autowired
    private SysUserTenantMapper userTenantMapper;
	@Autowired
	private SysUserPositionMapper sysUserPositionMapper;
	@Autowired
	private SysPositionMapper sysPositionMapper;
	@Autowired
	private SystemSendMsgHandle systemSendMsgHandle;
	
	@Autowired
	private ISysThirdAccountService sysThirdAccountService;
	@Autowired
	private RedisUtil redisUtil;
    
    @Autowired
    private SysTenantPackUserMapper packUserMapper;
    
    @Autowired
    private SysUserDepPostMapper depPostMapper;

	@Autowired
	private JeecgBaseConfig jeecgBaseConfig;

	/**
	 * 管理员账号
	 */
	public static final String[] ADMIN_ACCOUNT = new String[]{"admin"};

	@Override
	public Result<IPage<SysUser>> queryPageList(HttpServletRequest req, QueryWrapper<SysUser> queryWrapper, Integer pageSize, Integer pageNo) {
		Result<IPage<SysUser>> result = new Result<IPage<SysUser>>();
		//部门ID
		String departId = req.getParameter("departId");
		if (oConvertUtils.isNotEmpty(departId)) {
            //代码逻辑说明:【JHHB-762】用户管理需要支持按组织架构查询用户（支持多选）---
            //兼容多个部门id
            LambdaQueryWrapper<SysUserDepart> query = new LambdaQueryWrapper<>();
            if(departId.contains(SymbolConstant.COMMA)) {
                query.in(SysUserDepart::getDepId, Arrays.asList(departId.split(SymbolConstant.COMMA)));
            } else {
                query.eq(SysUserDepart::getDepId, departId);
            }
            List<SysUserDepart> list = sysUserDepartMapper.selectList(query);
			List<String> userIds = list.stream().map(SysUserDepart::getUserId).collect(Collectors.toList());
			// 代码逻辑说明: [issues/I4XTYB]查询用户时，当部门id 下没有分配用户时接口报错------------
			if (oConvertUtils.listIsNotEmpty(userIds)) {
				queryWrapper.in("id", userIds);
			} else {
				return Result.OK();
			}
		}
		//用户ID
		String code = req.getParameter("code");
		if (oConvertUtils.isNotEmpty(code)) {
			queryWrapper.in("id", Arrays.asList(code.split(",")));
			pageSize = code.split(",").length;
		}

		// 代码逻辑说明: JTC-372 【用户冻结问题】 online授权、用户组件，选择用户都能看到被冻结的用户
		String status = req.getParameter("status");
		if (oConvertUtils.isNotEmpty(status)) {
			queryWrapper.eq("status", Integer.parseInt(status));
		}

		// 代码逻辑说明: 【QQYUN-8110】在线通讯录支持设置权限(只能看分配的技术支持)---
		String tenantId = TokenUtils.getTenantIdByRequest(req);
		String lowAppId = TokenUtils.getLowAppIdByRequest(req);
//		Object bean = ResourceUtil.getImplementationClass(DataEnhanceEnum.getClassPath(tenantId,lowAppId));
//		if(null != bean){
//			UserFilterEnhance userEnhanceService = (UserFilterEnhance) bean;
//			LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
//			List<String> userIds = userEnhanceService.getUserIds(sysUser.getId());
//			if(CollectionUtil.isNotEmpty(userIds)){
//				queryWrapper.in("id", userIds);
//			}
//		}
		
		//TODO 外部模拟登陆临时账号，列表不显示
		queryWrapper.ne("username", "_reserve_user_external");
        // 代码逻辑说明: 【JHHB-765】需要能设置排序---
        queryWrapper.orderByAsc("sort");
        queryWrapper.orderByDesc("create_time");
		Page<SysUser> page = new Page<SysUser>(pageNo, pageSize);
		IPage<SysUser> pageList = this.page(page, queryWrapper);

		//批量查询用户的所属部门
		//step.1 先拿到全部的 useids
		//step.2 通过 useids，一次性查询用户的所属部门名字
		List<String> userIds = pageList.getRecords().stream().map(SysUser::getId).collect(Collectors.toList());
		if (userIds != null && userIds.size() > 0) {
			Map<String, String> useDepNames = this.getDepNamesByUserIds(userIds);
			pageList.getRecords().forEach(item -> {
				item.setOrgCodeTxt(useDepNames.get(item.getId()));
				//增加所属部门id,前台需要展示
                List<String> departs = sysDepartMapper.queryDepartsByUserId(item.getId());
                if(oConvertUtils.isNotEmpty(departs)){
                    item.setBelongDepIds(String.join(SymbolConstant.COMMA, departs));
                }
				//查询用户的租户ids
				List<Integer> list = userTenantMapper.getTenantIdsByUserId(item.getId());
				if (oConvertUtils.isNotEmpty(list)) {
					item.setRelTenantIds(StringUtils.join(list.toArray(), SymbolConstant.COMMA));
				} else {
					item.setRelTenantIds("");
				}
				Integer posTenantId = null;
				if (MybatisPlusSaasConfig.OPEN_SYSTEM_TENANT_CONTROL) {
					posTenantId = oConvertUtils.getInt(TenantContext.getTenant(), 0);;		
				}
				//查询用户职位关系表(获取租户下面的)
				// 代码逻辑说明: 【QQYUN-7028】用户职务保存后未回显---
				List<String> positionList =  sysUserPositionMapper.getPositionIdByUserTenantId(item.getId(),posTenantId);
				item.setPost(CommonUtils.getSplitText(positionList,SymbolConstant.COMMA));
				
				//是否根据租户隔离(敲敲云用户列表专用，用于展示是否同步钉钉)
				if (MybatisPlusSaasConfig.OPEN_SYSTEM_TENANT_CONTROL) {
					//查询账号表是否已同步钉钉
					LambdaQueryWrapper<SysThirdAccount> query = new LambdaQueryWrapper<>();
					query.eq(SysThirdAccount::getSysUserId,item.getId());
					query.eq(SysThirdAccount::getTenantId, tenantId);
					//目前只有同步钉钉
					query.eq(SysThirdAccount::getThirdType, MessageTypeEnum.DD.getType());
					//不为空代表已同步钉钉
					List<SysThirdAccount> account = sysThirdAccountService.list(query);
					if(CollectionUtil.isNotEmpty(account)){
						item.setIzBindThird(true);
					}
				}
                //查询部门的兼职岗位
                List<String> depPostList = depPostMapper.getDepPostByUserId(item.getId());
                if(CollectionUtil.isNotEmpty(depPostList)){
                    item.setOtherDepPostId(StringUtils.join(depPostList.toArray(), SymbolConstant.COMMA));
                }
            });
		}

		result.setSuccess(true);
		result.setResult(pageList);
		//log.info(pageList.toString());
		return result;
	}


    @Override
    @CacheEvict(value = {CacheConstant.SYS_USERS_CACHE}, allEntries = true)
    public Result<?> resetPassword(String username, String oldpassword, String newpassword, String confirmpassword) {
        SysUser user = userMapper.getUserByName(username);
        String passwordEncode = PasswordUtil.encrypt(username, oldpassword, user.getSalt());
        if (!user.getPassword().equals(passwordEncode)) {
            return Result.error("旧密码输入错误!");
        }
        if (oConvertUtils.isEmpty(newpassword)) {
            return Result.error("新密码不允许为空!");
        }
        if (!newpassword.equals(confirmpassword)) {
            return Result.error("两次输入密码不一致!");
        }
        String password = PasswordUtil.encrypt(username, newpassword, user.getSalt());
        this.userMapper.update(new SysUser().setPassword(password), new LambdaQueryWrapper<SysUser>().eq(SysUser::getId, user.getId()));
        return Result.ok("密码重置成功!");
    }

    @Override
    @CacheEvict(value = {CacheConstant.SYS_USERS_CACHE}, allEntries = true)
    public Result<?> changePassword(SysUser sysUser) {
        String salt = oConvertUtils.randomGen(8);
        sysUser.setSalt(salt);
        String password = sysUser.getPassword();
        String passwordEncode = PasswordUtil.encrypt(sysUser.getUsername(), password, salt);
        sysUser.setPassword(passwordEncode);
        sysUser.setLastPwdUpdateTime(new Date());
        this.userMapper.updateById(sysUser);
        return Result.ok("密码修改成功!");
    }

    @Override
    @CacheEvict(value={CacheConstant.SYS_USERS_CACHE}, allEntries=true)
	@Transactional(rollbackFor = Exception.class)
	public boolean deleteUser(String userId) {
		//1.验证当前用户是管理员账号 admin
		//验证用户是否为管理员
		this.checkUserAdminRejectDel(userId);
		
		//2.删除用户
		this.removeById(userId);
		return false;
	}

	@Override
    @CacheEvict(value={CacheConstant.SYS_USERS_CACHE}, allEntries=true)
	@Transactional(rollbackFor = Exception.class)
	public boolean deleteBatchUsers(String userIds) {
		//1.验证当前用户是管理员账号 admin
		this.checkUserAdminRejectDel(userIds);
		//2.删除用户
		this.removeByIds(Arrays.asList(userIds.split(",")));
		return false;
	}

	@Override
	public SysUser getUserByName(String username) {
		SysUser sysUser = userMapper.getUserByName(username);
		//查询用户的租户ids
		if(sysUser!=null){
			List<Integer> list = userTenantMapper.getTenantIdsByUserId(sysUser.getId());
			if (oConvertUtils.isNotEmpty(list)) {
				sysUser.setRelTenantIds(StringUtils.join(list.toArray(), SymbolConstant.COMMA));
			} else {
				sysUser.setRelTenantIds("");
			}
		}
		return sysUser;
	}
	
	
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void addUserWithRole(SysUser user, String roles) {
		this.save(user);
		if(oConvertUtils.isNotEmpty(roles)) {
			String[] arr = roles.split(",");
			for (String roleId : arr) {
				SysUserRole userRole = new SysUserRole(user.getId(), roleId);
				sysUserRoleMapper.insert(userRole);
			}
		}
	}

	@Override
	@CacheEvict(value= {CacheConstant.SYS_USERS_CACHE}, allEntries=true)
	@Transactional(rollbackFor = Exception.class)
	public void editUserWithRole(SysUser user, String roles) {
		this.updateById(user);
		//先删后加
		sysUserRoleMapper.delete(new QueryWrapper<SysUserRole>().lambda().eq(SysUserRole::getUserId, user.getId()));
		if(oConvertUtils.isNotEmpty(roles)) {
			String[] arr = roles.split(",");
			for (String roleId : arr) {
				SysUserRole userRole = new SysUserRole(user.getId(), roleId);
				sysUserRoleMapper.insert(userRole);
			}
		}
	}


	@Override
	public List<String> getRole(String username) {
		return sysUserRoleMapper.getRoleByUserName(username);
	}

	/**
	 * 获取动态首页路由配置
	 *
	 * @param username
	 * @param version
	 * @return
	 */
	@Override
	public SysRoleIndex getDynamicIndexByUserRole(String username, String version) {
		SysRoleIndex roleIndex = new SysRoleIndex();
		//只有 X-Version=v3 的时候，才读取sys_role_index表获取角色首页配置
		boolean isV3 = CommonConstant.VERSION_V3.equals(version);
		if (isV3) {
			//1.先查询 用户USER级别 的所有首页配置
			if(oConvertUtils.isNotEmpty(username)){
				LambdaQueryWrapper<SysRoleIndex> routeIndexUserQuery = new LambdaQueryWrapper<>();
				//角色首页状态0：未开启  1：开启
				routeIndexUserQuery.eq(SysRoleIndex::getStatus, CommonConstant.STATUS_1);
				routeIndexUserQuery.eq(SysRoleIndex::getRelationType, CommonConstant.HOME_RELATION_USER);
				routeIndexUserQuery.eq(SysRoleIndex::getRoleCode, username);
				//优先级正序排序
				routeIndexUserQuery.orderByAsc(SysRoleIndex::getPriority);
				List<SysRoleIndex> list = sysRoleIndexService.list(routeIndexUserQuery);
				if (CollectionUtils.isNotEmpty(list)) {
					roleIndex = list.get(0);
				}else{
				   //2.用户没有配置，再查询 角色ROLE级别 的所有首页配置
					LambdaQueryWrapper<SysRoleIndex> routeIndexQuery = new LambdaQueryWrapper<>();
					//角色首页状态0：未开启  1：开启
					routeIndexQuery.eq(SysRoleIndex::getStatus, CommonConstant.STATUS_1);
					//角色所有首页配置
					routeIndexQuery.eq(SysRoleIndex::getRelationType, CommonConstant.HOME_RELATION_ROLE);
					//当前用户角色
					List<String> roles = sysUserRoleMapper.getRoleByUserName(username);
					String componentUrl = RoleIndexConfigEnum.getIndexByRoles(roles);
					roleIndex = new SysRoleIndex(componentUrl);
					//用户所有角色
					// 代码逻辑说明: [QQYUN-13187]【新用户登录报错】没有添加角色时 报错
					if(CollectionUtil.isNotEmpty(roles)){
						routeIndexQuery.in(SysRoleIndex::getRoleCode, roles);
					}
					//优先级正序排序
					routeIndexQuery.orderByAsc(SysRoleIndex::getPriority);
					list = sysRoleIndexService.list(routeIndexQuery);
					if (CollectionUtils.isNotEmpty(list)) {
						roleIndex = list.get(0);
					}
				}
			}
		}

		if (oConvertUtils.isEmpty(roleIndex.getComponent())) {
			if (isV3) {
				// 如果角色没有配置首页，则使用默认首页
				return sysRoleIndexService.queryDefaultIndex();
			} else {
				// 非v3返回null
				return null;
			}
		}
		return roleIndex;
	}

	/**
	 * 通过用户名获取用户角色集合
	 * @param username 用户名
     * @return 角色集合
	 */
	@Override
	public Set<String> getUserRolesSet(String username) {
		// 查询用户拥有的角色集合
		List<String> roles = sysUserRoleMapper.getRoleByUserName(username);
		log.info("-------通过数据库读取用户拥有的角色Rules------username： " + username + ",Roles size: " + (roles == null ? 0 : roles.size()));
		return new HashSet<>(roles);
	}
	
	/**
	 * 通过用户名获取用户角色集合
	 * @param userId 用户ID
     * @return 角色集合
	 */
	@Override
	public Set<String> getUserRoleSetById(String userId) {
		// 查询用户拥有的角色集合
		List<String> roles = sysUserRoleMapper.getRoleCodeByUserId(userId);
		log.info("-------通过数据库读取用户拥有的角色Rules------userId： " + userId + ",Roles size: " + (roles == null ? 0 : roles.size()));
		return new HashSet<>(roles);
	}

	/**
	 * 通过用户名获取用户权限集合
	 *
	 * @param userId 用户ID
	 * @return 权限集合
	 */
	@Override
	public Set<String> getUserPermissionsSet(String userId) {
		Set<String> permissionSet = new HashSet<>();
		List<SysPermission> permissionList = sysPermissionMapper.queryByUser(userId);
		//================= begin 开启租户的时候 如果没有test角色，默认加入test角色================
		if (MybatisPlusSaasConfig.OPEN_SYSTEM_TENANT_CONTROL) {
			if (permissionList == null) {
				permissionList = new ArrayList<>();
			}
			List<SysPermission> testRoleList = sysPermissionMapper.queryPermissionByTestRoleId();
			permissionList.addAll(testRoleList);
		}
		//================= end 开启租户的时候 如果没有test角色，默认加入test角色================
		for (SysPermission po : permissionList) {
//			// TODO URL规则有问题？
//			if (oConvertUtils.isNotEmpty(po.getUrl())) {
//				permissionSet.add(po.getUrl());
//			}
			if (oConvertUtils.isNotEmpty(po.getPerms())) {
				permissionSet.add(po.getPerms());
			}
		}
		log.info("-------通过数据库读取用户拥有的权限Perms------userId： "+ userId+",Perms size: "+ (permissionSet==null?0:permissionSet.size()) );
		return permissionSet;
	}

	/**
	 * 升级SpringBoot2.6.6,不允许循环依赖
	 * @author:qinfeng
	 * @update: 2022-04-07
	 * @param username
	 * @return
	 */
	@Override
	public SysUserCacheInfo getCacheUser(String username) {
		SysUserCacheInfo info = new SysUserCacheInfo();
		info.setOneDepart(true);
		if(oConvertUtils.isEmpty(username)) {
			return null;
		}

		//查询用户信息
		SysUser sysUser = userMapper.getUserByName(username);
		if(sysUser!=null) {
			info.setSysUserCode(sysUser.getUsername());
			info.setSysUserName(sysUser.getRealname());
			info.setSysOrgCode(sysUser.getOrgCode());
		}
		
		//多部门支持in查询
		List<SysDepart> list = sysDepartMapper.queryUserDeparts(sysUser.getId());
		List<String> sysMultiOrgCode = new ArrayList<String>();
		if(list==null || list.size()==0) {
			//当前用户无部门
			//sysMultiOrgCode.add("0");
		}else if(list.size()==1) {
			sysMultiOrgCode.add(list.get(0).getOrgCode());
		}else {
			info.setOneDepart(false);
			for (SysDepart dpt : list) {
				sysMultiOrgCode.add(dpt.getOrgCode());
			}
		}
		info.setSysMultiOrgCode(sysMultiOrgCode);
		
		return info;
	}

    /**
     * 根据部门Id查询
     * @param page
     * @param departId 部门id
     * @param username 用户账户名称
     * @return
     */
	@Override
	public IPage<SysUser> getUserByDepId(Page<SysUser> page, String departId,String username) {
		return userMapper.getUserByDepId(page, departId,username);
	}

	@Override
	public IPage<SysUser> getUserByDepIds(Page<SysUser> page, List<String> departIds, String username) {
		return userMapper.getUserByDepIds(page, departIds,username);
	}

	@Override
	public Map<String, String> getDepNamesByUserIds(List<String> userIds) {
		List<SysUserDepVo> list = this.baseMapper.getDepNamesByUserIds(userIds);

		Map<String, String> res = new HashMap(5);
		list.forEach(item -> {
					if (res.get(item.getUserId()) == null) {
						res.put(item.getUserId(), item.getDepartName());
					} else {
						res.put(item.getUserId(), res.get(item.getUserId()) + "," + item.getDepartName());
					}
				}
		);
		return res;
	}

/*	@Override
	public IPage<SysUser> getUserByDepartIdAndQueryWrapper(Page<SysUser> page, String departId, QueryWrapper<SysUser> queryWrapper) {
		LambdaQueryWrapper<SysUser> lambdaQueryWrapper = queryWrapper.lambda();

		lambdaQueryWrapper.eq(SysUser::getDelFlag, CommonConstant.DEL_FLAG_0);
        lambdaQueryWrapper.inSql(SysUser::getId, "SELECT user_id FROM sys_user_depart WHERE dep_id = '" + departId + "'");

        return userMapper.selectPage(page, lambdaQueryWrapper);
	}*/

	@Override
	public IPage<SysUserSysDepartModel> queryUserByOrgCode(String orgCode, SysUser userParams, IPage page) {
		List<SysUserSysDepartModel> list = baseMapper.getUserByOrgCode(page, orgCode, userParams);
		//根据部门orgCode查询部门，需要将职位id进行传递
		for (SysUserSysDepartModel model:list) {
			List<String> positionList = sysUserPositionMapper.getPositionIdByUserId(model.getId());
			model.setPost(CommonUtils.getSplitText(positionList,SymbolConstant.COMMA));
		}
		Integer total = baseMapper.getUserByOrgCodeTotal(orgCode, userParams);

		IPage<SysUserSysDepartModel> result = new Page<>(page.getCurrent(), page.getSize(), total);
		result.setRecords(list);

		return result;
	}

    /**
     * 根据角色Id查询
     * @param page
     * @param roleId 角色id
     * @param username 用户账户名称
     * @param realname 用户姓名
     * @return
     */
	@Override
	public IPage<SysUser> getUserByRoleId(Page<SysUser> page, String roleId, String username, String realname) {

		IPage<SysUser> userRoleList = userMapper.getUserByRoleId(page, roleId, username,realname);
		List<SysUser> records = userRoleList.getRecords();
		if (null != records && records.size() > 0) {
			List<String> userIds = records.stream().map(SysUser::getId).collect(Collectors.toList());
			Map<String, String> useDepNames = this.getDepNamesByUserIds(userIds);
			for (SysUser sysUser : userRoleList.getRecords()) {
				//设置部门
				sysUser.setOrgCodeTxt(useDepNames.get(sysUser.getId()));
				//设置用户职位id
				this.userPositionId(sysUser);
			}
		}
		return userRoleList;
	}


	@Override
	@CacheEvict(value= {CacheConstant.SYS_USERS_CACHE}, key="#username")
	public void updateUserDepart(String username,String orgCode,Integer loginTenantId) {
		baseMapper.updateUserDepart(username, orgCode,loginTenantId);
	}


	@Override
	public SysUser getUserByPhone(String phone) {
		return userMapper.getUserByPhone(phone);
	}


	@Override
	public SysUser getUserByEmail(String email) {
		return userMapper.getUserByEmail(email);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void addUserWithDepart(SysUser user, String selectedParts) {
//		this.save(user);  //保存角色的时候已经添加过一次了
		if(oConvertUtils.isNotEmpty(selectedParts)) {
			String[] arr = selectedParts.split(",");
			for (String deaprtId : arr) {
				SysUserDepart userDeaprt = new SysUserDepart(user.getId(), deaprtId);
				sysUserDepartMapper.insert(userDeaprt);
			}
		}
	}


	@Override
	@Transactional(rollbackFor = Exception.class)
	@CacheEvict(value={CacheConstant.SYS_USERS_CACHE}, allEntries=true)
	public void editUserWithDepart(SysUser user, String departs) {
        //更新角色的时候已经更新了一次了，可以再跟新一次
		this.updateById(user);
		String[] arr = {};
		if(oConvertUtils.isNotEmpty(departs)){
			arr = departs.split(",");
		}
		//查询已关联部门
		List<SysUserDepart> userDepartList = sysUserDepartMapper.selectList(new QueryWrapper<SysUserDepart>().lambda().eq(SysUserDepart::getUserId, user.getId()));
		if(userDepartList != null && userDepartList.size()>0){
			for(SysUserDepart depart : userDepartList ){
				//修改已关联部门删除部门用户角色关系
				if(!Arrays.asList(arr).contains(depart.getDepId())){
					List<SysDepartRole> sysDepartRoleList = sysDepartRoleMapper.selectList(
							new QueryWrapper<SysDepartRole>().lambda().eq(SysDepartRole::getDepartId,depart.getDepId()));
					List<String> roleIds = sysDepartRoleList.stream().map(SysDepartRole::getId).collect(Collectors.toList());
					if(roleIds != null && roleIds.size()>0){
						departRoleUserMapper.delete(new QueryWrapper<SysDepartRoleUser>().lambda().eq(SysDepartRoleUser::getUserId, user.getId())
								.in(SysDepartRoleUser::getDroleId,roleIds));
					}
				}
			}
		}
		//先删后加
		sysUserDepartMapper.delete(new QueryWrapper<SysUserDepart>().lambda().eq(SysUserDepart::getUserId, user.getId()));
		if(oConvertUtils.isNotEmpty(departs)) {
			for (String departId : arr) {
				SysUserDepart userDepart = new SysUserDepart(user.getId(), departId);
				sysUserDepartMapper.insert(userDepart);
			}
		}
	}


	/**
	   * 校验用户是否有效
	 * @param sysUser
	 * @return
	 */
	@Override
	public Result<?> checkUserIsEffective(SysUser sysUser) {
		Result<?> result = new Result<Object>();
		//情况1：根据用户信息查询，该用户不存在
		if (sysUser == null) {
			result.error500("该用户不存在，请注册");
			baseCommonService.addLog("用户登录失败，用户不存在！", CommonConstant.LOG_TYPE_1, null);
			return result;
		}
		//情况2：根据用户信息查询，该用户已注销
		// 代码逻辑说明: if条件永远为falsebug------------
		if (CommonConstant.DEL_FLAG_1.equals(sysUser.getDelFlag())) {
			baseCommonService.addLog("用户登录失败，用户名:" + sysUser.getUsername() + "已注销！", CommonConstant.LOG_TYPE_1, null);
			result.error500("该用户已注销");
			return result;
		}
		//情况3：根据用户信息查询，该用户已冻结
		if (CommonConstant.USER_FREEZE.equals(sysUser.getStatus())) {
			baseCommonService.addLog("用户登录失败，用户名:" + sysUser.getUsername() + "已冻结！", CommonConstant.LOG_TYPE_1, null);
			result.error500("该用户已冻结");
			return result;
		}
		return result;
	}

	@Override
	public List<SysUser> queryLogicDeleted() {
        // 代码逻辑说明: 回收站查询未离职的------------
        LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.ne(SysUser::getStatus, CommonConstant.USER_QUIT);
        return this.queryLogicDeleted(wrapper);
    }

	@Override
	public List<SysUser> queryLogicDeleted(LambdaQueryWrapper<SysUser> wrapper) {
		if (wrapper == null) {
			wrapper = new LambdaQueryWrapper<>();
		}
		wrapper.eq(SysUser::getDelFlag, CommonConstant.DEL_FLAG_1);
		return userMapper.selectLogicDeleted(wrapper);
	}

	@Override
	@CacheEvict(value={CacheConstant.SYS_USERS_CACHE}, allEntries=true)
	public boolean revertLogicDeleted(List<String> userIds, SysUser updateEntity) {
		return userMapper.revertLogicDeleted(userIds, updateEntity) > 0;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public boolean removeLogicDeleted(List<String> userIds) {
		// 1. 删除用户
		int line = userMapper.deleteLogicDeleted(userIds);
		// 2. 删除用户部门关系
		line += sysUserDepartMapper.delete(new LambdaQueryWrapper<SysUserDepart>().in(SysUserDepart::getUserId, userIds));
		//3. 删除用户角色关系
		line += sysUserRoleMapper.delete(new LambdaQueryWrapper<SysUserRole>().in(SysUserRole::getUserId, userIds));
		//4.同步删除第三方App的用户
		try {
			dingtalkService.removeThirdAppUser(userIds);
			wechatEnterpriseService.removeThirdAppUser(userIds);
		} catch (Exception e) {
			log.error("同步删除第三方App的用户失败：", e);
		}
		//5. 删除第三方用户表（因为第4步需要用到第三方用户表，所以在他之后删）
		line += sysThirdAccountMapper.delete(new LambdaQueryWrapper<SysThirdAccount>().in(SysThirdAccount::getSysUserId, userIds));

		//6. 删除租户用户中间表的数据
		line += userTenantMapper.delete(new LambdaQueryWrapper<SysUserTenant>().in(SysUserTenant::getUserId,userIds));
		
		return line != 0;
	}

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateNullPhoneEmail() {
        userMapper.updateNullByEmptyString("email");
        userMapper.updateNullByEmptyString("phone");
        return true;
    }

	@Override
	public void saveThirdUser(SysUser sysUser) {
		//保存用户
		String userid = UUIDGenerator.generate();
		sysUser.setId(userid);
		baseMapper.insert(sysUser);
		//获取第三方角色
		SysRole sysRole = sysRoleMapper.selectOne(new LambdaQueryWrapper<SysRole>().eq(SysRole::getRoleCode, "third_role"));
		//保存用户角色
		SysUserRole userRole = new SysUserRole();
		userRole.setRoleId(sysRole.getId());
		userRole.setUserId(userid);
		sysUserRoleMapper.insert(userRole);
	}

	@Override
	public List<SysUser> queryByDepIds(List<String> departIds, String username) {
		return userMapper.queryByDepIds(departIds,username);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void saveUser(SysUser user, String selectedRoles, String selectedDeparts, String relTenantIds, boolean izSyncPack) {
        if(null == user.getSort()){
            user.setSort(CommonConstant.DEFAULT_USER_SORT);
        }
        //step.1 保存用户
		this.save(user);
		//获取用户保存前台传过来的租户id并添加到租户
        this.saveUserTenant(user.getId(),relTenantIds, izSyncPack);
		//step.2 保存角色
		if(oConvertUtils.isNotEmpty(selectedRoles)) {
			String[] arr = selectedRoles.split(",");
			for (String roleId : arr) {
				SysUserRole userRole = new SysUserRole(user.getId(), roleId);
				sysUserRoleMapper.insert(userRole);
			}
		}
		
		//step.3 保存所属部门
		if(oConvertUtils.isNotEmpty(selectedDeparts)) {
			String[] arr = selectedDeparts.split(",");
			for (String deaprtId : arr) {
				SysUserDepart userDeaprt = new SysUserDepart(user.getId(), deaprtId);
				sysUserDepartMapper.insert(userDeaprt);
			}
		}

		//step.4 保存职位
		this.saveUserPosition(user.getId(),user.getPost());
        //step5 保存兼职岗位
        this.saveUserOtherDepPost(user.getId(),user.getOtherDepPostId());
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	@CacheEvict(value={CacheConstant.SYS_USERS_CACHE}, allEntries=true)
	public void editUser(SysUser user, String roles, String departs, String relTenantIds, String updateFromPage) {
		//获取用户编辑前台传过来的租户id
        this.editUserTenants(user.getId(),relTenantIds);
        if(null == user.getSort()){
            user.setSort(CommonConstant.DEFAULT_USER_SORT);
        }
		//step.1 修改用户基础信息
		this.updateById(user);
		//step.2 修改角色
		if (oConvertUtils.isEmpty(updateFromPage) || !"deptUsers".equalsIgnoreCase(updateFromPage)) {
			// 处理用户角色 先删后加 , 如果是在部门用户页面修改用户,不处理用户角色,因为该页面无法编辑用户角色.
			sysUserRoleMapper.delete(new QueryWrapper<SysUserRole>().lambda().eq(SysUserRole::getUserId, user.getId()));
			if (oConvertUtils.isNotEmpty(roles)) {
				String[] arr = roles.split(",");
				for (String roleId : arr) {
					SysUserRole userRole = new SysUserRole(user.getId(), roleId);
					sysUserRoleMapper.insert(userRole);
				}
			}
		}

		//step.3 修改部门
		String[] arr = {};
		if(oConvertUtils.isNotEmpty(departs)){
			arr = departs.split(",");
		}
		//查询已关联部门
		List<SysUserDepart> userDepartList = sysUserDepartMapper.selectList(new QueryWrapper<SysUserDepart>().lambda().eq(SysUserDepart::getUserId, user.getId()));
		if(userDepartList != null && userDepartList.size()>0){
			for(SysUserDepart depart : userDepartList ){
				//修改已关联部门删除部门用户角色关系
				if(!Arrays.asList(arr).contains(depart.getDepId())){
					List<SysDepartRole> sysDepartRoleList = sysDepartRoleMapper.selectList(
							new QueryWrapper<SysDepartRole>().lambda().eq(SysDepartRole::getDepartId,depart.getDepId()));
					List<String> roleIds = sysDepartRoleList.stream().map(SysDepartRole::getId).collect(Collectors.toList());
					if(roleIds != null && roleIds.size()>0){
						departRoleUserMapper.delete(new QueryWrapper<SysDepartRoleUser>().lambda().eq(SysDepartRoleUser::getUserId, user.getId())
								.in(SysDepartRoleUser::getDroleId,roleIds));
					}
				}
			}
		}
		//先删后加
		sysUserDepartMapper.delete(new QueryWrapper<SysUserDepart>().lambda().eq(SysUserDepart::getUserId, user.getId()));
		if(oConvertUtils.isNotEmpty(departs)) {
			for (String departId : arr) {
				SysUserDepart userDepart = new SysUserDepart(user.getId(), departId);
				sysUserDepartMapper.insert(userDepart);
			}
		}
		//step.4 修改手机号和邮箱
		// 更新手机号、邮箱空字符串为 null
		userMapper.updateNullByEmptyString("email");
		userMapper.updateNullByEmptyString("phone");

		//step.5 修改职位
		this.editUserPosition(user.getId(),user.getPost());

        //代码逻辑说明: 兼职岗位改造成中间表的方式---
        //step6 修改兼职岗位
        //先删后加
        depPostMapper.delete(new QueryWrapper<SysUserDepPost>().lambda().eq(SysUserDepPost::getUserId, user.getId()));
        this.saveUserOtherDepPost(user.getId(),user.getOtherDepPostId());
	}


    /**
     * 保存兼职岗位
     *
     * @param userId
     * @param otherDepPostId
     */
    private void saveUserOtherDepPost(String userId, String otherDepPostId) {
        if (oConvertUtils.isNotEmpty(otherDepPostId)) {
            String[] depPostId = otherDepPostId.split(SymbolConstant.COMMA);
            for (String postId : depPostId) {
                SysUserDepPost userPosition = new SysUserDepPost(userId, postId);
                depPostMapper.insert(userPosition);
            }
        }
    }

	@Override
	public List<String> userIdToUsername(Collection<String> userIdList) {
		LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.in(SysUser::getId, userIdList);
		List<SysUser> userList = super.list(queryWrapper);
		return userList.stream().map(SysUser::getUsername).collect(Collectors.toList());
	}

	@Override
	@Cacheable(cacheNames=CacheConstant.SYS_USERS_CACHE, key="#username")
	@SensitiveEncode
	public LoginUser getEncodeUserInfo(String username){
		if(oConvertUtils.isEmpty(username)) {
			return null;
		}
		LoginUser loginUser = new LoginUser();
		SysUser sysUser = userMapper.getUserByName(username);
		//查询用户的租户ids
		this.setUserTenantIds(sysUser);
		//设置职位id
		this.userPositionId(sysUser);
		if(sysUser==null) {
			return null;
		}
		BeanUtils.copyProperties(sysUser, loginUser);
		// 查询当前登录用户的部门id
		loginUser.setOrgId(this.getDepartIdByOrCode(sysUser.getOrgCode()));
		// 查询当前登录用户的角色code（多个逗号分割）
		loginUser.setRoleCode(this.getJoinRoleCodeByUserId(sysUser.getId()));
		return loginUser;
	}

    @Override
    @CacheEvict(value={CacheConstant.SYS_USERS_CACHE}, allEntries=true)
    @Transactional(rollbackFor = Exception.class)
    public void userQuit(String username) {
        SysUser sysUser = userMapper.getUserByName(username);
        if(null == sysUser){
            throw new JeecgBootException("离职失败，该用户已不存在");
        }
		// 代码逻辑说明: [QQYUN-3951]租户用户离职重构------------
		int tenantId = oConvertUtils.getInt(TenantContext.getTenant(), 0);
		//更新用户租户表的状态为离职状态
		if(tenantId==0){
			throw new JeecgBootException("离职失败，租户不存在");
		}
		LambdaQueryWrapper<SysUserTenant> query = new LambdaQueryWrapper<>();
		query.eq(SysUserTenant::getUserId,sysUser.getId());
		query.eq(SysUserTenant::getTenantId,tenantId);
		SysUserTenant userTenant = new SysUserTenant();
		userTenant.setStatus(CommonConstant.USER_TENANT_QUIT);
		userTenantMapper.update(userTenant,query);
    }

    @Override
    public List<SysUser> getQuitList(Integer tenantId) {
        return userMapper.getTenantQuitList(tenantId);
    }

    @Override
    public void updateStatusAndFlag(List<String> userIds, SysUser sysUser) {
        userMapper.updateStatusAndFlag(userIds,sysUser);
    }

	/**
	 * 设置登录租户
	 * @param sysUser
	 * @return
	 */
	@Override
	public Result<JSONObject>  setLoginTenant(SysUser sysUser, JSONObject obj, String username, Result<JSONObject> result){
		//用户有哪些租户
//		List<SysTenant> tenantList = null;
		// 代码逻辑说明: [QQYUN-3371]租户逻辑改造，改成关系表
		List<SysTenant> tenantList = relationMapper.getTenantNoCancel(sysUser.getId());
		obj.put("tenantList", tenantList);
//		if (null!=tenantIdList && tenantIdList.size()>0) {
//			//-------------------------------------------------------------------------------------
//			//查询有效的租户集合
//			LambdaQueryWrapper<SysTenant> queryWrapper = new LambdaQueryWrapper<>();
//			queryWrapper.in(SysTenant::getId, tenantIdList);
//			queryWrapper.eq(SysTenant::getStatus, Integer.valueOf(CommonConstant.STATUS_1));
//			tenantList = sysTenantMapper.selectList(queryWrapper);
//			//-------------------------------------------------------------------------------------
//
//			if (tenantList.size() == 0) {
//				return result.error500("与该用户关联的租户均已被冻结，无法登录！");
//			} else {
//				obj.put("tenantList", tenantList);
//			}
//		}


		//登录会话租户ID，有效性重置
		if (tenantList != null && tenantList.size() > 0) {
			if (tenantList.size() == 1) {
				sysUser.setLoginTenantId(tenantList.get(0).getId());
			} else {
				List<SysTenant> listAfterFilter = tenantList.stream().filter(s -> s.getId().equals(sysUser.getLoginTenantId())).collect(Collectors.toList());
				if (listAfterFilter == null || listAfterFilter.size() == 0) {
					//如果上次登录租户ID，在用户拥有的租户集合里面没有了，则随机取用户拥有的第一个租户ID
					sysUser.setLoginTenantId(tenantList.get(0).getId());
				}
			}
		} else {
			//无租户的时候，设置为 0
			sysUser.setLoginTenantId(0);
		}
		//设置用户登录缓存租户
		this.updateUserDepart(username, null,sysUser.getLoginTenantId());
		log.debug(" 登录接口用户的租户ID = {}", sysUser.getLoginTenantId());
		if(sysUser.getLoginTenantId()!=null){
			//登录的时候需要手工设置下会话中的租户ID,不然登录接口无法通过租户隔离查询到数据
			TenantContext.setTenant(sysUser.getLoginTenantId()+"");
		}
		return null;
	}


    /**
     * 获取租户id
     * @param sysUser
     */
    private void setUserTenantIds(SysUser sysUser) {
		if(ObjectUtils.isNotEmpty(sysUser)) {
			List<Integer> list  = relationMapper.getTenantIdsNoStatus(sysUser.getId());
			if(null!=list && list.size()>0){
				sysUser.setRelTenantIds(StringUtils.join(list.toArray(), ","));
			}else{
				sysUser.setRelTenantIds("");
			}
		}
    }

    /**
     * 保存租户
     *
     * @param userId
     * @param relTenantIds
     * @param izSyncPack 是否需要将用户同步当前产品包下
     */
    private void saveUserTenant(String userId, String relTenantIds, boolean izSyncPack) {
        if (oConvertUtils.isNotEmpty(relTenantIds)) {
            String[] tenantIds = relTenantIds.split(SymbolConstant.COMMA);
            for (String tenantId : tenantIds) {
                SysUserTenant relation = new SysUserTenant();
                relation.setUserId(userId);
                relation.setTenantId(Integer.valueOf(tenantId));
                relation.setStatus(CommonConstant.STATUS_1);
                
				LambdaQueryWrapper sysUserTenantQueryWrapper = new LambdaQueryWrapper<SysUserTenant>()
						.eq(SysUserTenant::getUserId, userId)
						.eq(SysUserTenant::getTenantId,Integer.valueOf(tenantId));
				SysUserTenant tenantPresent = relationMapper.selectOne(sysUserTenantQueryWrapper);
				if (tenantPresent != null) {
					tenantPresent.setStatus(CommonConstant.STATUS_1);
					relationMapper.updateById(tenantPresent);
				}else{
					relationMapper.insert(relation);
                    ISysTenantService currentService = SpringContextUtils.getApplicationContext().getBean(ISysTenantService.class);
                    //默认添加当前用户到租户套餐中
                    currentService.addPackUser(userId,tenantId);
				}
            }
        }else{
			//是否开启系统管理模块的多租户数据隔离【SAAS多租户模式】
			if (MybatisPlusSaasConfig.OPEN_SYSTEM_TENANT_CONTROL) {
				// 代码逻辑说明: 判断当前用户是否在当前租户里面，如果不存在在新增------------
				String tenantId = TenantContext.getTenant();
				if(oConvertUtils.isNotEmpty(tenantId)){
					Integer count = relationMapper.userTenantIzExist(userId, Integer.parseInt(tenantId));
					if(count == 0){
						SysUserTenant relation = new SysUserTenant();
						relation.setUserId(userId);
						relation.setTenantId(Integer.parseInt(tenantId));
						relation.setStatus(CommonConstant.STATUS_1);
						relationMapper.insert(relation);
                        if(izSyncPack){
                            ISysTenantService currentService = SpringContextUtils.getApplicationContext().getBean(ISysTenantService.class);
                            //自动为用户，添加租户下所有套餐
                            currentService.addPackUser(userId,tenantId);
                        }
					}
				}
			}
		}
    }

    /**
     * 编辑租户
     * @param userId
     * @param relTenantIds
     */
    private void editUserTenants(String userId, String relTenantIds) {
        LambdaQueryWrapper<SysUserTenant> query = new LambdaQueryWrapper<>();
        query.eq(SysUserTenant::getUserId, userId);
        //数据库的租户id
		List<Integer> oldTenantIds = relationMapper.getTenantIdsByUserId(userId);
        //如果传过来的租户id为空，那么就删除租户
        if (oConvertUtils.isEmpty(relTenantIds) && CollectionUtils.isNotEmpty(oldTenantIds)) {
            this.deleteTenantByUserId(userId, null);
        } else if (oConvertUtils.isNotEmpty(relTenantIds) && CollectionUtils.isEmpty(oldTenantIds)) {
            //如果传过来的租户id不为空但是数据库的租户id为空，那么就新增
            this.saveUserTenant(userId, relTenantIds, false);
        } else {
			//都不为空，需要比较，进行添加或删除
			if(oConvertUtils.isNotEmpty(relTenantIds) && CollectionUtils.isNotEmpty(oldTenantIds)){
				//找到新的租户id与原来的租户id不同之处，进行删除
				String[] relTenantIdArray = relTenantIds.split(SymbolConstant.COMMA);
				List<String> relTenantIdList = Arrays.asList(relTenantIdArray);
				
				List<Integer> deleteTenantIdList = oldTenantIds.stream().filter(item -> !relTenantIdList.contains(item.toString())).collect(Collectors.toList());
				for (Integer tenantId : deleteTenantIdList) {
					this.deleteTenantByUserId(userId, tenantId);
				}
				//找到原来租户的用户id与新的租户id不同之处，进行新增
				String tenantIds = relTenantIdList.stream().filter(item -> !oldTenantIds.contains(Integer.valueOf(item))).collect(Collectors.joining(","));
				this.saveUserTenant(userId, tenantIds, false);
			}
        }
    }

    /**
     * 删除租户通过用户id
     * @param tenantId
     * @param userId
     */
    private void deleteTenantByUserId(String userId,Integer tenantId){
        LambdaQueryWrapper<SysUserTenant> query = new LambdaQueryWrapper<>();
        query.eq(SysUserTenant::getUserId, userId);
        if(oConvertUtils.isNotEmpty(tenantId)){
            query.eq(SysUserTenant::getTenantId, tenantId);
        }
        relationMapper.delete(query);
        //删除产品包用户关联
        LambdaQueryWrapper<SysTenantPackUser> packUserQuery = new LambdaQueryWrapper<>();
        packUserQuery.eq(SysTenantPackUser::getUserId, userId);
        if(oConvertUtils.isNotEmpty(tenantId)){
            packUserQuery.eq(SysTenantPackUser::getTenantId, tenantId);
        }
        packUserMapper.delete(packUserQuery);
    }



	@Override
	public void batchEditUsers(JSONObject json) {
		String userIds = json.getString("userIds");
		List<String> idList = JSONArray.parseArray(userIds, String.class);
		//部门
		String selecteddeparts = json.getString("selecteddeparts");
		//职位
		String post = json.getString("post");
		//工作地点? 没有这个字段
		String workAddress = json.getString("workAddress");
		//批量修改用户职位
		if(oConvertUtils.isNotEmpty(post)) {
			//修改职位用户关系表
			for (String userId:idList) {
				this.editUserPosition(userId,post);
			}
		}
		if(oConvertUtils.isNotEmpty(selecteddeparts)) {
			//查询当前租户的部门列表
			Integer currentTenantId = oConvertUtils.getInt(TenantContext.getTenant(), 0);
			LambdaQueryWrapper<SysDepart> departQuery = new LambdaQueryWrapper<SysDepart>()
					.eq(SysDepart::getTenantId, currentTenantId);
			List<SysDepart> departList = sysDepartMapper.selectList(departQuery);
			if(departList==null || departList.size()==0){
				log.error("batchEditUsers 根据租户ID没有找到部门>"+currentTenantId);
				return;
			}
			List<String> departIdList = new ArrayList<String>();
			for(SysDepart depart: departList){
				if(depart!=null){
					String id = depart.getId();
					if(oConvertUtils.isNotEmpty(id)){
						departIdList.add(id);
					}
				}
			}
			//删除人员的部门关联
			LambdaQueryWrapper<SysUserDepart> query = new LambdaQueryWrapper<SysUserDepart>()
					.in(SysUserDepart::getUserId, idList)
					.in(SysUserDepart::getDepId, departIdList);
			sysUserDepartMapper.delete(query);
			
			String[] arr = selecteddeparts.split(",");
			
			//再新增
			for (String deaprtId : arr) {
				for(String userId: idList){
					SysUserDepart userDepart = new SysUserDepart(userId, deaprtId);
					sysUserDepartMapper.insert(userDepart);
				}
			}
		}
	}

	@Override
	public DepartAndUserInfo searchByKeyword(String keyword) {
		DepartAndUserInfo departAndUserInfo = new DepartAndUserInfo();
		if(oConvertUtils.isNotEmpty(keyword)){
			LambdaQueryWrapper<SysUser> query1 = new LambdaQueryWrapper<SysUser>()
					.like(SysUser::getRealname, keyword);
			String str = oConvertUtils.getString(TenantContext.getTenant(), "0");
			Integer tenantId = Integer.valueOf(str);
			if(MybatisPlusSaasConfig.OPEN_SYSTEM_TENANT_CONTROL){
				List<String> userIds = userTenantMapper.getUserIdsByTenantId(tenantId);
				if (oConvertUtils.listIsNotEmpty(userIds)) {
					query1.in(SysUser::getId, userIds);
				}else{
					query1.eq(SysUser::getId, "");
				}
			}
			List<SysUser> list1 = this.baseMapper.selectList(query1);
			if(list1!=null && list1.size()>0){
				List<UserAvatar> userList = list1.stream().map(v -> new UserAvatar(v)).collect(Collectors.toList());
				departAndUserInfo.setUserList(userList);
			}

			LambdaQueryWrapper<SysDepart> query2 = new LambdaQueryWrapper<SysDepart>()
					.like(SysDepart::getDepartName, keyword);
			if(MybatisPlusSaasConfig.OPEN_SYSTEM_TENANT_CONTROL){
				query2.eq(SysDepart::getTenantId, tenantId);
			}
			List<SysDepart> list2 = sysDepartMapper.selectList(query2);
			if(list2!=null && list2.size()>0){
				List<DepartInfo> departList = new ArrayList<>();
				for(SysDepart depart: list2){
					List<String> orgName = new ArrayList<>();
					List<String> orgId = new ArrayList<>();
					getParentDepart(depart, orgName, orgId);
					DepartInfo departInfo = new DepartInfo();
					departInfo.setId(depart.getId());
					departInfo.setOrgId(orgId);
					departInfo.setOrgName(orgName);
					departList.add(departInfo);
				}
				departAndUserInfo.setDepartList(departList);
			}
		}
		return departAndUserInfo;
	}

	@Override
	public UpdateDepartInfo getUpdateDepartInfo(String departId) {
		SysDepart depart = sysDepartMapper.selectById(departId);
		if(depart!=null){
			UpdateDepartInfo info = new UpdateDepartInfo(depart);
			List<SysDepart> subList = sysDepartMapper.queryDeptByPid(departId);
			if(subList!=null && subList.size()>0){
				info.setHasSub(true);
			}
			//获取部门负责人信息
			LambdaQueryWrapper<SysUser> query = new LambdaQueryWrapper<SysUser>()
					.eq(SysUser::getUserIdentity, 2)
					.like(SysUser::getDepartIds, depart.getId());
			List<SysUser> userList = this.baseMapper.selectList(query);
			if(userList!=null && userList.size()>0){
				List<String> idList = userList.stream().map(i -> i.getId()).collect(Collectors.toList());
				info.setChargePersonList(idList);
			}
			return info;
		}
		return null;
	}

	@Override
	public void doUpdateDepartInfo(UpdateDepartInfo info) {
		String departId = info.getDepartId();
		SysDepart depart = sysDepartMapper.selectById(departId);
		if(depart!=null){
			//修改部门信息-上级和部门名称
			if(!depart.getParentId().equals(info.getParentId())){
				String pid = info.getParentId();
				SysDepart parentDepart = sysDepartMapper.selectById(pid);
				if(parentDepart!=null){
					String orgCode = getNextOrgCode(pid);
					depart.setOrgCode(orgCode);
					depart.setParentId(pid);
				}
			}
			depart.setDepartName(info.getDepartName());
			sysDepartMapper.updateById(depart);
			//先查询这个部门的负责人
			List<SysUser> departChargeUsers = queryDepartChargePersons(departId);
			List<String> departChargeUserIdList = departChargeUsers.stream().map(i -> i.getId()).collect(Collectors.toList());
			//修改部门负责人
			List<String> userIdList = info.getChargePersonList();
			if(userIdList!=null && userIdList.size()>0){
				for(String userId: userIdList){
					SysUser user = this.baseMapper.selectById(userId);
					if(user!=null){
						departChargeUserIdList.remove(user.getId());
						user.setUserIdentity(2);
						String departIds = user.getDepartIds();
						if(oConvertUtils.isEmpty(departIds)){
							user.setDepartIds(departId);
						}else{
							List<String> list = new ArrayList<String>(Arrays.asList(departIds.split(",")));
							if(list.indexOf(departId)>=0){
								continue;
							}else{
								list.add(departId);
								String newDepartIds = String.join(",", list);
								user.setDepartIds(newDepartIds);
							}
						}
						this.baseMapper.updateById(user);
					}
				}
			// 代码逻辑说明: 部门负责人不能被删除------------
				this.removeDepartmentManager(departChargeUserIdList,departChargeUsers,departId);
			}else{
				if(CollectionUtil.isNotEmpty(departChargeUsers)){
					//前端传过来用户列表id为空，说明数据库的负责部门人员均需要删除
					this.removeDepartmentManager(departChargeUserIdList,departChargeUsers,departId);
				}
				
			}
		}
	}

	private List<SysUser> queryDepartChargePersons(String departId){
    	List<SysUser> result = new ArrayList<>();
		// 代码逻辑说明: 部门负责人不能被删除------------
		LambdaQueryWrapper<SysUser> userQuery = new LambdaQueryWrapper<>();
		userQuery.like(SysUser::getDepartIds,departId);
		List<SysUser> userList = userMapper.selectList(userQuery);
		if(userList!=null && userList.size()>0){
			for(SysUser user: userList){
				Integer identity = user.getUserIdentity();
				String deps = user.getDepartIds();
				if(identity!=null && identity==2){
					if(oConvertUtils.isNotEmpty(deps)){
						if(deps.indexOf(departId)>=0){
							result.add(user);
						}
					}
				}
			}
		}
    	return result;
	}
	
	/**
	 * 变更父级部门 修改编码
	 * @param parentId
	 * @return
	 */
	private String getNextOrgCode(String parentId){
		JSONObject formData = new JSONObject();
		formData.put("parentId",parentId);
		String[] codeArray = (String[]) FillRuleUtil.executeRule(FillRuleConstant.DEPART, formData);
		return codeArray[0];
	}

	@Override
	public void changeDepartChargePerson(JSONObject json) {
		String userId = json.getString("userId");
		String departId = json.getString("departId");
		boolean status  = json.getBoolean("status");
		SysUser user = this.getById(userId);
		if(user!=null){
			String ids = user.getDepartIds();
			if(status==true){
				//设置部门负责人
				if(oConvertUtils.isEmpty(ids)){
					//设置为上级
					user.setUserIdentity(CommonConstant.USER_IDENTITY_2);
					user.setDepartIds(departId);
				}else{
					List<String> list = new ArrayList<String>(Arrays.asList(ids.split(",")));
					if(list.indexOf(departId)>=0){
						//啥也不干
					}else{
						list.add(departId);
						String newIds = String.join(",", list);
						//设置为上级
						user.setUserIdentity(CommonConstant.USER_IDENTITY_2);
						user.setDepartIds(newIds);
					}
				}
			}else{
				// 取消负责人
				if(oConvertUtils.isNotEmpty(ids)){
					List<String> list = new ArrayList<String>();
					for(String temp: ids.split(",")){
						if(oConvertUtils.isEmpty(temp)){
							continue;
						}
						if(!temp.equals(departId)){
							list.add(temp);
						}
					}
					String newIds = "";
					if(list.size()>0){
						newIds = String.join(",", list);
					}else{
						//负责部门为空时，说明已经是普通用户
						user.setUserIdentity(CommonConstant.USER_IDENTITY_1);
					}
					user.setDepartIds(newIds);
				}
			}
			this.updateById(user);
		}
	}

	/**
	 * 找上级部门
	 * @param depart
	 * @param orgName
	 * @param orgId
	 */
	private void getParentDepart(SysDepart depart,List<String> orgName,List<String> orgId){
		String pid = depart.getParentId();
		orgName.add(0, depart.getDepartName());
		orgId.add(0, depart.getId());
		if(oConvertUtils.isNotEmpty(pid)){
			SysDepart temp = sysDepartMapper.selectById(pid);
			getParentDepart(temp, orgName, orgId);
		}
	}
	
	@Override
	@Transactional(rollbackFor = Exception.class)
	@CacheEvict(value={CacheConstant.SYS_USERS_CACHE}, allEntries=true)
	public void editTenantUser(SysUser sysUser, String tenantId, String departs, String roles) {
		SysUser user = new SysUser();
		user.setWorkNo(sysUser.getWorkNo());
		user.setId(sysUser.getId());
		this.updateById(user);
		// 代码逻辑说明: 【QQYUN-5251】人员与部门：部门删除不掉------------
		if(oConvertUtils.isEmpty(departs)){
			//直接删除用户下的的租户部门
			sysUserDepartMapper.deleteUserDepart(user.getId(),tenantId);
		}else{
			//修改租户用户下的部门
			this.updateTenantDepart(user, tenantId, departs);
		}
		//修改用户下的职位
		this.editUserPosition(sysUser.getId(),sysUser.getPost());
	}

	/**
	 * 修改账号状态
	 * @param id 账号id
	 * @param status 账号状态
	 */
	@Override
	@CacheEvict(value={CacheConstant.SYS_USERS_CACHE}, allEntries=true)
	public void updateStatus(String id, String status) {
		userMapper.update(new SysUser().setStatus(Integer.parseInt(status)),
				new UpdateWrapper<SysUser>().lambda().eq(SysUser::getId,id));
	}

	/**
	 * 修改租户下的部门
	 * @param departs
	 */
	public void updateTenantDepart(SysUser user, String tenantId, String departs) {
		List<String> departList = new ArrayList<>();
		long startTime = System.currentTimeMillis();
		if (oConvertUtils.isNotEmpty(departs)) {
			//获取当前租户下的部门id,根据前台
			departList = sysUserDepartMapper.getTenantDepart(Arrays.asList(departs.split(SymbolConstant.COMMA)), tenantId);
		}
		long endTime = System.currentTimeMillis();
		System.out.println("查询用户部门用时：" + (endTime - startTime) + "ms");
		//查询当前租户下部门和用户已关联的部门
		List<SysUserDepart> userDepartList = sysUserDepartMapper.getTenantUserDepart(user.getId(), tenantId);
		if (userDepartList != null && userDepartList.size() > 0 && departList.size() > 0) {
			for (SysUserDepart depart : userDepartList) {
				//修改已关联部门删除部门用户角色关系
				if (!departList.contains(depart.getDepId())) {
					List<SysDepartRole> sysDepartRoleList = sysDepartRoleMapper.selectList(
							new QueryWrapper<SysDepartRole>().lambda().eq(SysDepartRole::getDepartId, depart.getDepId()));
					List<String> roleIds = sysDepartRoleList.stream().map(SysDepartRole::getId).collect(Collectors.toList());
					if (roleIds.size() > 0) {
						departRoleUserMapper.delete(new QueryWrapper<SysDepartRoleUser>().lambda().eq(SysDepartRoleUser::getUserId, user.getId())
								.in(SysDepartRoleUser::getDroleId, roleIds));
					}
				}
			}
		}
		long endTime1 = System.currentTimeMillis();
		System.out.println("修改部门角色用时：" + (endTime1 - startTime) + "ms");
		
		if (departList.size() > 0) {
			//删除用户下的部门
			sysUserDepartMapper.deleteUserDepart(user.getId(), tenantId);
			for (String departId : departList) {
				//添加部门
				SysUserDepart userDepart = new SysUserDepart(user.getId(), departId);
				sysUserDepartMapper.insert(userDepart);
			}
		}
		long endTime2 = System.currentTimeMillis();
		System.out.println("修改用户部门用时：" + (endTime2 - startTime) + "ms");
	}

	/**
	 * 保存用户职位
	 *
	 * @param userId
	 * @param positionIds
	 */
	private void saveUserPosition(String userId, String positionIds) {
		if (oConvertUtils.isNotEmpty(positionIds)) {
			String[] positionIdArray = positionIds.split(SymbolConstant.COMMA);
			for (String postId : positionIdArray) {
				SysUserPosition userPosition = new SysUserPosition();
				userPosition.setUserId(userId);
				userPosition.setPositionId(postId);
				sysUserPositionMapper.insert(userPosition);
			}
		}
	}

	/**
	 * 编辑用户职位
	 *
	 * @param userId
	 * @param positionIds
	 */
	private void editUserPosition(String userId, String positionIds) {
		//先删除
		LambdaQueryWrapper<SysUserPosition> query = new LambdaQueryWrapper<>();
		query.eq(SysUserPosition::getUserId, userId);
		sysUserPositionMapper.delete(query);
		//后新增数据
		this.saveUserPosition(userId, positionIds);
	}

	/**
	 * 设置用户职位id(已逗号拼接起来)
	 * @param sysUser
	 */
	private void userPositionId(SysUser sysUser) {
		if(null != sysUser){
			List<String> positionList = sysUserPositionMapper.getPositionIdByUserId(sysUser.getId());
			sysUser.setPost(CommonUtils.getSplitText(positionList,SymbolConstant.COMMA));
		}
	}

	/**
	 * 查询用户当前登录部门的id
	 *
	 * @param orgCode
	 */
	private @Nullable String getDepartIdByOrCode(String orgCode) {
		if (oConvertUtils.isEmpty(orgCode)) {
			return null;
		}
		LambdaQueryWrapper<SysDepart> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(SysDepart::getOrgCode, orgCode);
		queryWrapper.select(SysDepart::getId);
		SysDepart depart = sysDepartMapper.selectOne(queryWrapper);
		if (depart == null || oConvertUtils.isEmpty(depart.getId())) {
			return null;
		}
		return depart.getId();
	}

	/**
	 * 查询用户的角色code（多个逗号分割）
	 *
	 * @param userId
	 */
	private @Nullable String getJoinRoleCodeByUserId(String userId) {
		if (oConvertUtils.isEmpty(userId)) {
			return null;
		}
		// 判断是否开启saas模式，根据租户id过滤
		Integer tenantId = null;
		if (MybatisPlusSaasConfig.OPEN_SYSTEM_TENANT_CONTROL) {
			// 开启了但是没有租户ID，默认-1，使其查询不到任何数据
			tenantId = oConvertUtils.getInt(TenantContext.getTenant(), -1);
		}
		List<SysRole> roleList = sysRoleMapper.getRoleCodeListByUserId(userId, tenantId);
		if (CollectionUtils.isEmpty(roleList)) {
			return null;
		}
		return roleList.stream().map(SysRole::getRoleCode).collect(Collectors.joining(SymbolConstant.COMMA));
	}

	/**
	 * 移除部门负责人
	 * @param departChargeUserIdList
	 * @param departChargeUsers
	 * @param departId
	 */
	private void removeDepartmentManager(List<String> departChargeUserIdList,List<SysUser> departChargeUsers,String departId){
		//移除部门负责人
		for(String chargeUserId: departChargeUserIdList){
			for(SysUser chargeUser: departChargeUsers){
				if(chargeUser.getId().equals(chargeUserId)){
					String departIds = chargeUser.getDepartIds();
					List<String> list = new ArrayList<String>(Arrays.asList(departIds.split(",")));
					list.remove(departId);
					String newDepartIds = String.join(",", list);
					chargeUser.setDepartIds(newDepartIds);
					this.baseMapper.updateById(chargeUser);
					break;
				}
			}
		}
	}

	//======================================= begin 用户与部门 用户列表导出 =========================================
	@Override
	public ModelAndView exportAppUser(HttpServletRequest request) {
		Integer tenantId = oConvertUtils.getInt(TenantContext.getTenant());
		// Step.1 组装查询条件，导出选中的部门id数据
		String departIds = request.getParameter("departIds");
		List<String> list = new ArrayList<>();
		if(oConvertUtils.isNotEmpty(departIds)){
			list = Arrays.asList(departIds.split(SymbolConstant.COMMA));
		}
		//查询用户数据
		List<SysUser> userList = userMapper.getUserByDepartsTenantId(list, tenantId);
        //获取部门名称
        List<SysUserDepVo> userDepVos = new ArrayList<>();
        if(CollectionUtil.isNotEmpty(userList)){
            userDepVos = sysDepartMapper.getUserDepartByTenantUserId(userList, tenantId);
        }
		//获取职位
		List<SysUserPositionVo> positionVos = sysUserPositionMapper.getPositionIdByUsersTenantId(userList, tenantId);
		// step2 根据用户id进行分类
		//循环用户数据将数据整合导出
		List<AppExportUserVo> exportUserVoList = new ArrayList<>();
		for (SysUser sysUser : userList) {
			AppExportUserVo exportUserVo = new AppExportUserVo();
			BeanUtils.copyProperties(sysUser, exportUserVo);
            // 代码逻辑说明: 【QQYUN-10926】组织管理——用户导出时，部门没有导出上下级关系---
            Map<String, String> departMap = this.getDepartNamesAndCategory(userDepVos, sysUser);
            String departNames = departMap.get("departNames");
            exportUserVo.setDepart(departNames.toString());
			String posNames = positionVos.stream().filter(item -> item.getUserId().equals(sysUser.getId())).map(SysUserPositionVo::getName).collect(Collectors.joining(SymbolConstant.SEMICOLON));
			exportUserVo.setPosition(posNames);
			exportUserVoList.add(exportUserVo);
		}
		//step3 封装导出excel参数
		ModelAndView mv = new ModelAndView(new JeecgEntityExcelView());
		//导出文件名称
		mv.addObject(NormalExcelConstants.FILE_NAME, "用户列表");
		mv.addObject(NormalExcelConstants.CLASS, AppExportUserVo.class);
		LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal();
		ExportParams exportParams = new ExportParams("导入规则：\n" +
				"1、存在用户编号时，数据会根据用户编号进行匹配，匹配成功后只会更新职位和工号;\n" +
				"2、不存在用户编号时，支持手机号、邮箱、姓名、部们、职位、工号导入,其中手机号必填;\n" +
				"3、上下级部门用英文字符 / 连接，如 财务部/财务一部，多个部门或者职位用英文字符 ; 进行连接,如 财务部;研发部", "导出人:" + user.getRealname(), "导出信息");
		mv.addObject(NormalExcelConstants.PARAMS, exportParams);
		mv.addObject(NormalExcelConstants.DATA_LIST, exportUserVoList);
		return mv;
	}

    /**
     * 获取部门名称和部门类型
     * for：【QQYUN-10926】组织管理——用户导出时，部门没有导出上下级关系
     *
     * @param userDepVos
     * @param sysUser
     * @return
     */
    private Map<String,String> getDepartNamesAndCategory(List<SysUserDepVo> userDepVos, SysUser sysUser) {
        List<SysUserDepVo> SysUserDepVoList = userDepVos.stream().filter(item -> item.getUserId().equals(sysUser.getId()))
                .map(item -> {
                    SysUserDepVo userDepVo = new SysUserDepVo();
                    userDepVo.setUserId(item.getUserId());
                    userDepVo.setDeptId(item.getDeptId());
                    userDepVo.setDepartName(item.getDepartName());
                    userDepVo.setParentId(item.getParentId());
                    userDepVo.setOrgCategory(DepartCategoryEnum.getNameByValue(item.getOrgCategory()));
                    return userDepVo;
                }).collect(Collectors.toList());
        //循环SysUserDepVoList,如果存在父级id的情况下，需要将父级id的部门名称查询出来
        StringBuilder departNames = new StringBuilder();
        StringBuilder departOrgCategorys = new StringBuilder();
        for (SysUserDepVo sysUserDepVo : SysUserDepVoList) {
            if(oConvertUtils.isEmpty(sysUserDepVo.getDepartName())){
                continue;
            }
            //用于查询父级的部门名称
            List<String> departNameList = new LinkedList<>();
            //用于查询父级的部门类型
            List<String> departOrgCategoryList = new LinkedList<>();
            departNameList.add(sysUserDepVo.getDepartName());
            departOrgCategoryList.add(sysUserDepVo.getOrgCategory());
            if (StringUtils.isNotEmpty(sysUserDepVo.getParentId())) {
                //递归查询部门名称
                this.getDepartNameByParentId(sysUserDepVo.getParentId(), departNameList, departOrgCategoryList);
            }
            Collections.reverse(departNameList);
            Collections.reverse(departOrgCategoryList);
            String departName = departNameList.stream().collect(Collectors.joining(SymbolConstant.SINGLE_SLASH));
            if (StringUtils.isNotEmpty(departNames.toString())) {
                departNames.append(SymbolConstant.SEMICOLON);
            }
            departNames.append(departName);
            String orgCatrgory = departOrgCategoryList.stream().collect(Collectors.joining(SymbolConstant.SINGLE_SLASH));
            if (StringUtils.isNotEmpty(departOrgCategorys.toString())) {
                departOrgCategorys.append(SymbolConstant.SEMICOLON);
            }
            departOrgCategorys.append(orgCatrgory);
        }
        // 代码逻辑说明: 【QQYUN-13617】导入时 部门添加层级不对了---
        Map<String,String> map = new HashMap<>();
        map.put("departNames", departNames.toString());
        map.put("departOrgCategorys",departOrgCategorys.toString());
        return map;
    }

    /**
     * 根据父级id查询父级的部门名称和部门类型
     * for：【QQYUN-10926】组织管理——用户导出时，部门没有导出上下级关系
     *
     * @param parentId
     * @param departNameList
     * @param departOrgCategoryList
     */
    private void getDepartNameByParentId(String parentId, List<String> departNameList, List<String> departOrgCategoryList) {
        SysDepart parentDepartId = sysDepartMapper.getDepartById(parentId);
        if (null != parentDepartId) {
            departNameList.add(parentDepartId.getDepartName());
            departOrgCategoryList.add(DepartCategoryEnum.getNameByValue(parentDepartId.getOrgCategory()));
            if (StringUtils.isNotEmpty(parentDepartId.getParentId())) {
                this.getDepartNameByParentId(parentDepartId.getParentId(), departNameList, departOrgCategoryList);
            }
        }
    }

    //======================================= end 用户与部门 用户列表导出 =========================================

	//======================================= begin 用户与部门 用户列表导入 =========================================
	@Override
	public Result<?> importAppUser(HttpServletRequest request) {
		MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
		Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
		Integer tenantId = oConvertUtils.getInt(TenantContext.getTenant());
		SysTenant sysTenant = sysTenantMapper.selectById(tenantId);
		// 错误信息
		List<String> errorMessage = new ArrayList<>();
		int successLines = 0, errorLines = 0;
		for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
			MultipartFile file = entity.getValue();
			ImportParams params = new ImportParams();
			params.setTitleRows(2);
			params.setHeadRows(1);
			params.setNeedSave(true);
			//存放职位的map;key为名称 value为职位id。避免多次导入和查询
			Map<String, String> positionMap = new HashMap<>();
			//存放部门的map;key为名称 value为SysDepart对象。避免多次导入和查询
			Map<String, SysDepart> departMap = new HashMap<>();
			try {
				List<AppExportUserVo> listSysUsers = ExcelImportUtil.importExcel(file.getInputStream(), AppExportUserVo.class, params);
				for (int i = 0; i < listSysUsers.size(); i++) {
					//记录现在是多少行
					int lineNumber = i + 1;
					//记录是编辑还是添加
					boolean isEdit = false;
					AppExportUserVo sysUserExcel = listSysUsers.get(i);
					String id = sysUserExcel.getId();
					String workNo = sysUserExcel.getWorkNo();
					String email = sysUserExcel.getEmail();
					String phone = sysUserExcel.getPhone();
					String realname = sysUserExcel.getRealname();
					String depart = sysUserExcel.getDepart();
					String position = sysUserExcel.getPosition();
					SysUser sysUser = new SysUser();
					//判断id是否存在，如果存在的话就是更新
					if (oConvertUtils.isNotEmpty(id)) {
						SysUser user = userMapper.selectById(id);
						if (null == user) {
							errorLines++;
							errorMessage.add("第 " + lineNumber + " 行：用户不存在，请查看编号是否已修改，忽略导入。");
							continue;
						}
						isEdit = true;
						sysUser.setId(id);
					} else {
						//处理租户中是否已存在，用户是否已存在，已存在的用户直接更新
						isEdit = false;
					}
					if (oConvertUtils.isNotEmpty(workNo)) {
						sysUser.setWorkNo(workNo);
					}
					try {
						if (isEdit) {
							userMapper.updateById(sysUser);
						} else {
							if (oConvertUtils.isEmpty(phone)) {
								errorMessage.add("第 " + lineNumber + " 行：手机号为空，忽略导入。");
								errorLines++;
								continue;
							}
							SysUser userByPhone = userMapper.getUserByPhone(phone);
							if (null != userByPhone) {
								//查看看是否已经存在此租户中，存在禁止导入，否则直接更新即可
								Integer tenantCount = userTenantMapper.userTenantIzExist(userByPhone.getId(), tenantId);
								if (tenantCount > 0) {
									errorMessage.add("第 " + lineNumber + " 行：成员已存在该组织中，如果列表中不存在，请确认该成员是否在审核中或者已离职，忽略导入。");
									errorLines++;
									continue;
								}
								sysUser.setId(userByPhone.getId());
								userMapper.updateById(sysUser);
								this.addUserTenant(sysUser.getId(), tenantId, userByPhone.getUsername(),sysTenant.getName());
							} else {
								// 密码默认为 “租户门牌号+手机号”
								String password = sysTenant.getHouseNumber()+phone;
								String salt = oConvertUtils.randomGen(8);
								sysUser.setSalt(salt);
								// 密码加密加盐
								String passwordEncode = PasswordUtil.encrypt(phone, password, salt);
								sysUser.setPassword(passwordEncode);
								sysUser.setUsername(phone);
								sysUser.setRealname(oConvertUtils.getString(realname,phone));
								sysUser.setEmail(email);
								sysUser.setPhone(phone);
								sysUser.setStatus(CommonConstant.DEL_FLAG_1);
								sysUser.setDelFlag(CommonConstant.DEL_FLAG_0);
								sysUser.setCreateTime(new Date());
								userMapper.insert(sysUser);
								this.addUserTenant(sysUser.getId(), tenantId, sysUser.getUsername(),sysTenant.getName());
							}
						}
						//新增或编辑职位
						if (oConvertUtils.isNotEmpty(position)) {
							this.addOrEditPosition(sysUser.getId(), position, isEdit, tenantId, positionMap);
						}
						//新增的时候才可以添加部门
						if (!isEdit) {
							//新增或编辑部门
							this.addOrEditDepart(sysUser.getId(), depart, tenantId, departMap);
						}
						successLines++;
					} catch (Exception e) {
						errorLines++;
						String message = e.getMessage().toLowerCase();

						// 通过索引名判断出错信息
						if (message.contains(CommonConstant.SQL_INDEX_UNIQ_SYS_USER_USERNAME)) {
							errorMessage.add("第 " + lineNumber + " 行：用户名已经存在，忽略导入。");
						} else if (message.contains(CommonConstant.SQL_INDEX_UNIQ_SYS_USER_WORK_NO)) {
							errorMessage.add("第 " + lineNumber + " 行：工号已经存在，忽略导入。");
						} else if (message.contains(CommonConstant.SQL_INDEX_UNIQ_SYS_USER_PHONE)) {
							errorMessage.add("第 " + lineNumber + " 行：手机号已经存在，忽略导入。");
						} else if (message.contains(CommonConstant.SQL_INDEX_UNIQ_SYS_USER_EMAIL)) {
							errorMessage.add("第 " + lineNumber + " 行：电子邮件已经存在，忽略导入。");
						} else if (message.contains(CommonConstant.SQL_INDEX_UNIQ_SYS_USER)) {
							errorMessage.add("第 " + lineNumber + " 行：违反表唯一性约束。");
						} else {
							errorMessage.add("第 " + lineNumber + " 行：未知错误，忽略导入");
							log.error(e.getMessage(), e);
						}
					}
				}
			} catch (Exception e) {
				errorMessage.add("发生异常：" + e.getMessage());
				log.error(e.getMessage(), e);
			} finally {
				try {
					file.getInputStream().close();
				} catch (IOException e) {
					log.error(e.getMessage(), e);
				}
			}
		}
		try {
			return ImportExcelUtil.imporReturnRes(errorLines, successLines, errorMessage);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 新增或者编辑职位
	 *
	 * @param userId      用户id
	 * @param position    职位名称 已/拼接
	 * @param isEdit      新增或编辑
	 * @param positionMap 职位map key为name，value为职位id
	 */
	private void addOrEditPosition(String userId, String position, Boolean isEdit, Integer tenantId, Map<String, String> positionMap) {
		Page<SysPosition> page = new Page<>(1, 1);
		String[] positions = position.split(SymbolConstant.SEMICOLON);
		List<String> positionList = Arrays.asList(positions);
		positionList = positionList.stream().distinct().collect(Collectors.toList());
		//删除当前租户下的职位，根据职位名称、租户id、用户id
		sysUserPositionMapper.deleteUserPosByNameAndTenantId(positionList, tenantId, userId);
		//循环需要添加或修改的数据
		for (String pos : positionList) {
			String posId = "";
			if (positionMap.containsKey(pos)) {
				posId = positionMap.get(pos);
			} else {
				List<String> namePage = sysPositionMapper.getPositionIdByName(pos, tenantId, page);
				if (CollectionUtil.isNotEmpty(namePage)) {
					posId = namePage.get(0);
					positionMap.put(pos, posId);
				}
			}

			//职位id不为空直接新增
			if (oConvertUtils.isNotEmpty(posId)) {
				this.addSysUserPosition(userId, posId);
				continue;
			}

			//不是编辑的情况下职位才会新增
			if (!isEdit) {
				//新增职位和用户职位关系
				SysPosition sysPosition = new SysPosition();
				sysPosition.setName(pos);
				sysPosition.setCode(RandomUtil.randomString(10));
				sysPosition.setTenantId(tenantId);
				sysPositionMapper.insert(sysPosition);
				positionMap.put(pos, sysPosition.getId());
				this.addSysUserPosition(userId, sysPosition.getId());
			}
		}
	}

	/**
	 * 添加用户职位
	 */
	private void addSysUserPosition(String userId, String positionId) {
		Long count = sysUserPositionMapper.getUserPositionCount(userId, positionId);
		if(count == 0){
			SysUserPosition userPosition = new SysUserPosition();
			userPosition.setUserId(userId);
			userPosition.setPositionId(positionId);
			sysUserPositionMapper.insert(userPosition);
		}
	}

	/**
	 * 新增或编辑部门
	 *
	 * @param userId    用户id
	 * @param depart    部门名称
	 * @param tenantId  租户id
	 * @param departMap 存放部门的map;key为名称 value为SysDepart对象。
	 */
	private void addOrEditDepart(String userId, String depart, Integer tenantId, Map<String, SysDepart> departMap) {
		//批量将部门和用户信息建立关联关系
		if (StringUtils.isNotEmpty(depart)) {
			Page<SysDepart> page = new Page<>(1, 1);
			//多个部门分离开
			String[] departNames = depart.split(SymbolConstant.SEMICOLON);
			List<String> departNameList = Arrays.asList(departNames);
			departNameList = departNameList.stream().distinct().collect(Collectors.toList());
			for (String departName : departNameList) {
                //部门id
                String parentId = "";
				String[] names = departName.split(SymbolConstant.SINGLE_SLASH);
				//部门名称拼接
				String nameStr = "";
				for (int i = 0; i < names.length; i++) {
					String name = names[i];
					//拼接name
					if (oConvertUtils.isNotEmpty(nameStr)) {
						nameStr = nameStr + SymbolConstant.SINGLE_SLASH + name;
					} else {
						nameStr = name;
					}
					SysDepart sysDepart = null;
					//判断map中是否存在该部门名称
					if (departMap.containsKey(nameStr)) {
						sysDepart = departMap.get(nameStr);
					} else {
						//不存在需要去查询
						List<SysDepart> departPageByName = sysDepartMapper.getDepartPageByName(page, name, tenantId, parentId);
						//部门为空需要新增部门
						if (CollectionUtil.isEmpty(departPageByName)) {
							JSONObject formData = new JSONObject();
							formData.put("parentId", parentId);
							String[] codeArray = (String[]) FillRuleUtil.executeRule(FillRuleConstant.DEPART, formData);
							sysDepart = new SysDepart();
							sysDepart.setParentId(parentId);
							sysDepart.setOrgCode(codeArray[0]);
							sysDepart.setOrgType(codeArray[1]);
							sysDepart.setTenantId(tenantId);
							sysDepart.setDepartName(name);
							sysDepart.setIzLeaf(CommonConstant.IS_LEAF);
							sysDepart.setDelFlag(String.valueOf(CommonConstant.DEL_FLAG_0));
							sysDepart.setStatus(CommonConstant.STATUS_1);
							sysDepartMapper.insert(sysDepart);
						} else {
							sysDepart = departPageByName.get(0);
						}
						//父级id不为空那么就将父级部门改成不是叶子节点
						if (oConvertUtils.isNotEmpty(parentId)) {
							sysDepartMapper.setMainLeaf(parentId, CommonConstant.NOT_LEAF);
						}
						parentId = sysDepart.getId();
						departMap.put(nameStr, sysDepart);
					}
					//最后一位新增部门用户关系表
					if (i == names.length - 1) {
						Long count = sysUserDepartMapper.getCountByDepartIdAndUserId(userId, sysDepart.getId());
						if(count == 0){
							SysUserDepart userDepart = new SysUserDepart(userId, sysDepart.getId());
							sysUserDepartMapper.insert(userDepart);
						}
					}
				}
			}
		}

	}

	/**
	 * 添加用户租户
	 *
	 * @param userId
	 * @param tenantId
	 * @param invitedUsername 被邀请人的账号
	 * @param tenantName 租户名称 
	 */
	private void addUserTenant(String userId, Integer tenantId, String invitedUsername, String tenantName) {
		SysUserTenant userTenant = new SysUserTenant();
		userTenant.setTenantId(tenantId);
		userTenant.setUserId(userId);
		userTenant.setStatus(CommonConstant.USER_TENANT_INVITE);
		userTenantMapper.insert(userTenant);
		//发送系统消息通知
		LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
		MessageDTO messageDTO = new MessageDTO();
		String title = sysUser.getRealname() + " 邀请您加入 " + tenantName + "。";
		messageDTO.setTitle(title);
		Map<String, Object> data = new HashMap<>();
		// 代码逻辑说明: 【QQYUN-8425】用户导入成功后 消息提醒 跳转至同意页面---
		data.put(CommonConstant.NOTICE_MSG_BUS_TYPE,SysAnnmentTypeEnum.TENANT_INVITE.getType());
		messageDTO.setData(data);
		messageDTO.setContent(title);
		messageDTO.setToUser(invitedUsername);
		messageDTO.setFromUser("system");
		systemSendMsgHandle.sendMessage(messageDTO);
	}
	//======================================= end 用户与部门 用户列表导入 =========================================
	
	@Override
	public void checkUserAdminRejectDel(String userIds) {
		LambdaQueryWrapper<SysUser> query = new LambdaQueryWrapper<>();
		query.in(SysUser::getId,Arrays.asList(userIds.split(SymbolConstant.COMMA)));
		query.eq(SysUser::getUsername,"admin");
		Long adminRoleCount = this.baseMapper.selectCount(query);
		//大于0说明存在管理员用户，不允许删除
		if(adminRoleCount>0){
			throw new JeecgBootException("admin用户，不允许删除！");
		}
	}

	@Override
	public void changePhone(JSONObject json, String username) {
		String smscode = json.getString("smscode");
		String phone = json.getString("phone");
		String type = json.getString("type");
		if(oConvertUtils.isEmpty(phone)){
			throw new JeecgBootException("请填写原手机号！");
		}
		if(oConvertUtils.isEmpty(smscode)){
			throw new JeecgBootException("请填写验证码！");
		}
		//step1 验证原手机号是否和当前用户匹配
		SysUser sysUser = userMapper.getUserByNameAndPhone(phone,username);
		if (null == sysUser){
			throw new JeecgBootException("原手机号不匹配，无法修改密码！");
		}
		//step2 根据类型判断是验证原手机号的验证码还是新手机号的验证码
		//验证原手机号
		if(CommonConstant.VERIFY_ORIGINAL_PHONE.equals(type)){
			this.verifyPhone(phone, smscode);
		}else if(CommonConstant.UPDATE_PHONE.equals(type)){
			//修改手机号
			String newPhone = json.getString("newPhone");
			//需要验证新手机号和原手机号是否一致，一致不让修改
			if(newPhone.equals(phone)){
				throw new JeecgBootException("新手机号与原手机号一致，无法修改！");
			}
			this.verifyPhone(newPhone, smscode);
			//step3 新手机号验证码验证成功之后即可修改手机号
			sysUser.setPhone(newPhone);
			userMapper.updateById(sysUser);
		}
	}
	
	/**
	 * 验证手机号
	 *
	 * @param phone
	 * @param smsCode
	 * @return
	 */
	public void verifyPhone(String phone, String smsCode){
		String phoneKey = CommonConstant.CHANGE_PHONE_REDIS_KEY_PRE + phone;
		Object phoneCode = redisUtil.get(phoneKey);
		if(null == phoneCode){
			throw new JeecgBootException("验证码失效，请重新发送验证码！");
		}
		if(!smsCode.equals(phoneCode.toString())) {
			throw new JeecgBootException("短信验证码不匹配！");
		}
		//验证完成之后清空手机验证码
		redisUtil.removeAll(phoneKey);
	}
	
	@Override
	public void sendChangePhoneSms(JSONObject jsonObject, String username, String ipAddress) {
		String type = jsonObject.getString("type");
		String phone = jsonObject.getString("phone");
		if(oConvertUtils.isEmpty(phone)){
			throw new JeecgBootException("请填写手机号！");
		}
		//step1 根据类型判断是发送旧手机号验证码还是新的手机号验证码
		if(CommonConstant.VERIFY_ORIGINAL_PHONE.equals(type)){
			//step2 旧手机号验证码需要验证手机号是否匹配
			SysUser sysUser = userMapper.getUserByNameAndPhone(phone, username);
			if(null == sysUser){
				throw new JeecgBootException("旧手机号不匹配，无法修改手机号！");
			}
		}else if(CommonConstant.UPDATE_PHONE.equals(type)){
			//step3 新手机号需要验证手机号码是否已注册过
			SysUser userByPhone = userMapper.getUserByPhone(phone);
			if(null != userByPhone){
				throw new JeecgBootException("手机号已被注册，请尝试其他手机号！");
			}
		}
		//step4 发送短信验证码
		String redisKey = CommonConstant.CHANGE_PHONE_REDIS_KEY_PRE+phone;
		this.sendPhoneSms(phone, ipAddress,redisKey);
	}

	@Override
	public void sendLogOffPhoneSms(JSONObject jsonObject, String username, String ipAddress) {
		String phone = jsonObject.getString("phone");
		//通过用户名查询数据库中的手机号
		SysUser userByNameAndPhone = userMapper.getUserByNameAndPhone(phone, username);
		if (null == userByNameAndPhone) {
			throw new JeecgBootException("当前用户手机号不匹配，无法修改！");
		}
		String code = CommonConstant.LOG_OFF_PHONE_REDIS_KEY_PRE + phone;
		this.sendPhoneSms(phone, ipAddress, code);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void userLogOff(JSONObject jsonObject, String username) {
		String phone = jsonObject.getString("phone");
		String smsCode = jsonObject.getString("smscode");
		//通过用户名查询数据库中的手机号
		SysUser userByNameAndPhone = userMapper.getUserByNameAndPhone(phone, username);
		if (null == userByNameAndPhone) {
			throw new JeecgBootException("当前用户手机号不匹配，无法注销！");
		}
		String code = CommonConstant.LOG_OFF_PHONE_REDIS_KEY_PRE + phone;
		Object redisSmdCode = redisUtil.get(code);
		if (null == redisSmdCode) {
			throw new JeecgBootException("验证码失效，无法注销！");
		}
		if (!redisSmdCode.toString().equals(smsCode)) {
			throw new JeecgBootException("验证码不匹配，无法注销！");
		}
		this.deleteUser(userByNameAndPhone.getId());
		redisUtil.removeAll(code);
		redisUtil.removeAll(CacheConstant.SYS_USERS_CACHE + phone);
	}

	/**
	 * 发送短信验证码
	 * @param phone
	 */
	private void sendPhoneSms(String phone, String clientIp,String redisKey) {
		Object object = redisUtil.get(redisKey);

		if (object != null) {
			throw new JeecgBootException("验证码10分钟内，仍然有效！");
		}

		//增加 check防止恶意刷短信接口
		if(!DySmsLimit.canSendSms(clientIp)){
			log.warn("--------[警告] IP地址:{}, 短信接口请求太多-------", clientIp);
			throw new JeecgBootException("短信接口请求太多，请稍后再试！", CommonConstant.PHONE_SMS_FAIL_CODE);
		}
		
		//随机数
		String captcha = RandomUtil.randomNumbers(6);
		JSONObject obj = new JSONObject();
		obj.put("code", captcha);
		try {
			boolean sendSmsSuccess = DySmsHelper.sendSms(phone, obj, DySmsEnum.LOGIN_TEMPLATE_CODE);
			if(!sendSmsSuccess){
				throw new JeecgBootException("短信验证码发送失败,请稍后重试！");
			}
			//验证码10分钟内有效
			redisUtil.set(redisKey, captcha, 600);
		} catch (ClientException e) {
			log.error(e.getMessage(),e);
			throw new JeecgBootException("短信接口未配置，请联系管理员！");
		}
	}

    //================================================= begin 低代码部门导入导出 ================================================================
    @Override
    public List<SysUserExportVo> getDepartAndRoleExportMsg(List<SysUser> userList) {
        List<SysUserExportVo> list = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(userList)) {
            //获取部门
            List<SysUserDepVo> userDepVos = sysDepartMapper.getUserDepartByUserId(userList);
            //获取角色
            List<SysUserPositionVo> sysRoles = sysRoleMapper.getUserRoleByUserId(userList);
            //存放职位名称的map，key：主岗位的id value: 职级的名称
            Map<String, String> postNameMap = new HashMap<>();
            //组装数据并返回
            for (SysUser sysUser : userList) {
                SysUserExportVo userExportVo = new SysUserExportVo();
                BeanUtils.copyProperties(sysUser, userExportVo);
                // 代码逻辑说明: 【QQYUN-13617】导入时 部门添加层级不对了---
                Map<String, String> departMap = this.getDepartNamesAndCategory(userDepVos, sysUser);
                String departNames = departMap.get("departNames");
                userExportVo.setDepartNames(departNames);
                userExportVo.setOrgCategorys(departMap.get("departOrgCategorys"));
                String departIds = sysUser.getDepartIds();
                if (oConvertUtils.isNotEmpty(departIds)) {
                    List<SysUserDepVo> depVoList = sysDepartMapper.getDepartByIds(Arrays.asList(departIds.split(",")));
                    Map<String, String> departMaps = this.getDepartNamesAndCategory(userDepVos, sysUser);
                    userExportVo.setDepartIds(departMaps.get("departNames"));
                }
                String posNames = sysRoles.stream().filter(item -> item.getUserId().equals(sysUser.getId())).map(SysUserPositionVo::getName).collect(Collectors.joining(SymbolConstant.SEMICOLON));
                userExportVo.setRoleNames(posNames);
                if (null != sysUser.getMainDepPostId()) {
                    String postName = "";
                    if (null != postNameMap && postNameMap.containsKey(sysUser.getMainDepPostId())) {
                        postName = postNameMap.get(sysUser.getMainDepPostId());
                    } else {
                        postName = sysDepartMapper.getPostNameByPostId(sysUser.getMainDepPostId());
                    }
                    userExportVo.setPostName(postName);
                    postNameMap.put(sysUser.getMainDepPostId(), postName);
                }
                // 代码逻辑说明: 兼职岗位改造成中间表的方式---
                List<String> depPost = depPostMapper.getDepPostByUserId(sysUser.getId());
                if(CollectionUtil.isNotEmpty(depPost)){
                    userExportVo.setOtherDepPostId(String.join(SymbolConstant.COMMA, depPost));
                }
                list.add(userExportVo);
            }
        }
        return list;
    }

    @Override
    public Result<?> importSysUser(HttpServletRequest request) {
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        String fileKey = multipartRequest.getParameter("fileKey");
        Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
        // 错误信息
        List<String> errorMessage = new ArrayList<>();
        int successLines = 0, errorLines = 0;
        //存放部门的map;key为名称 value为SysDepart对象。避免多次导入和查询
        Map<String, SysDepart> departMap = new HashMap<>();
        //职级map key: 职级名称 value: 职级id
        Map<String, String> positionMap = new HashMap<>();
        //岗位map key：岗位名称 + 部门id value：岗位（部门id）
        Map<String,String> postMap = new HashMap<>();
        String tenantId = TokenUtils.getTenantIdByRequest(request);
        for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
            MultipartFile file = entity.getValue();// 获取上传文件对象
            ImportParams params = new ImportParams();
            params.setTitleRows(2);
            params.setHeadRows(1);
            params.setNeedSave(true);
            try {
                List<SysUserImportVo> listSysUsers = ExcelImportUtil.importExcel(file.getInputStream(), SysUserImportVo.class, params);
                ImportSysUserCache.setImportSysUserMap(fileKey,0,listSysUsers.size(),"user");
                for (int i = 0; i < listSysUsers.size(); i++) {
                    SysUserImportVo sysUserExcel = listSysUsers.get(i);
                    SysUser sysUser = new SysUser();
                    BeanUtils.copyProperties(sysUserExcel, sysUser);
                    if (oConvertUtils.isEmpty(sysUser.getUsername())) {
                        errorLines += 1;
                        int lineNumber = i + 1;
                        errorMessage.add("第 " + lineNumber + " 行：用户账号为空，忽略导入。");
                        continue;
                    }
                    try {
                        String username = sysUser.getUsername();
                        //根据用户名程序，为空则添加用户
                        SysUser userByName = userMapper.getUserByName(username);
                        if (null != userByName) {
                            errorLines += 1;
                            int lineNumber = i + 1;
                            errorMessage.add("第 " + lineNumber + " 行：用户名已经存在，忽略导入。");
                            continue;
                        } else {
                            // 密码默认为 “123456”
                            sysUser.setPassword(PasswordConstant.DEFAULT_PASSWORD);
                            // 密码加密加盐
                            String salt = oConvertUtils.randomGen(8);
                            sysUser.setSalt(salt);
                            String passwordEncode = PasswordUtil.encrypt(sysUserExcel.getUsername(), sysUser.getPassword(), salt);
                            sysUser.setPassword(passwordEncode);
                            sysUser.setActivitiSync(CommonConstant.ACT_SYNC_1);
                            if(null == sysUser.getDelFlag()){
                                sysUser.setDelFlag(CommonConstant.DEL_FLAG_0);
                            }
                            if(null == sysUser.getStatus()){
                                sysUser.setStatus(CommonConstant.STATUS_1_INT);
                            }
                            this.save(sysUser);
                        }
                        //添加部门
                        String departNames = sysUserExcel.getDepartNames();
                        String orgCategorys = sysUserExcel.getOrgCategorys();
                        //新增或编辑部门
                        Integer tenantIdInt = 0;
                        if (MybatisPlusSaasConfig.OPEN_SYSTEM_TENANT_CONTROL) {
                            tenantIdInt = oConvertUtils.getInt(tenantId, 0);
                        }
                        this.lowAddOrEditDepart(sysUser.getId(), departNames, tenantIdInt, departMap, orgCategorys, sysUserExcel.getPostName(), sysUserExcel.getMainDepPostId(),postMap,positionMap, sysUserExcel.getOtherDepPostId());
                        //新增或编辑角色
                        String roleNames = sysUserExcel.getRoleNames();
                        this.saveOrEditRole(sysUser.getId(), roleNames, tenantIdInt);
                        //新增或编辑职位
                       /* String position = sysUserExcel.getPost();
                        if (oConvertUtils.isNotEmpty(position)) {
                            this.addOrEditPosition(sysUser.getId(), position, false, tenantIdInt, positionMap);
                        }*/
                        //添加负责部门
                        this.saveChargeDepart(sysUser, sysUserExcel.getDepartIds(), departMap);
                        successLines++;
                    } catch (Exception e) {
                        errorLines++;
                        String message = e.getMessage().toLowerCase();
                        int lineNumber = i + 1;
                        // 通过索引名判断出错信息
                        if (message.contains(CommonConstant.SQL_INDEX_UNIQ_SYS_USER_USERNAME)) {
                            errorMessage.add("第 " + lineNumber + " 行：用户名已经存在，忽略导入。");
                        } else if (message.contains(CommonConstant.SQL_INDEX_UNIQ_SYS_USER_WORK_NO)) {
                            errorMessage.add("第 " + lineNumber + " 行：工号已经存在，忽略导入。");
                        } else if (message.contains(CommonConstant.SQL_INDEX_UNIQ_SYS_USER_PHONE)) {
                            errorMessage.add("第 " + lineNumber + " 行：手机号已经存在，忽略导入。");
                        } else if (message.contains(CommonConstant.SQL_INDEX_UNIQ_SYS_USER_EMAIL)) {
                            errorMessage.add("第 " + lineNumber + " 行：电子邮件已经存在，忽略导入。");
                        } else if (message.contains(CommonConstant.SQL_INDEX_UNIQ_SYS_USER)) {
                            errorMessage.add("第 " + lineNumber + " 行：违反表唯一性约束。");
                        } else {
                            errorMessage.add("第 " + lineNumber + " 行：未知错误，忽略导入");
                            log.error(e.getMessage(), e);
                        }
                    }
                    ImportSysUserCache.setImportSysUserMap(fileKey,i,listSysUsers.size(),"user");
                }
            } catch (Exception e) {
                ImportSysUserCache.removeImportLowAppMap(fileKey);
                errorMessage.add("发生异常：" + e.getMessage());
                log.error(e.getMessage(), e);
            } finally {
                try {
                    file.getInputStream().close();
                } catch (IOException e) {
                    ImportSysUserCache.removeImportLowAppMap(fileKey);
                    log.error(e.getMessage(), e);
                }
            }
        }
        try {
            departMap.clear();
            departMap = null;
            //最终导入完成
            ImportSysUserCache.setImportSysUserMap(fileKey,1,1,"user");
            return ImportExcelUtil.imporReturnRes(errorLines, successLines, errorMessage);
        } catch (IOException e) {
            ImportSysUserCache.removeImportLowAppMap(fileKey);
            throw new RuntimeException(e);
        }
    }

    //================================================================ begin 【用户导入】导入时 部门添加层级不对了======================================================================
    /**
     * 低代码下添加部门和用户
     *
     * @param userId          用户id
     * @param depart          部门名称
     * @param tenantId        租户id
     * @param departMap       存放部门的map;key为名称 value为SysDepart对象。
     * @param orgCategorys    部门类型
     * @param postName        职级名称
     * @param mainDepPostName 主岗位名称
     * @param postMap         key: 岗位名称 + 部门id value：岗位（部门id）
     * @param positionMap     key: 职级名称  value: 职级id
     * @param otherDepPostName 兼职岗位名称
     * @Description 和敲敲云分割处理，原因：因低代码岗位等改造，有级别，故添加部门分开处理
     */
    private void lowAddOrEditDepart(String userId, String depart, Integer tenantId, Map<String, SysDepart> departMap, String orgCategorys, String postName, String mainDepPostName, Map<String, String> postMap, Map<String, String> positionMap, String otherDepPostName) {
        //批量将部门和用户信息建立关联关系
        if (StringUtils.isNotEmpty(depart)) {
            Page<SysDepart> page = new Page<>(1, 1);
            //多个部门分离开
            String[] departNames = depart.split(SymbolConstant.SEMICOLON);
            List<String> departNameList = Arrays.asList(departNames);
            //部门类型
            List<String> categoryList = new ArrayList<>();
            if (oConvertUtils.isNotEmpty(orgCategorys)) {
                categoryList = Arrays.asList(orgCategorys.split(SymbolConstant.SEMICOLON));
            }
            departNameList = departNameList.stream().distinct().collect(Collectors.toList());
            //当下部门循环下标
            int index = 0;
            //是否已导入岗位，岗位只导入第一个部门下
            boolean izImportPost = false;
            for (String departName : departNameList) {
                //部门id
                String parentId = "";
                String[] names = departName.split(SymbolConstant.SINGLE_SLASH);
                //部门名称拼接
                String nameStr = "";
                //部门类型
                String[] orgCategory = null;
                if (categoryList != null && categoryList.size() > index) {
                    orgCategory = categoryList.get(index).split(SymbolConstant.SINGLE_SLASH);
                }
                for (int i = 0; i < names.length; i++) {
                    String name = names[i];
                    //拼接name
                    if (oConvertUtils.isNotEmpty(nameStr)) {
                        nameStr = nameStr + SymbolConstant.SINGLE_SLASH + name;
                    } else {
                        nameStr = name;
                    }
                    SysDepart sysDepart = null;
                    //默认部门
                    String category = DepartCategoryEnum.DEPART_CATEGORY_DEPART.getValue();
                    if (null != orgCategory && orgCategory.length > i) {
                        category = orgCategory[i];
                    }
                    //判断map中是否存在该部门名称
                    if (departMap.containsKey(nameStr)) {
                        sysDepart = departMap.get(nameStr);
                        parentId = sysDepart.getId();
                    } else {
                        //不存在需要去查询
                        List<SysDepart> departPageByName = sysDepartMapper.getDepartPageByName(page, name, tenantId, parentId);
                        //部门为空需要新增部门
                        if (CollectionUtil.isEmpty(departPageByName)) {
                            JSONObject formData = new JSONObject();
                            formData.put("parentId", parentId);
                            String[] codeArray = (String[]) FillRuleUtil.executeRule(FillRuleConstant.DEPART, formData);
                            sysDepart = new SysDepart();
                            sysDepart.setParentId(parentId);
                            sysDepart.setOrgCode(codeArray[0]);
                            sysDepart.setOrgType(codeArray[1]);
                            sysDepart.setTenantId(tenantId);
                            sysDepart.setDepartName(name);
                            sysDepart.setIzLeaf(CommonConstant.IS_LEAF);
                            sysDepart.setDelFlag(String.valueOf(CommonConstant.DEL_FLAG_0));
                            sysDepart.setStatus(CommonConstant.STATUS_1);
                            sysDepart.setOrgCategory(DepartCategoryEnum.getValueByName(category));
                            sysDepartMapper.insert(sysDepart);
                        } else {
                            sysDepart = departPageByName.get(0);
                        }
                        //父级id不为空那么就将父级部门改成不是叶子节点
                        if (oConvertUtils.isNotEmpty(parentId)) {
                            sysDepartMapper.setMainLeaf(parentId, CommonConstant.NOT_LEAF);
                        }
                        parentId = sysDepart.getId();
                        departMap.put(nameStr, sysDepart);
                    }
                    //最后一位新增部门用户关系表
                    if (i == names.length - 1 && !izImportPost) {
                        Long count = sysUserDepartMapper.getCountByDepartIdAndUserId(userId, sysDepart.getId());
                        if (count == 0) {
                            SysUserDepart userDepart = new SysUserDepart(userId, sysDepart.getId());
                            sysUserDepartMapper.insert(userDepart);
                        }
                        //添加岗位
                        if (oConvertUtils.isNotEmpty(mainDepPostName)) {
                            this.insertDepartPost(userId, parentId ,postName, mainDepPostName, postMap, tenantId, positionMap);
                        }
                        //添加兼职岗位
                        if(oConvertUtils.isNotEmpty(otherDepPostName)){
                            this.insertOtherDepartPost(userId,parentId,postName, otherDepPostName, postMap, tenantId, positionMap);
                        }
                        izImportPost = true;
                    }
                }
                index++;
            }
        }
    }

    /**
     * 添加部门岗位
     *
     * @param mainDepPost 岗位名称
     * @param userId      用户id
     * @param departId    部门id【上级部门id】
     * @param postName    职级名称
     * @param mainDepPostName    岗位名称
     * @param postMap     岗位map key：岗位名称 + 部门id value：岗位（部门id）
     * @param tenantId    租户id
     * @param postionMap  职级map key: 职级名称 value: 职级id
     */
    private void insertDepartPost(String userId, String depId, String postName, String mainDepPostName, Map<String, String> postMap, Integer tenantId, Map<String, String> postionMap) {
        if(mainDepPostName.contains(SymbolConstant.COMMA)){
            mainDepPostName = mainDepPostName.split(SymbolConstant.COMMA)[0];
        }
        //当前部门下已经存在岗位就不需要再次添加岗位了
        if (null == postMap || !postMap.containsKey(mainDepPostName + depId)) {
            //根据父级部门id和职务名称查找岗位id
            String departId = sysDepartMapper.getDepIdByDepIdAndPostName(depId, postName);
            //不存在新增岗位
            if (oConvertUtils.isEmpty(departId) ) {
                //添加部门岗位信息
                departId = this.addCommontDepartPost(depId, tenantId, mainDepPostName, postionMap, postName, postMap);
            }
            if(oConvertUtils.isNotEmpty(departId)){
                //更新用户主岗位
                SysUser user = new SysUser();
                user.setId(userId);
                user.setMainDepPostId(departId);
                userMapper.updateById(user); 
            }
        }
    }

    /**
     * 导入通用添加部门岗位方法
     *
     * @param depId
     * @param tenantId
     * @param mainDepPostName
     * @param postionMap
     * @param postName
     * @param map
     * @param postMap
     * @return
     */
    private String addCommontDepartPost(String depId, Integer tenantId, String mainDepPostName, Map<String, String> postionMap, String postName, Map<String, String> postMap) {
        //新增岗位
        SysDepart sysDepart = new SysDepart();
        JSONObject formData = new JSONObject();
        formData.put("parentId", depId);
        String[] codeArray = (String[]) FillRuleUtil.executeRule(FillRuleConstant.DEPART, formData);
        sysDepart.setParentId(depId);
        sysDepart.setOrgCode(codeArray[0]);
        sysDepart.setOrgType(codeArray[1]);
        sysDepart.setTenantId(tenantId);
        sysDepart.setDepartName(mainDepPostName);
        sysDepart.setIzLeaf(CommonConstant.IS_LEAF);
        sysDepart.setDelFlag(String.valueOf(CommonConstant.DEL_FLAG_0));
        sysDepart.setStatus(CommonConstant.STATUS_1);
        sysDepart.setOrgCategory(DepartCategoryEnum.DEPART_CATEGORY_POST.getValue());
        //获取职级id
        String positionId = "";
        if (postionMap.containsKey(postName)) {
            positionId = postionMap.get(postName);
        } else {
            //根据租户id和职级名称获取职级id
            positionId = this.getSysPosition(tenantId, postName);
        }
        sysDepart.setPositionId(positionId);
        postionMap.put(postName, positionId);
        sysDepartMapper.insert(sysDepart);
        sysDepartMapper.setMainLeaf(depId, CommonConstant.NOT_LEAF);
        postMap.put(mainDepPostName + depId, sysDepart.getId());
        //需要将用户表的主岗位进行关联
        return sysDepart.getId();
    }

    /**
     * 添加兼职岗位
     *
     * @param userId           用户id
     * @param departId         部门id【上级部门id】
     * @param postName         职级名称
     * @param otherDepPostName 兼职岗位名称
     * @param postMap          岗位map key：岗位名称 + 部门id value：岗位（部门id）
     * @param tenantId         租户id
     * @param postionMap       职级map key: 职级名称 value: 职级id
     */
    private void insertOtherDepartPost(String userId, String depId, String postName, String otherDepPostName, Map<String, String> postMap, Integer tenantId, Map<String, String> positionMap) {
        String[] otherDepPostNames = otherDepPostName.split(SymbolConstant.SEMICOLON);
        for (int i = 0; i < otherDepPostNames.length; i++) {
            //当前部门下已经存在岗位就不需要再次添加岗位了
            String departId = "";
            if (null == postMap || !postMap.containsKey(otherDepPostNames[i] + depId)) {
                //不存在时新增部门岗位
                departId = this.addCommontDepartPost(depId, tenantId, otherDepPostNames[i], positionMap, postName, postMap);
            } else {
                departId = postMap.get(otherDepPostNames[i] + depId);
            }
            //插入用岗位第三方中间表
            if (oConvertUtils.isNotEmpty(departId)) {
                try {
                    SysUserDepPost depPost = new SysUserDepPost(userId, departId);
                    depPostMapper.insert(depPost);
                } catch (Exception e) {
                    log.error("当前岗位插入失败：" + e.getMessage(), e);
                }
            }
        }
    }

    /**
     * 获取职务信息
     *
     * @param tenantId
     * @param postName
     * @return
     */
    private String getSysPosition(Integer tenantId, String postName) {
        tenantId = oConvertUtils.getInt(tenantId,0);
        Page<SysPosition> page = new Page<>(1, 1);
        List<String> namePage = sysPositionMapper.getPositionIdByName(postName, tenantId, page);
        if (CollectionUtil.isNotEmpty(namePage)) {
            return namePage.get(0);
        }
        return "";
    }
    //================================================================ end 【用户导入】导入时 部门添加层级不对了======================================================================
    
    private void saveChargeDepart(SysUser sysUser, String departIds, Map<String, SysDepart> departMap) {
        //判断那些部门没有，即没有加入到部门，则不能成为负责部门人员
        if (oConvertUtils.isEmpty(departIds)) {
            return;
        }
        //多个部门用;分隔开
        String[] split = departIds.split(SymbolConstant.SEMICOLON);
        //负责部门id
        StringBuilder departIdBulider = new StringBuilder();
        for (String name : split) {
            if (departMap.containsKey(name)) {
                SysDepart sysDepart = departMap.get(name);
                departIdBulider.append(sysDepart.getId()).append(",");
            }
        }
        // 检查并删除最后一个逗号
        if (departIdBulider.length() > 0 && departIdBulider.charAt(departIdBulider.length() - 1) == ',') {
            departIdBulider.deleteCharAt(departIdBulider.length() - 1);
        }
        SysUser user = new SysUser();
        user.setId(sysUser.getId());
        user.setDepartIds(departIdBulider.toString());
        this.updateById(user);
    }

    /**
     * 保存或编辑角色
     *
     * @param userId
     * @param roleNames
     * @param tenantIdInt
     */
    private void saveOrEditRole(String userId, String roleNames, Integer tenantIdInt) {
        if (oConvertUtils.isEmpty(roleNames)) {
            return;
        }
        String[] roleNameArray = roleNames.split(SymbolConstant.SEMICOLON);
        //删除用户下的角色
        LambdaQueryWrapper<SysUserRole> deleteQuery = new LambdaQueryWrapper<>();
        deleteQuery.eq(SysUserRole::getUserId, userId);
        sysUserRoleMapper.delete(deleteQuery);
        //通过名字获取角色
        LambdaQueryWrapper<SysRole> roleQuery = new LambdaQueryWrapper<>();
        roleQuery.orderByDesc(SysRole::getCreateTime);
        if (MybatisPlusSaasConfig.OPEN_SYSTEM_TENANT_CONTROL) {
            roleQuery.eq(SysRole::getTenantId, tenantIdInt);
        }
        for (String roleName : roleNameArray) {
            roleQuery.eq(SysRole::getRoleName, roleName);
            List<SysRole> sysRoles = sysRoleMapper.selectList(roleQuery);
            String roleId = "";
            if (CollectionUtil.isNotEmpty(sysRoles)) {
                roleId = sysRoles.get(0).getId();
            } else {
                SysRole sysRole = new SysRole();
                sysRole.setRoleName(roleName);
                sysRole.setRoleCode(RandomUtil.randomString(10));
                sysRoleMapper.insert(sysRole);
                roleId = sysRole.getId();
            }
            SysUserRole sysUserRole = new SysUserRole();
            sysUserRole.setUserId(userId);
            sysUserRole.setRoleId(roleId);
            sysUserRoleMapper.insert(sysUserRole);
        }
    }
    //================================================= end 低代码部门导入导出 ================================================================

    @Override
    public void updatePasswordNotBindPhone(String oldPassword, String password, String username) {
        LoginUser sysUser = (LoginUser)SecurityUtils.getSubject().getPrincipal();
        //step1 只能修改自己的密码
        if(!sysUser.getUsername().equals(username)){
            throw new JeecgBootBizTipException("只允许修改自己的密码！");
        }
        //step2 用户不存在禁止修改密码
        SysUser user = this.getUserByName(username);
        if(null == user){
            throw new JeecgBootBizTipException("用户不存在，无法修改密码！");
        }
        //setp3 如果手机号存在需要用手机号修改密码的方式
        if(oConvertUtils.isNotEmpty(user.getPhone())){
            throw new JeecgBootBizTipException("手机号不为空，请根据手机号进行修改密码操作！");
        }
        //step4 判断旧密码是否正确
        String passwordEncode = PasswordUtil.encrypt(username, oldPassword, user.getSalt());
        if (!user.getPassword().equals(passwordEncode)) {
            throw new JeecgBootBizTipException("旧密码输入错误!");
        }
        if (oConvertUtils.isEmpty(password)) {
            throw new JeecgBootBizTipException("新密码不允许为空!");
        }
        //step5 修改密码
        String newPassWord = PasswordUtil.encrypt(username, password, user.getSalt());
        this.userMapper.update(new SysUser().setPassword(newPassWord).setLastPwdUpdateTime(new Date()), new LambdaQueryWrapper<SysUser>().eq(SysUser::getId, user.getId()));
    }

	/**
	 *
	 * @param userName
	 * @return
	 */
	@Override
	public Map<String, String> queryUserAndDeptByName(String userName) {
		// 返回用户和部门信息（根据需求调整）
		Map<String, String> result = new HashMap<>();
		SysUser user = this.getUserByName(userName);
		result.put("userId", user.getId());
		result.put("username", user.getUsername());
		//用户的部门信息
		String orgCode = user.getOrgCode();
		if (oConvertUtils.isEmpty(orgCode)) {
			return result;
		}

		// 查询公司部门
		String companyName  = Optional.ofNullable(sysDepartMapper.queryCompByOrgCode(orgCode))
				.map(SysDepart::getDepartName)
				.orElse("");

		// 查询用户部门并匹配
		String userDeptName = sysDepartMapper.queryDepartsByUsername(userName).stream()
				.filter(depart -> orgCode.equals(depart.getOrgCode()))
				.findFirst()
				.map(SysDepart::getDepartName)
				.orElse("");

		// 设置部门显示文本
		String compDepart;
		if (StringUtils.isNotEmpty(companyName) && StringUtils.isNotEmpty(userDeptName)) {
			compDepart = companyName.equals(userDeptName)
					? companyName
					: companyName + "-" + userDeptName;
		} else {
			compDepart = StringUtils.isNotEmpty(companyName) ? companyName : userDeptName;
		}
		result.put("compDepart", compDepart);
		return result;
	}

    /**
     * 查询部门、岗位下的用户 包括子部门下的用户
     * 
     * @param orgCode
     * @param userParams
     * @param page
     * @return
     */
    @Override
    public IPage<SysUserSysDepPostModel> queryDepartPostUserByOrgCode(String orgCode, SysUser userParams, IPage page) {
        List<SysUserSysDepPostModel> sysDepartModels = baseMapper.queryDepartPostUserByOrgCode(page, orgCode, userParams);
        if(CollectionUtil.isNotEmpty(sysDepartModels)){
            List<String> userIds = sysDepartModels.stream().map(SysUserSysDepPostModel::getId).toList();
            //获取部门名称
            Map<String, String> useDepNames = this.getDepNamesByUserIds(userIds);
            sysDepartModels.forEach(item -> {
                List<String> positionList = sysUserPositionMapper.getPositionIdByUserId(item.getId());
                item.setPost(CommonUtils.getSplitText(positionList,SymbolConstant.COMMA));
                item.setOrgCodeTxt(useDepNames.get(item.getId()));
                //查询用户的租户ids
                List<Integer> list = userTenantMapper.getTenantIdsByUserId(item.getId());
                if (oConvertUtils.isNotEmpty(list)) {
                    item.setRelTenantIds(StringUtils.join(list.toArray(), SymbolConstant.COMMA));
                } else {
                    item.setRelTenantIds("");
                }
                //兼职岗位
                List<String> depPostList = depPostMapper.getDepPostByUserId(item.getId());
                if(CollectionUtil.isNotEmpty(depPostList)){
                    item.setOtherDepPostId(StringUtils.join(depPostList.toArray(), SymbolConstant.COMMA));
                }
            });
        }
        return page.setRecords(sysDepartModels);
    }

    /**
     * 据 orgCode 查询用户信息（部门全路径，主岗位和兼职岗位的信息），包括公司、子公司、部门
     *
     * @param orgCode
     * @param userParams
     * @param page
     * @return
     */
    @Override
    public IPage<SysUserSysDepPostModel> queryDepartUserByOrgCode(String orgCode, SysUser userParams, IPage page) {
        List<SysUserSysDepPostModel> sysDepartModels = baseMapper.queryDepartUserByOrgCode(page, orgCode, userParams);
        //用户id
        List<String> userIdList = sysDepartModels.stream().map(SysUserSysDepPostModel::getId).toList();
        if (CollectionUtil.isNotEmpty(userIdList)) {
            //根据用户ids获取部门名称 key 用户id value 部门名称
            Map<String, String> departNameMap = this.getDepartNamesByUserIds(userIdList, SymbolConstant.COMMA);
            //获取兼职岗位
            Map<String, String> departPostMap = this.getDepartOtherPostByUserIds(userIdList, SymbolConstant.COMMA);
            ISysDepartService service = SpringContextUtils.getBean(SysDepartServiceImpl.class);
            sysDepartModels.forEach(item -> {
                item.setDepartName(departNameMap.get(item.getId()));
                item.setOtherPostName(departPostMap.get(item.getId()));
                //获取主岗位全路径
                if (oConvertUtils.isNotEmpty(item.getMainDepPostId())) {
                    SysDepart departById = sysDepartMapper.getDepartById(item.getMainDepPostId());
                    if (null != departById) {
                        String departPathName = service.getDepartPathNameByOrgCode(departById.getOrgCode(), "");
                        item.setPostName(departPathName);
                    }
                }
            });
        }
        return page.setRecords(sysDepartModels);
    }

    /**
     * 通讯录点击用户获取用户详情（包含用户基本信息、部门全路径、主岗位兼职岗位全路径）
     *
     * @param userId
     * @return
     */
    @Override
    public SysUserSysDepPostModel getUserDetailByUserId(String userId) {
        SysUser sysUser = baseMapper.selectById(userId);
        if (null != sysUser) {
            SysUserSysDepPostModel userModel = new SysUserSysDepPostModel();
            BeanUtils.copyProperties(sysUser, userModel);
            //获取部门名称
            List<String> userIds = new ArrayList<>();
            userIds.add(userId);
            Map<String, String> departNameMap = this.getDepartNamesByUserIds(userIds, "__");
            userModel.setDepartName(departNameMap.get(userId));
            ISysDepartService service = SpringContextUtils.getBean(SysDepartServiceImpl.class);
            //获取主岗位全路径
            if (oConvertUtils.isNotEmpty(sysUser.getMainDepPostId())) {
                SysDepart departById = sysDepartMapper.getDepartById(sysUser.getMainDepPostId());
                if (null != departById) {
                    String departPathName = service.getDepartPathNameByOrgCode(departById.getOrgCode(), "");
                    userModel.setPostName(departPathName);
                }
            }
            //获取兼职岗位全路径
            Map<String, String> departPostMap = this.getDepartOtherPostByUserIds(userIds, "__");
            userModel.setOtherPostName(departPostMap.get(userId));
            return userModel;
        }
        return null;
    }

	/**
	 * 登录获取用户部门信息
	 * @param jsonObject
	 * @return
	 */
	@Override
	public Result loginGetUserDeparts(JSONObject jsonObject) {
		Result result = new Result<>();
		//返回内容
		JSONObject obj = new JSONObject(new LinkedHashMap<>());
		// 登录方式 phone:手机 account:账号密码
		String loginType = jsonObject.getString("loginType");
		String username = jsonObject.getString("username");
		String source = oConvertUtils.getString(jsonObject.getString("source"),"PC");
		// 手机号登录校验
		if("phone".equalsIgnoreCase(loginType)){
			String phone = jsonObject.getString("mobile");
			//1.校验用户有效性
			SysUser sysUser = baseMapper.getUserByPhone(phone);
			result = this.checkUserIsEffective(sysUser);
			if(!result.isSuccess()) {
				return result;
			}
			//2.校验验证码
			String smscode = jsonObject.getString("smscode");
			String redisKey = CommonConstant.PHONE_REDIS_KEY_PRE+phone;
			Object code = redisUtil.get(redisKey);
			if (!smscode.equals(code)) {
				return Result.error("手机验证码错误");
			}
			//3.当前登录账号
			username = sysUser.getUsername();
			String orgCode = sysUser.getOrgCode();
			obj.put("currentOrgCode", orgCode);
		}else{
			String password  = AesEncryptUtil.resolvePassword(jsonObject.getString("password"));
			log.debug("登录密码，原始密码:{}，解密密码:{}" , jsonObject.getString("password"), password);
            // 手机端没有验证码，不做校验
			if(!"APP".equalsIgnoreCase(source)){
				// step.1 验证码check
				SysLoginModel sysLoginModel = new SysLoginModel();
				String inputCode = jsonObject.getString("inputCode");
				String checkKey = jsonObject.getString("checkKey");
				sysLoginModel.setCaptcha(inputCode);
				sysLoginModel.setCheckKey(checkKey);
				if (inputCode == null) {
					result.error500("验证码无效");
					return result;
				}
				String lowerCaseCaptcha = inputCode.toLowerCase();
				String keyPrefix = Md5Util.md5Encode(sysLoginModel.getCheckKey() + jeecgBaseConfig.getSignatureSecret(), "utf-8");
				String realKey = keyPrefix + lowerCaseCaptcha;
				Object checkCode = redisUtil.get(realKey);
				if (checkCode == null || !checkCode.toString().equals(lowerCaseCaptcha)) {
					log.warn("验证码错误，key= {} , Ui checkCode= {}, Redis checkCode = {}", sysLoginModel.getCheckKey(), lowerCaseCaptcha, checkCode);
					result.error500("验证码错误");
					result.setCode(HttpStatus.PRECONDITION_FAILED.value());
					return result;
				}
			}

			// step.2 校验用户是否存在且有效
			SysUser sysUser = baseMapper.getUserByName(username);
			result = this.checkUserIsEffective(sysUser);
			if(!result.isSuccess()) {
				return result;
			}

			// step.3 校验用户名或密码是否正确
			String userpassword = PasswordUtil.encrypt(username, password, sysUser.getSalt());
			String syspassword = sysUser.getPassword();
			if (!syspassword.equals(userpassword)) {
				result.error500("用户名或密码错误");
				return result;
			}
			String orgCode = sysUser.getOrgCode();
			obj.put("currentOrgCode", orgCode);
		}
		//  step.4 获取用户部门信息，仅限部门
		List<SysDepart> departList = sysDepartMapper.queryDeptByUserAndCategory(username,DepartCategoryEnum.DEPART_CATEGORY_DEPART.getValue());
		if (CollectionUtil.isNotEmpty(departList)) {
			ISysDepartService service = SpringContextUtils.getBean(SysDepartServiceImpl.class);
			List<Map<String, String>> departs = departList.stream()
				.filter(depart -> oConvertUtils.isNotEmpty(depart) &&
						oConvertUtils.isNotEmpty(depart.getOrgCode()))
				.map(depart -> {
					String departName = depart.getDepartNameAbbr();
					//简称是空的情况下，查询全路径名称
					if(oConvertUtils.isEmpty(departName)){
						departName = service.getDepartPathNameByOrgCode(depart.getOrgCode(), "");
					}
					Map<String, String> map = new HashMap<>();
					map.put("orgCode", depart.getOrgCode());
					map.put("departName", departName);
					return map;
				})
				.collect(Collectors.toList());
			obj.put("departs", departs);
		}
		result.setResult(obj);
		return result;
	}

	/**
	 * 批量重置密码为系统密码
	 * @param usernames
	 */
	@Override
	public void resetToSysPassword(String usernames) {
		//1.判断是否存在admin账户
		if(hasAdminIntersection(usernames)){
			throw new JeecgBootException("所选用户中包含管理员，管理员账号不允许重置密码！！");
		}
		List<String> userArr = Arrays.asList(usernames.split(","));
		userArr.stream().forEach(username -> {
			if(oConvertUtils.isNotEmpty(username)){
				String salt = oConvertUtils.randomGen(8);
				String passwordEncode = PasswordUtil.encrypt(username, PasswordConstant.DEFAULT_PASSWORD, salt);
				//重置密码
				UpdateWrapper<SysUser> updateWrapper = new UpdateWrapper<>();
				updateWrapper
						.eq("username", username)
						.set("last_pwd_update_time", new Date())
						.set("password", passwordEncode)
						.set("salt", salt);
				this.baseMapper.update(null, updateWrapper);
			}
		});
	}

	/**
	 * 更新设备信息
	 * @param clientId
	 * @param userId
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void updateClientId(String clientId,String userId) {
		//解绑之前的设备账户
		if(oConvertUtils.isNotEmpty(clientId)){
			UpdateWrapper<SysUser> updateWrapper = new UpdateWrapper<>();
			updateWrapper
					.eq("client_id", clientId)
					.set("client_id", null);
			this.baseMapper.update(null, updateWrapper);
		}
		//设置新的绑定
		SysUser sysUser = new SysUser();
		sysUser.setClientId(clientId);
		sysUser.setId(userId);
		this.baseMapper.updateById(sysUser);
	}

	/**
	 * 是否有交集
	 */
	public static boolean hasAdminIntersection(String usernames) {
		if (oConvertUtils.isEmpty(usernames)) {
			return false;
		}
		// 使用HashSet提高查找效率
		Set<String> adminSet = Arrays.stream(ADMIN_ACCOUNT)
				.map(String::toLowerCase)
				.collect(Collectors.toSet());

		return Arrays.stream(usernames.split(SymbolConstant.COMMA))
				.map(String::trim)
				.map(String::toLowerCase)
				.anyMatch(adminSet::contains);
	}
	/**
     * 根据用户ids获取部门名称
     *
     * @param userIdList
     * @param symbol
     * @return
     */
    private Map<String, String> getDepartOtherPostByUserIds(List<String> userIdList, String symbol) {
        Map<String, String> departPostMap = new HashMap<>();
        List<SysUserSysDepPostModel> departPost = sysDepartMapper.getDepartOtherPostByUserIds(userIdList);
        if (CollectionUtil.isNotEmpty(departPost)) {
            ISysDepartService service = SpringContextUtils.getBean(SysDepartServiceImpl.class);
            departPost.forEach(item -> {
                if (oConvertUtils.isNotEmpty(item.getId()) && oConvertUtils.isNotEmpty(item.getOtherDepPostId())) {
                    String postName = service.getDepartPathNameByOrgCode(item.getOrgCode(), "");
                    if (departPostMap.containsKey(item.getId())) {
                        departPostMap.put(item.getId(), departPostMap.get(item.getId()) + symbol + postName);
                    } else {
                        departPostMap.put(item.getId(), postName);
                    }
                }
            });
        }
        return departPostMap;
    }

    /**
     * 根据用户ids获取部门名称
     *
     * @param userIdList
     * @param symbol
     * @return
     */
    private Map<String, String> getDepartNamesByUserIds(List<String> userIdList, String symbol) {
        Map<String, String> userOrgCodeMap = new HashMap<>();
        if (CollectionUtil.isNotEmpty(userIdList)) {
            List<SysUserSysDepPostModel> userDepPosts = sysUserDepartMapper.getUserDepPostByUserIds(userIdList);
            if (CollectionUtil.isNotEmpty(userDepPosts)) {
                ISysDepartService service = SpringContextUtils.getBean(SysDepartServiceImpl.class);
                userDepPosts.forEach(item -> {
                    if (oConvertUtils.isNotEmpty(item.getId()) && oConvertUtils.isNotEmpty(item.getOrgCode())) {
                        String departNamePath = service.getDepartPathNameByOrgCode(item.getOrgCode(), "");
                        if (userOrgCodeMap.containsKey(item.getId())) {
                            userOrgCodeMap.put(item.getId(), userOrgCodeMap.get(item.getId()) + symbol + departNamePath);
                        } else {
                            userOrgCodeMap.put(item.getId(), departNamePath);
                        }
                    }
                });
            }
        }
        return userOrgCodeMap;
    }
}
