package org.jeecg.modules.system.controller;


import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.PermissionData;
import org.jeecg.common.base.BaseMap;
import org.jeecg.common.config.TenantContext;
import org.jeecg.common.constant.CacheConstant;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.constant.PasswordConstant;
import org.jeecg.common.constant.SymbolConstant;
import org.jeecg.common.modules.redis.client.JeecgRedisClient;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.*;
import org.jeecg.config.JeecgBaseConfig;
import org.jeecg.config.mybatis.MybatisPlusSaasConfig;
import org.jeecg.modules.base.service.BaseCommonService;
import org.jeecg.modules.system.entity.*;
import org.jeecg.modules.system.excelstyle.ExcelExportSysUserStyle;
import org.jeecg.modules.system.model.DepartIdModel;
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.SysDepartUsersVO;
import org.jeecg.modules.system.vo.SysUserExportVo;
import org.jeecg.modules.system.vo.SysUserRoleVO;
import org.jeecg.modules.system.vo.lowapp.DepartAndUserInfo;
import org.jeecg.modules.system.vo.lowapp.UpdateDepartInfo;
import org.jeecgframework.poi.excel.def.NormalExcelConstants;
import org.jeecgframework.poi.excel.entity.ExportParams;
import org.jeecgframework.poi.excel.entity.enmus.ExcelType;
import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 用户表 前端控制器
 * </p>
 *
 * @Author scott
 * @since 2018-12-20
 */
@Slf4j
@RestController
@RequestMapping("/sys/user")
public class SysUserController {

	@Autowired
	private ISysUserService sysUserService;

    @Autowired
    private ISysDepartService sysDepartService;

	@Autowired
	private ISysUserRoleService sysUserRoleService;

	@Autowired
	private ISysUserDepartService sysUserDepartService;

    @Autowired
    private ISysDepartRoleUserService departRoleUserService;

    @Autowired
    private ISysDepartRoleService departRoleService;

	@Autowired
	private RedisUtil redisUtil;

    @Value("${jeecg.path.upload}")
    private String upLoadPath;

    @Autowired
    private BaseCommonService baseCommonService;

    @Autowired
    private ISysPositionService sysPositionService;

    @Autowired
    private ISysUserTenantService userTenantService;

    @Autowired
    private JeecgRedisClient jeecgRedisClient;
    @Autowired
    private JeecgBaseConfig jeecgBaseConfig;
    
    /**
     * 获取租户下用户数据（支持租户隔离）
     * @param user
     * @param pageNo
     * @param pageSize
     * @param req
     * @return
     */
    @PermissionData(pageComponent = "system/UserList")
	@RequestMapping(value = "/list", method = RequestMethod.GET)
	public Result<IPage<SysUser>> queryPageList(SysUser user,@RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
									  @RequestParam(name="pageSize", defaultValue="10") Integer pageSize,HttpServletRequest req) {
		QueryWrapper<SysUser> queryWrapper = QueryGenerator.initQueryWrapper(user, req.getParameterMap());
        //------------------------------------------------------------------------------------------------
        //是否开启系统管理模块的多租户数据隔离【SAAS多租户模式】
        if (MybatisPlusSaasConfig.OPEN_SYSTEM_TENANT_CONTROL) {
            String tenantId = oConvertUtils.getString(TenantContext.getTenant(), "-1");
            List<String> userIds = userTenantService.getUserIdsByTenantId(Integer.valueOf(tenantId));
            if (oConvertUtils.listIsNotEmpty(userIds)) {
                queryWrapper.in("id", userIds);
            }else{
                queryWrapper.eq("id", "通过租户查询不到任何用户");
            }
        }
        //------------------------------------------------------------------------------------------------
        return sysUserService.queryPageList(req, queryWrapper, pageSize, pageNo);
	}

    /**
     * 获取系统用户数据（查询全部用户，不做租户隔离）
     *
     * @param user
     * @param pageNo
     * @param pageSize
     * @param req
     * @return
     */
    @RequiresPermissions("system:user:listAll")
    @RequestMapping(value = "/listAll", method = RequestMethod.GET)
    public Result<IPage<SysUser>> queryAllPageList(SysUser user, @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                                   @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, HttpServletRequest req) {
        QueryWrapper<SysUser> queryWrapper = QueryGenerator.initQueryWrapper(user, req.getParameterMap());
        return sysUserService.queryPageList(req, queryWrapper, pageSize, pageNo);
    }

    @RequiresPermissions("system:user:add")
	@RequestMapping(value = "/add", method = RequestMethod.POST)
	public Result<SysUser> add(@RequestBody JSONObject jsonObject) {
		Result<SysUser> result = new Result<SysUser>();
		String selectedRoles = jsonObject.getString("selectedroles");
		String selectedDeparts = jsonObject.getString("selecteddeparts");
		try {
			SysUser user = JSON.parseObject(jsonObject.toJSONString(), SysUser.class);
			user.setCreateTime(new Date());//设置创建时间
			String salt = oConvertUtils.randomGen(8);
			user.setSalt(salt);
			String passwordEncode = PasswordUtil.encrypt(user.getUsername(), user.getPassword(), salt);
			user.setPassword(passwordEncode);
			user.setStatus(1);
			user.setDelFlag(CommonConstant.DEL_FLAG_0);
			//用户表字段org_code不能在这里设置他的值
            user.setOrgCode(null);
            user.setLastPwdUpdateTime(new Date());
			// 保存用户走一个service 保证事务
            //获取租户ids
            String relTenantIds = jsonObject.getString("relTenantIds");
            sysUserService.saveUser(user, selectedRoles, selectedDeparts, relTenantIds, false);
            baseCommonService.addLog("添加用户，username： " +user.getUsername() ,CommonConstant.LOG_TYPE_2, 2);
			result.success("添加成功！");
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			result.error500("操作失败");
		}
		return result;
	}

    @RequiresPermissions("system:user:edit")
	@RequestMapping(value = "/edit", method = {RequestMethod.PUT,RequestMethod.POST})
	public Result<SysUser> edit(@RequestBody JSONObject jsonObject) {
		Result<SysUser> result = new Result<SysUser>();
		try {
			SysUser sysUser = sysUserService.getById(jsonObject.getString("id"));
			baseCommonService.addLog("编辑用户，username： " +sysUser.getUsername() ,CommonConstant.LOG_TYPE_2, 2);
			if(sysUser==null) {
				result.error500("未找到对应实体");
			}else {
				SysUser user = JSON.parseObject(jsonObject.toJSONString(), SysUser.class);
				user.setUpdateTime(new Date());
				//String passwordEncode = PasswordUtil.encrypt(user.getUsername(), user.getPassword(), sysUser.getSalt());
				user.setPassword(sysUser.getPassword());
				String roles = jsonObject.getString("selectedroles");
                String departs = jsonObject.getString("selecteddeparts");
                if(oConvertUtils.isEmpty(departs)){
                    //vue3.0前端只传递了departIds
                    departs=user.getDepartIds();
                }
                //用户表字段org_code不能在这里设置他的值
                user.setOrgCode(null);
                // 修改用户走一个service 保证事务
                //获取租户ids
                String relTenantIds = jsonObject.getString("relTenantIds");
                String updateFromPage = jsonObject.getString("updateFromPage");
                //update-begin---author:wangshuai---date:2025-11-12---for:【JHHB-776】用户编辑，应该从数据库查出老数据，页面传递什么字段，把这些字段覆盖数据库查询结果，再更新---
                oConvertUtils.copyNonNullFields(user, sysUser);
                sysUserService.editUser(sysUser, roles, departs, relTenantIds, updateFromPage);
                //update-end---author:wangshuai---date:2025-11-12---for:【JHHB-776】用户编辑，应该从数据库查出老数据，页面传递什么字段，把这些字段覆盖数据库查询结果，再更新---
				result.success("修改成功!");
			}
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			result.error500("操作失败");
		}
		return result;
	}

    /**
     * 添加用户【后台租户模式专用，敲敲云不要用这个】
     *
     * @param jsonObject
     * @return
     */
    @RequiresPermissions("system:user:addTenantUser")
    @RequestMapping(value = "/addTenantUser", method = RequestMethod.POST)
    public Result<SysUser> addTenantUser(@RequestBody JSONObject jsonObject) {
        Result<SysUser> result = new Result<SysUser>();
        String selectedRoles = jsonObject.getString("selectedroles");
        String selectedDeparts = jsonObject.getString("selecteddeparts");
        try {
            SysUser user = JSON.parseObject(jsonObject.toJSONString(), SysUser.class);
            user.setCreateTime(new Date());//设置创建时间
            String salt = oConvertUtils.randomGen(8);
            user.setSalt(salt);
            String passwordEncode = PasswordUtil.encrypt(user.getUsername(), user.getPassword(), salt);
            user.setPassword(passwordEncode);
            user.setStatus(1);
            user.setDelFlag(CommonConstant.DEL_FLAG_0);
            //用户表字段org_code不能在这里设置他的值
            user.setOrgCode(null);
            // 保存用户走一个service 保证事务
            //获取租户ids
            String relTenantIds = jsonObject.getString("relTenantIds");
            sysUserService.saveUser(user, selectedRoles, selectedDeparts, relTenantIds, true);
            baseCommonService.addLog("添加用户，username： " + user.getUsername(), CommonConstant.LOG_TYPE_2, 2);
            result.success("添加成功！");
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            result.error500("操作失败");
        }
        return result;
    }

	/**
	 * 删除用户
	 */
    @RequiresPermissions("system:user:delete")
	@RequestMapping(value = "/delete", method = RequestMethod.DELETE)
	public Result<?> delete(@RequestParam(name="id",required=true) String id) {
		baseCommonService.addLog("删除用户，id： " +id ,CommonConstant.LOG_TYPE_2, 3);
        List<String> userNameList = sysUserService.userIdToUsername(Arrays.asList(id));
		this.sysUserService.deleteUser(id);

        if (!userNameList.isEmpty()) {
            String joinedString = String.join(",", userNameList);
        }
		return Result.ok("删除用户成功");
	}

	/**
	 * 批量删除用户
	 */
    @RequiresPermissions("system:user:deleteBatch")
	@RequestMapping(value = "/deleteBatch", method = RequestMethod.DELETE)
	public Result<?> deleteBatch(@RequestParam(name="ids",required=true) String ids) {
		baseCommonService.addLog("批量删除用户， ids： " +ids ,CommonConstant.LOG_TYPE_2, 3);
        List<String> userNameList = sysUserService.userIdToUsername(Arrays.asList(ids.split(",")));
		this.sysUserService.deleteBatchUsers(ids);
		
        // 用户变更，触发同步工作流
        if (!userNameList.isEmpty()) {
            String joinedString = String.join(",", userNameList);
        }
		return Result.ok("批量删除用户成功");
	}

	/**
	  * 冻结&解冻用户
	 * @param jsonObject
	 * @return
	 */
    @RequiresPermissions("system:user:frozenBatch")
	@RequestMapping(value = "/frozenBatch", method = RequestMethod.PUT)
	public Result<SysUser> frozenBatch(@RequestBody JSONObject jsonObject) {
		Result<SysUser> result = new Result<SysUser>();
		try {
			String ids = jsonObject.getString("ids");
			sysUserService.checkUserAdminRejectDel(ids);
			String status = jsonObject.getString("status");
			String[] arr = ids.split(",");
            for (String id : arr) {
				if(oConvertUtils.isNotEmpty(id)) {
                    // 代码逻辑说明: [QQYUN-5577]用户列表-冻结用户，再解冻之后，用户还是无法登陆，有缓存问题 #5066------------
                    sysUserService.updateStatus(id,status);
                }
			}
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			result.error500("操作失败"+e.getMessage());
		}
		result.success("操作成功!");
		return result;

    }
    /**
     * 重置为系统密码接口
     * @param usernames
     * @return
     */
    @RequiresRoles({"admin"})
    @RequiresPermissions("system:user:resetPassword")
	@RequestMapping(value = "/resetPassword", method = RequestMethod.PUT)
	public Result<SysUser> resetPassword(@RequestParam(name = "usernames") String usernames) {
		Result<SysUser> result = new Result<SysUser>();
		try {
            sysUserService.resetToSysPassword(usernames);
            result.success("操作成功!");
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			result.error500(e.getMessage());
		}
		return result;

    }

    @RequiresPermissions("system:user:queryById")
    @RequestMapping(value = "/queryById", method = RequestMethod.GET)
    public Result<SysUser> queryById(@RequestParam(name = "id", required = true) String id) {
        Result<SysUser> result = new Result<SysUser>();
        SysUser sysUser = sysUserService.getById(id);
        if (sysUser == null) {
            result.error500("未找到对应实体");
        } else {
            result.setResult(sysUser);
            result.setSuccess(true);
        }
        return result;
    }

    @RequiresPermissions("system:user:queryUserRole")
    @RequestMapping(value = "/queryUserRole", method = RequestMethod.GET)
    public Result<List<String>> queryUserRole(@RequestParam(name = "userid", required = true) String userid) {
        Result<List<String>> result = new Result<>();
        List<String> list = new ArrayList<String>();
        List<SysUserRole> userRole = sysUserRoleService.list(new QueryWrapper<SysUserRole>().lambda().eq(SysUserRole::getUserId, userid));
        if (userRole == null || userRole.size() <= 0) {
            result.error500("未找到用户相关角色信息");
        } else {
            for (SysUserRole sysUserRole : userRole) {
                list.add(sysUserRole.getRoleId());
            }
            result.setSuccess(true);
            result.setResult(list);
        }
        return result;
    }


    /**
	  *  校验用户账号是否唯一<br>
	  *  可以校验其他 需要检验什么就传什么。。。
     *
     * @param sysUser
     * @return
     */
    @RequestMapping(value = "/checkOnlyUser", method = RequestMethod.GET)
    public Result<Boolean> checkOnlyUser(SysUser sysUser) {
        Result<Boolean> result = new Result<>();
        //如果此参数为false则程序发生异常
        result.setResult(true);
        try {
            //通过传入信息查询新的用户信息
            sysUser.setPassword(null);
            SysUser user = sysUserService.getOne(new QueryWrapper<SysUser>(sysUser));
            if (user != null) {
                result.setSuccess(false);
                result.setMessage("用户账号已存在");
                return result;
            }

        } catch (Exception e) {
            result.setSuccess(false);
            result.setMessage(e.getMessage());
            return result;
        }
        result.setSuccess(true);
        return result;
    }

    /**
     * 修改密码
     */
    @RequiresPermissions("system:user:changepwd")
    @RequestMapping(value = "/changePassword", method = RequestMethod.PUT)
    public Result<?> changePassword(@RequestBody SysUser sysUser, HttpServletRequest request) {
        //-------------------------------------------------------------------------------------
        //增加 check防止恶意刷短信接口
        String clientIp = IpUtils.getIpAddr(request);
        if(!DySmsLimit.canSendSms(clientIp)){
            log.warn("-------- IP地址:{}, 短信接口请求太多，有攻击风险！", clientIp);
            return Result.error("短信接口请求太多，请稍后再试！");
        }
        //-------------------------------------------------------------------------------------
        SysUser u = this.sysUserService.getOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUsername, sysUser.getUsername()));
        if (u == null) {
            return Result.error("用户不存在！");
        }
        sysUser.setId(u.getId());
        // 代码逻辑说明: [VUEN-234]修改密码添加敏感日志------------
        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        baseCommonService.addLog("修改用户 "+sysUser.getUsername()+" 的密码，操作人： " +loginUser.getUsername() ,CommonConstant.LOG_TYPE_2, 2);
        return sysUserService.changePassword(sysUser);
    }

    /**
     * 查询指定用户和部门关联的数据
     *
     * @param userId
     * @return
     */
    @RequestMapping(value = "/userDepartList", method = RequestMethod.GET)
    public Result<List<DepartIdModel>> getUserDepartsList(@RequestParam(name = "userId", required = true) String userId) {
        Result<List<DepartIdModel>> result = new Result<>();
        try {
            List<DepartIdModel> depIdModelList = this.sysUserDepartService.queryDepartIdsOfUser(userId);
            if (depIdModelList != null && depIdModelList.size() > 0) {
                result.setSuccess(true);
                result.setMessage("查找成功");
                result.setResult(depIdModelList);
            } else {
                result.setSuccess(false);
                result.setMessage("查找失败");
            }
            return result;
        } catch (Exception e) {
        	log.error(e.getMessage(), e);
            result.setSuccess(false);
            result.setMessage("查找过程中出现了异常: " + e.getMessage());
            return result;
        }

    }

    /**
     * 生成在添加用户情况下没有主键的问题,返回给前端,根据该id绑定部门数据
     *
     * @return
     */
    @RequestMapping(value = "/generateUserId", method = RequestMethod.GET)
    public Result<String> generateUserId() {
        Result<String> result = new Result<>();
        //System.out.println("我执行了,生成用户ID==============================");
        String userId = UUID.randomUUID().toString().replace("-", "");
        result.setSuccess(true);
        result.setResult(userId);
        return result;
    }

    /**
     * 根据部门id查询用户信息
     *
     * @param id
     * @return
     */
    @RequestMapping(value = "/queryUserByDepId", method = RequestMethod.GET)
    public Result<List<SysUser>> queryUserByDepId(@RequestParam(name = "id", required = true) String id,@RequestParam(name="realname",required=false) String realname) {
        Result<List<SysUser>> result = new Result<>();
        //List<SysUser> userList = sysUserDepartService.queryUserByDepId(id);
        SysDepart sysDepart = sysDepartService.getById(id);
        List<SysUser> userList = sysUserDepartService.queryUserByDepCode(sysDepart.getOrgCode(),realname);

        //批量查询用户的所属部门
        //step.1 先拿到全部的 useids
        //step.2 通过 useids，一次性查询用户的所属部门名字
        List<String> userIds = userList.stream().map(SysUser::getId).collect(Collectors.toList());
        if(userIds!=null && userIds.size()>0){
            Map<String,String>  useDepNames = sysUserService.getDepNamesByUserIds(userIds);
            userList.forEach(item->{
                //TODO 临时借用这个字段用于页面展示
                item.setOrgCodeTxt(useDepNames.get(item.getId()));
            });
        }

        try {
            result.setSuccess(true);
            result.setResult(userList);
            return result;
        } catch (Exception e) {
        	log.error(e.getMessage(), e);
            result.setSuccess(false);
            return result;
        }
    }

    /**
     * 用户选择组件 专用  根据用户账号或部门分页查询
     * @param departId
     * @param username
     * @return
     */
    @RequestMapping(value = "/queryUserComponentData", method = RequestMethod.GET)
    public Result<IPage<SysUser>> queryUserComponentData(
            @RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
            @RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
            @RequestParam(name = "departId", required = false) String departId,
            @RequestParam(name="realname",required=false) String realname,
            @RequestParam(name="username",required=false) String username,
            @RequestParam(name="isMultiTranslate",required=false) String isMultiTranslate,
            @RequestParam(name="id",required = false) String id) {
        // 代码逻辑说明: VUEN-1702【禁止问题】sql注入漏洞
        String[] arr = new String[]{departId, realname, username, id};
        SqlInjectionUtil.filterContent(arr, SymbolConstant.SINGLE_QUOTATION_MARK);
        IPage<SysUser> pageList = sysUserDepartService.queryDepartUserPageList(departId, username, realname, pageSize, pageNo,id,isMultiTranslate);
        return Result.OK(pageList);
    }

    /**
     * 导出excel
     *
     * @param request
     * @param sysUser
     */
    @RequiresPermissions("system:user:export")
    @RequestMapping(value = "/exportXls")
    public ModelAndView exportXls(SysUser sysUser,HttpServletRequest request) {
        // Step.1 组装查询条件
        QueryWrapper<SysUser> queryWrapper = QueryGenerator.initQueryWrapper(sysUser, request.getParameterMap());
        queryWrapper.ne("username", "_reserve_user_external");
        //Step.2 AutoPoi 导出Excel
        ModelAndView mv = new ModelAndView(new JeecgEntityExcelView());
        // 代码逻辑说明: [03]用户导出，如果选择数据则只导出相关数据--------------------
        String selections = request.getParameter("selections");
       if(!oConvertUtils.isEmpty(selections)){
           queryWrapper.in("id",selections.split(","));
       }
        //是否存在部门id
        boolean izDepartId = true;
        String departId = request.getParameter("departId");
        if (oConvertUtils.isNotEmpty(departId)) {
            LambdaQueryWrapper<SysUserDepart> query = new LambdaQueryWrapper<>();
            query.in(SysUserDepart::getDepId, Arrays.asList(departId.split(",")));
            List<SysUserDepart> list = sysUserDepartService.list(query);
            List<String> userIds = list.stream().map(SysUserDepart::getUserId).collect(Collectors.toList());
            if (oConvertUtils.listIsNotEmpty(userIds)) {
                queryWrapper.in("id", userIds);
            }else{
                izDepartId = false;
            }
        }
        List<SysUserExportVo> list = new ArrayList<>();
        // 代码逻辑说明: 【JHHB-762】【用户管理】需要支持按组织架构查询用户---
        if(izDepartId){
            List<SysUser> pageList = sysUserService.list(queryWrapper);
            list  = sysUserService.getDepartAndRoleExportMsg(pageList);
        }
        //导出文件名称
        mv.addObject(NormalExcelConstants.FILE_NAME, "用户列表");
        mv.addObject(NormalExcelConstants.CLASS, SysUserExportVo.class);
		LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        ExportParams exportParams = new ExportParams("导入规则：\n" +
                "1. 用户名为必填项，仅支持新增数据导入；\n" +
                "2. 多个部门、角色或负责部门请用英文分号 ; 分隔，如：财务部;研发部；\n" +
                "3. 部门层级请用英文斜杠 / 分隔，如：北京公司/财务部/财务一部；\n" +
                "4. 部门类型需与部门层级一致，也用 / 分隔，如：公司/部门/部门 或 1/3/3，多个类型用 ; 分隔。机构类型编码：公司(1)，子公司(4)，部门(3)；\n" +
                "5. 部门根据用户名匹配，若存在多个则关联最新创建的部门，不存在时自动新增；\n" +
                "6. 负责部门与所属部门导入规则一致，若所属部门不包含负责部门，则不关联负责部门；\n" +
                "7. 用户主岗位导入时会在部门下自动创建新岗位，职级为空时默认不与岗位建立关联。", "导出人：" + user.getRealname(), "导出信息");
        exportParams.setTitleHeight((short)70);
        exportParams.setStyle(ExcelExportSysUserStyle.class);
        exportParams.setImageBasePath(upLoadPath);
        //导出为xlsx
        exportParams.setType(ExcelType.XSSF);
        mv.addObject(NormalExcelConstants.PARAMS, exportParams);
        mv.addObject(NormalExcelConstants.DATA_LIST, list);
        //用户导出支持导出字段
        String exportFields = request.getParameter(NormalExcelConstants.EXPORT_FIELDS);
        if(oConvertUtils.isNotEmpty(exportFields)){
            mv.addObject(NormalExcelConstants.EXPORT_FIELDS, exportFields);
        }
        return mv;
    }

    /**
     * 通过excel导入数据
     *
     * @param request
     * @param response
     * @return
     */
    @RequiresPermissions("system:user:import")
    @RequestMapping(value = "/importExcel", method = RequestMethod.POST)
    public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response)throws IOException {
        //return ImportOldUserUtil.importOldSysUser(request);
        return sysUserService.importSysUser(request);
    }

    /**
	 * @功能：根据id 批量查询
	 * @param userIds
	 * @return
	 */
	@RequestMapping(value = "/queryByIds", method = RequestMethod.GET)
	public Result<Collection<SysUser>> queryByIds(@RequestParam(name = "userIds") String userIds) {
		Result<Collection<SysUser>> result = new Result<>();
		String[] userId = userIds.split(",");
		Collection<String> idList = Arrays.asList(userId);
		Collection<SysUser> userRole = sysUserService.listByIds(idList);
		result.setSuccess(true);
		result.setResult(userRole);
		return result;
	}


    /**
     * @功能：根据id 批量查询
     * @param userNames
     * @return
     */
    @RequestMapping(value = "/queryByNames", method = RequestMethod.GET)
    public Result<Collection<SysUser>> queryByNames(@RequestParam(name = "userNames") String userNames) {
        Result<Collection<SysUser>> result = new Result<>();
        String[] names = userNames.split(",");
        QueryWrapper<SysUser> queryWrapper=new QueryWrapper();
        queryWrapper.lambda().in(true,SysUser::getUsername,names);
        Collection<SysUser> userRole = sysUserService.list(queryWrapper);
        result.setSuccess(true);
        result.setResult(userRole);
        return result;
    }

    /**
     * @功能：根据userName查询用户以及部门信息
     * @param userName
     * @return
     */
    @RequestMapping(value = "/queryUserAndDeptByName", method = RequestMethod.GET)
    public Result<Map<String,String>> queryUserAndDeptByName(@RequestParam(name = "userName") String userName) {
        Map<String,String> userInfo= sysUserService.queryUserAndDeptByName(userName);
        return Result.ok(userInfo);
    }

	/**
	 * 首页用户重置密码
	 */
    @RequiresPermissions("system:user:updatepwd")
    @RequestMapping(value = "/updatePassword", method = RequestMethod.PUT)
	public Result<?> updatePassword(@RequestBody JSONObject json) {
		String username = json.getString("username");
		String oldpassword = json.getString("oldpassword");
		String password = json.getString("password");
		String confirmpassword = json.getString("confirmpassword");
        LoginUser sysUser = (LoginUser)SecurityUtils.getSubject().getPrincipal();
        if(!sysUser.getUsername().equals(username)){
            return Result.error("只允许修改自己的密码！");
        }
		SysUser user = this.sysUserService.getOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUsername, username));
		if(user==null) {
			return Result.error("用户不存在！");
		}
        // 代码逻辑说明: [VUEN-234]修改密码添加敏感日志------------
        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        baseCommonService.addLog("修改密码，username： " +loginUser.getUsername() ,CommonConstant.LOG_TYPE_2, 2);
		return sysUserService.resetPassword(username,oldpassword,password,confirmpassword);
	}

    @RequestMapping(value = "/userRoleList", method = RequestMethod.GET)
    public Result<IPage<SysUser>> userRoleList(@RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
                                               @RequestParam(name="pageSize", defaultValue="10") Integer pageSize, HttpServletRequest req) {
        Result<IPage<SysUser>> result = new Result<IPage<SysUser>>();
        Page<SysUser> page = new Page<SysUser>(pageNo, pageSize);
        String roleId = req.getParameter("roleId");
        String username = req.getParameter("username");
        String realname = req.getParameter("realname");
        IPage<SysUser> pageList = sysUserService.getUserByRoleId(page,roleId,username,realname);
        result.setSuccess(true);
        result.setResult(pageList);
        return result;
    }

    /**
     * 给指定角色添加用户
     *
     * @param
     * @return
     */
    @RequiresPermissions("system:user:addUserRole")
    @RequestMapping(value = "/addSysUserRole", method = RequestMethod.POST)
    public Result<String> addSysUserRole(@RequestBody SysUserRoleVO sysUserRoleVO) {
        Result<String> result = new Result<String>();
        //TODO 判断当前操作的角色是当前登录租户下的
        try {
            String sysRoleId = sysUserRoleVO.getRoleId();
            for(String sysUserId:sysUserRoleVO.getUserIdList()) {
                SysUserRole sysUserRole = new SysUserRole(sysUserId,sysRoleId);
                QueryWrapper<SysUserRole> queryWrapper = new QueryWrapper<SysUserRole>();
                queryWrapper.eq("role_id", sysRoleId).eq("user_id",sysUserId);
                SysUserRole one = sysUserRoleService.getOne(queryWrapper);
                if(one==null){
                    sysUserRoleService.save(sysUserRole);
                }

            }
            result.setMessage("添加成功!");
            result.setSuccess(true);
            return result;
        }catch(Exception e) {
            log.error(e.getMessage(), e);
            result.setSuccess(false);
            result.setMessage("出错了: " + e.getMessage());
            return result;
        }
    }
    /**
     *   删除指定角色的用户关系
     * @param
     * @return
     */
    @RequiresPermissions("system:user:deleteRole")
    @RequestMapping(value = "/deleteUserRole", method = RequestMethod.DELETE)
    public Result<SysUserRole> deleteUserRole(@RequestParam(name="roleId") String roleId,
                                                    @RequestParam(name="userId",required=true) String userId
    ) {
        Result<SysUserRole> result = new Result<SysUserRole>();
        try {
            QueryWrapper<SysUserRole> queryWrapper = new QueryWrapper<SysUserRole>();
            queryWrapper.eq("role_id", roleId).eq("user_id",userId);
            sysUserRoleService.remove(queryWrapper);
            result.success("删除成功!");
        }catch(Exception e) {
            log.error(e.getMessage(), e);
            result.error500("删除失败！");
        }
        return result;
    }

    /**
     * 批量删除指定角色的用户关系
     *
     * @param
     * @return
     */
    @RequiresPermissions("system:user:deleteRoleBatch")
    @RequestMapping(value = "/deleteUserRoleBatch", method = RequestMethod.DELETE)
    public Result<SysUserRole> deleteUserRoleBatch(
            @RequestParam(name="roleId") String roleId,
            @RequestParam(name="userIds",required=true) String userIds) {
        Result<SysUserRole> result = new Result<SysUserRole>();
        try {
            QueryWrapper<SysUserRole> queryWrapper = new QueryWrapper<SysUserRole>();
            queryWrapper.eq("role_id", roleId).in("user_id",Arrays.asList(userIds.split(",")));
            sysUserRoleService.remove(queryWrapper);
            result.success("删除成功!");
        }catch(Exception e) {
            log.error(e.getMessage(), e);
            result.error500("删除失败！");
        }
        return result;
    }

    /**
     * 部门用户列表
     */
    @RequestMapping(value = "/departUserList", method = RequestMethod.GET)
    public Result<IPage<SysUser>> departUserList(@RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
                                                 @RequestParam(name="pageSize", defaultValue="10") Integer pageSize, HttpServletRequest req) {
        Result<IPage<SysUser>> result = new Result<IPage<SysUser>>();
        Page<SysUser> page = new Page<SysUser>(pageNo, pageSize);
        String depId = req.getParameter("depId");
        String username = req.getParameter("username");
        //根据部门ID查询,当前和下级所有的部门IDS
        List<String> subDepids = new ArrayList<>();
        //部门id为空时，查询我的部门下所有用户
        if(oConvertUtils.isEmpty(depId)){
            LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal();
            int userIdentity = user.getUserIdentity() != null?user.getUserIdentity():CommonConstant.USER_IDENTITY_1;
            // 代码逻辑说明: [QQYUN-10775]验证码可以复用 #7674------------
            if(oConvertUtils.isNotEmpty(userIdentity) && userIdentity == CommonConstant.USER_IDENTITY_2
                    && oConvertUtils.isNotEmpty(user.getDepartIds())) {
                subDepids = sysDepartService.getMySubDepIdsByDepId(user.getDepartIds());
            }
        }else{
            subDepids = sysDepartService.getSubDepIdsByDepId(depId);
        }
        if(subDepids != null && subDepids.size()>0){
            IPage<SysUser> pageList = sysUserService.getUserByDepIds(page,subDepids,username);
            //批量查询用户的所属部门
            //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 = sysUserService.getDepNamesByUserIds(userIds);
                pageList.getRecords().forEach(item -> {
                    //批量查询用户的所属部门
                    item.setOrgCode(useDepNames.get(item.getId()));
                });
            }
            //设置租户id
            page.setRecords(userTenantService.setUserTenantIds(page.getRecords()));
            result.setSuccess(true);
            result.setResult(pageList);
        }else{
            result.setSuccess(true);
            result.setResult(null);
        }
        return result;
    }


    /**
     * 根据 orgCode 查询用户，包括子部门下的用户
     * 若某个用户包含多个部门，则会显示多条记录，可自行处理成单条记录
     */
    @GetMapping("/queryByOrgCode")
    public Result<?> queryByDepartId(
            @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
            @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
            @RequestParam(name = "orgCode") String orgCode,
            SysUser userParams
    ) {
        IPage<SysUserSysDepartModel> pageList = sysUserService.queryUserByOrgCode(orgCode, userParams, new Page(pageNo, pageSize));
        return Result.ok(pageList);
    }

    /**
     * 根据 orgCode 查询用户，包括子部门下的用户 【不包含岗位下的用户】
     * 针对通讯录模块做的接口，将多个部门的用户合并成一条记录，并转成对前端友好的格式
     */
    @GetMapping("/queryByOrgCodeForAddressList")
    public Result<?> queryByOrgCodeForAddressList(
            @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
            @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
            @RequestParam(name = "orgCode",required = false) String orgCode,
            SysUser userParams
    ) {
        IPage page = new Page(pageNo, pageSize);
        IPage<SysUserSysDepartModel> pageList = sysUserService.queryUserByOrgCode(orgCode, userParams, page);
        List<SysUserSysDepartModel> list = pageList.getRecords();

        // 记录所有出现过的 user, key = userId
        Map<String, JSONObject> hasUser = new HashMap<>(list.size());

        JSONArray resultJson = new JSONArray(list.size());

        for (SysUserSysDepartModel item : list) {
            String userId = item.getId();
            // userId
            JSONObject getModel = hasUser.get(userId);
            // 之前已存在过该用户，直接合并数据
            if (getModel != null) {
                String departName = getModel.get("departName").toString();
                getModel.put("departName", (departName + " | " + item.getDepartName()));
            } else {
                // 将用户对象转换为json格式，并将部门信息合并到 json 中
                JSONObject json = JSON.parseObject(JSON.toJSONString(item));
                json.remove("id");
                json.put("userId", userId);
                json.put("departId", item.getDepartId());
                json.put("departName", item.getDepartName());
//                json.put("avatar", item.getSysUser().getAvatar());
                resultJson.add(json);
                hasUser.put(userId, json);
            }
        }

        IPage<JSONObject> result = new Page<>(pageNo, pageSize, pageList.getTotal());
        result.setRecords(resultJson.toJavaList(JSONObject.class));
        return Result.ok(result);
    }

    /**
     * 根据 orgCode 查询用户，包括公司、子公司、岗位部门下的用户
     */
    @GetMapping("/queryDepartPostByOrgCode")
    public Result<?> queryDepartPostByOrgCode(@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                              @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
                                              @RequestParam(name = "orgCode",required = false) String orgCode,
                                              SysUser userParams
    ) {
        IPage page = new Page(pageNo, pageSize);
        IPage<SysUserSysDepPostModel> pageList = sysUserService.queryDepartPostUserByOrgCode(orgCode, userParams, page);
        return Result.ok(pageList);
    }

    /**
     * 根据 orgCode 查询用户信息（部门全路径，主岗位和兼职岗位的信息），包括公司、子公司、部门
     */
    @GetMapping("/queryDepartUserByOrgCode")
    public Result<IPage<SysUserSysDepPostModel>> queryDepartUserByOrgCode(@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                              @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
                                              @RequestParam(name = "orgCode",required = false) String orgCode,
                                              SysUser userParams
    ) {
        IPage page = new Page(pageNo, pageSize);
        IPage<SysUserSysDepPostModel> pageList = sysUserService.queryDepartUserByOrgCode(orgCode, userParams, page);
        return Result.ok(pageList);
    }

    /**
     * 通讯录点击用户获取用户详情（包含用户基本信息、部门全路径、主岗位兼职岗位全路径）
     * 
     * @param userId
     * @return
     */
    @GetMapping("/getUserDetailByUserId")
    public Result<SysUserSysDepPostModel> getUserDetailByUserId(@RequestParam(name = "userId") String userId) {
        Result<SysUserSysDepPostModel> result = new Result<SysUserSysDepPostModel>();
        try {
            SysUserSysDepPostModel sysDepPostModel = sysUserService.getUserDetailByUserId(userId);
            result.setSuccess(true);
            result.setResult(sysDepPostModel);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            result.setSuccess(false);
            result.setMessage("查询失败: " + e.getMessage());
        }
        return result;
    }
    
    /**
     * 给指定部门添加对应的用户
     */
    @RequiresPermissions("system:user:editDepartWithUser")
    @RequestMapping(value = "/editSysDepartWithUser", method = RequestMethod.POST)
    public Result<String> editSysDepartWithUser(@RequestBody SysDepartUsersVO sysDepartUsersVO) {
        Result<String> result = new Result<String>();
        try {
            String sysDepId = sysDepartUsersVO.getDepId();
            boolean updated = false;
            for(String sysUserId:sysDepartUsersVO.getUserIdList()) {
                SysUserDepart sysUserDepart = new SysUserDepart(null,sysUserId,sysDepId);
                QueryWrapper<SysUserDepart> queryWrapper = new QueryWrapper<SysUserDepart>();
                queryWrapper.eq("dep_id", sysDepId).eq("user_id",sysUserId);
                SysUserDepart one = sysUserDepartService.getOne(queryWrapper);
                if(one==null){
                    updated = true;
                    sysUserDepartService.save(sysUserDepart);
                }
            }
            // 【JHHB-737】更新关系后清空用户缓存
            if (updated) {
                redisUtil.removeAll(CacheConstant.SYS_USERS_CACHE);
            }
            result.setMessage("添加成功!");
            result.setSuccess(true);
            return result;
        }catch(Exception e) {
            log.error(e.getMessage(), e);
            result.setSuccess(false);
            result.setMessage("出错了: " + e.getMessage());
            return result;
        }
    }

    /**
     *   删除指定机构的用户关系
     */
    @RequiresPermissions("system:user:deleteUserInDepart")
    @RequestMapping(value = "/deleteUserInDepart", method = RequestMethod.DELETE)
    public Result<SysUserDepart> deleteUserInDepart(@RequestParam(name="depId") String depId,
                                                    @RequestParam(name="userId",required=true) String userId
    ) {
        Result<SysUserDepart> result = new Result<SysUserDepart>();
        try {
            QueryWrapper<SysUserDepart> queryWrapper = new QueryWrapper<SysUserDepart>();
            queryWrapper.eq("dep_id", depId).eq("user_id",userId);
            boolean b = sysUserDepartService.remove(queryWrapper);
            if(b){
                List<SysDepartRole> sysDepartRoleList = departRoleService.list(new QueryWrapper<SysDepartRole>().eq("depart_id",depId));
                List<String> roleIds = sysDepartRoleList.stream().map(SysDepartRole::getId).collect(Collectors.toList());
                if(roleIds != null && roleIds.size()>0){
                    QueryWrapper<SysDepartRoleUser> query = new QueryWrapper<>();
                    query.eq("user_id",userId).in("drole_id",roleIds);
                    departRoleUserService.remove(query);
                }
                result.success("删除成功!");
            }else{
                result.error500("当前选中部门与用户无关联关系!");
            }
        }catch(Exception e) {
            log.error(e.getMessage(), e);
            result.error500("删除失败！");
        }
        return result;
    }

    /**
     * 批量删除指定机构的用户关系
     */
    @RequiresPermissions("system:user:deleteUserInDepartBatch")
    @RequestMapping(value = "/deleteUserInDepartBatch", method = RequestMethod.DELETE)
    public Result<SysUserDepart> deleteUserInDepartBatch(
            @RequestParam(name="depId") String depId,
            @RequestParam(name="userIds",required=true) String userIds) {
        Result<SysUserDepart> result = new Result<SysUserDepart>();
        try {
            QueryWrapper<SysUserDepart> queryWrapper = new QueryWrapper<SysUserDepart>();
            queryWrapper.eq("dep_id", depId).in("user_id",Arrays.asList(userIds.split(",")));
            boolean b = sysUserDepartService.remove(queryWrapper);
            if(b){
                departRoleUserService.removeDeptRoleUser(Arrays.asList(userIds.split(",")),depId);
            }else{
                result.error500("删除失败，目标用户不在当前部门！");
                return result;
            }
            result.success("删除成功!");
        }catch(Exception e) {
            log.error(e.getMessage(), e);
            result.error500("删除失败！");
        }
        return result;
    }
    
    /**
         *  查询当前用户的所有部门/当前部门编码
     * @return
     */
    @RequestMapping(value = "/getCurrentUserDeparts", method = RequestMethod.GET)
    public Result<Map<String,Object>> getCurrentUserDeparts() {
        Result<Map<String,Object>> result = new Result<Map<String,Object>>();
        try {
        	LoginUser sysUser = (LoginUser)SecurityUtils.getSubject().getPrincipal();
            List<SysDepart> list = this.sysDepartService.queryUserDeparts(sysUser.getId());
            Map<String,Object> map = new HashMap(5);
            map.put("list", list);
            map.put("orgCode", sysUser.getOrgCode());
            result.setSuccess(true);
            result.setResult(map);
        }catch(Exception e) {
            log.error(e.getMessage(), e);
            result.error500("查询失败！");
        }
        return result;
    }

    


	/**
	 * 用户注册接口
	 * 
	 * @param jsonObject
	 * @param user
	 * @return
	 */
	@PostMapping("/register")
	public Result<JSONObject> userRegister(@RequestBody JSONObject jsonObject, SysUser user) {
		Result<JSONObject> result = new Result<JSONObject>();
		String phone = jsonObject.getString("phone");
		String smscode = jsonObject.getString("smscode");

        // 代码逻辑说明: VUEN-2245 【漏洞】发现新漏洞待处理20220906
		String redisKey = CommonConstant.PHONE_REDIS_KEY_PRE+phone;
		Object code = redisUtil.get(redisKey);

		String username = jsonObject.getString("username");
		//未设置用户名，则用手机号作为用户名
		if(oConvertUtils.isEmpty(username)){
            username = phone;
        }
        //未设置密码，则随机生成一个密码
		String password = jsonObject.getString("password");
		if(oConvertUtils.isEmpty(password)){
            password = RandomUtil.randomString(8);
        }
		String email = jsonObject.getString("email");
		SysUser sysUser1 = sysUserService.getUserByName(username);
		if (sysUser1 != null) {
			result.setMessage("用户名已注册");
			result.setSuccess(false);
			return result;
		}
		SysUser sysUser2 = sysUserService.getUserByPhone(phone);
		if (sysUser2 != null) {
			result.setMessage("该手机号已注册");
			result.setSuccess(false);
			return result;
		}

		if(oConvertUtils.isNotEmpty(email)){
            SysUser sysUser3 = sysUserService.getUserByEmail(email);
            if (sysUser3 != null) {
                result.setMessage("邮箱已被注册");
                result.setSuccess(false);
                return result;
            }
        }
        if(null == code){
            result.setMessage("手机验证码失效，请重新获取");
            result.setSuccess(false);
            return result;
        }
		if (!smscode.equals(code.toString())) {
			result.setMessage("手机验证码错误");
			result.setSuccess(false);
			return result;
		}

        String realname = jsonObject.getString("realname");
        if(oConvertUtils.isEmpty(realname)){
            realname = username;
        }
        
		try {
			user.setCreateTime(new Date());// 设置创建时间
			String salt = oConvertUtils.randomGen(8);
			String passwordEncode = PasswordUtil.encrypt(username, password, salt);
			user.setSalt(salt);
			user.setUsername(username);
			user.setRealname(realname);
			user.setPassword(passwordEncode);
			user.setEmail(email);
			user.setPhone(phone);
			user.setStatus(CommonConstant.USER_UNFREEZE);
			user.setDelFlag(CommonConstant.DEL_FLAG_0);
			user.setActivitiSync(CommonConstant.ACT_SYNC_1);
            user.setLastPwdUpdateTime(new Date());
			sysUserService.addUserWithRole(user,"");//默认临时角色 test
			result.success("注册成功");
		} catch (Exception e) {
			result.error500("注册失败");
		}
		return result;
	}

//	/**
//	 * 根据用户名或手机号查询用户信息
//	 * @param
//	 * @return
//	 */
//	@GetMapping("/querySysUser")
//	public Result<Map<String, Object>> querySysUser(SysUser sysUser) {
//		String phone = sysUser.getPhone();
//		String username = sysUser.getUsername();
//		Result<Map<String, Object>> result = new Result<Map<String, Object>>();
//		Map<String, Object> map = new HashMap<String, Object>();
//		if (oConvertUtils.isNotEmpty(phone)) {
//			SysUser user = sysUserService.getUserByPhone(phone);
//			if(user!=null) {
//				map.put("username",user.getUsername());
//				map.put("phone",user.getPhone());
//				result.setSuccess(true);
//				result.setResult(map);
//				return result;
//			}
//		}
//		if (oConvertUtils.isNotEmpty(username)) {
//			SysUser user = sysUserService.getUserByName(username);
//			if(user!=null) {
//				map.put("username",user.getUsername());
//				map.put("phone",user.getPhone());
//				result.setSuccess(true);
//				result.setResult(map);
//				return result;
//			}
//		}
//		result.setSuccess(false);
//		result.setMessage("验证失败");
//		return result;
//	}

	/**
	 * 用户手机号验证
	 */
	@PostMapping("/phoneVerification")
	public Result<Map<String,String>> phoneVerification(@RequestBody JSONObject jsonObject) {
		Result<Map<String,String>> result = new Result<Map<String,String>>();
		String phone = jsonObject.getString("phone");
		String smscode = jsonObject.getString("smscode");
        // 代码逻辑说明: VUEN-2245 【漏洞】发现新漏洞待处理20220906
        String redisKey = CommonConstant.PHONE_REDIS_KEY_PRE+phone;
		Object code = redisUtil.get(redisKey);
        // 代码逻辑说明: 【issues/8567】严重：修改密码存在水平越权问题。---
        if (null == code) {
            result.setMessage("短信验证码失效！");
            result.setSuccess(false);
            return result;
        }
        String smsCode = "";
        if (code.toString().contains("code")) {
            smsCode = JSONObject.parseObject(code.toString()).getString("code");
        } else {
            smsCode = code.toString();
        }
		if (!smscode.equals(smsCode)) {
			result.setMessage("手机验证码错误");
			result.setSuccess(false);
			return result;
		}
		//设置有效时间
		redisUtil.set(redisKey, code,600);

		//新增查询用户名
		LambdaQueryWrapper<SysUser> query = new LambdaQueryWrapper<>();
        query.eq(SysUser::getPhone,phone);
        SysUser user = sysUserService.getOne(query);
        Map<String,String> map = new HashMap(5);
        map.put("smscode",smscode);
        if(null == user){
            //前端根据文字做判断用户是否存在判断，不能修改
            result.setMessage("用户信息不存在");
            result.setSuccess(false);
            return result;
        }
        map.put("username",user.getUsername());
        result.setResult(map);
		result.setSuccess(true);
		return result;
	}
	
	/**
	 * 用户更改密码
	 */
	@GetMapping("/passwordChange")
	public Result<SysUser> passwordChange(@RequestParam(name="username")String username,
										  @RequestParam(name="password")String password,
			                              @RequestParam(name="smscode")String smscode,
			                              @RequestParam(name="phone") String phone) {
        Result<SysUser> result = new Result<SysUser>();
        if(oConvertUtils.isEmpty(username) || oConvertUtils.isEmpty(password) || oConvertUtils.isEmpty(smscode)  || oConvertUtils.isEmpty(phone) ) {
            result.setMessage("重置密码失败！");
            result.setSuccess(false);
            return result;
        }

        SysUser sysUser=new SysUser();
        // 代码逻辑说明: VUEN-2245 【漏洞】发现新漏洞待处理20220906
        String redisKey = CommonConstant.PHONE_REDIS_KEY_PRE+phone;
        Object object= redisUtil.get(redisKey);
        if(null==object) {
        	result.setMessage("短信验证码失效！");
            result.setSuccess(false);
            return result;
        }

        // 代码逻辑说明: 【issues/8567】严重：修改密码存在水平越权问题。---
        String redisUsername = "";
        if(object.toString().contains("code")){
            JSONObject jsonObject = JSONObject.parseObject(object.toString());
            object = jsonObject.getString("code");
            redisUsername = jsonObject.getString("username");
        }
        //验证是否为当前用户的
        if(oConvertUtils.isNotEmpty(redisUsername) && !username.equals(redisUsername)){
            result.setMessage("此验证码不是当前用户的！");
            result.setSuccess(false);
            return result;
        }
        
        if(!smscode.equals(object.toString())) {
        	result.setMessage("短信验证码不匹配！");
            result.setSuccess(false);
            return result;
        }
        sysUser = this.sysUserService.getOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUsername,username).eq(SysUser::getPhone,phone));
        if (sysUser == null) {
            result.setMessage("当前用户和绑定的手机号不匹配，无法修改密码！");
            result.setSuccess(false);
            return result;
        } else {
            String salt = oConvertUtils.randomGen(8);
            sysUser.setSalt(salt);
            String passwordEncode = PasswordUtil.encrypt(sysUser.getUsername(), password, salt);
            sysUser.setPassword(passwordEncode);
            sysUser.setLastPwdUpdateTime(new Date());
            this.sysUserService.updateById(sysUser);
            // 代码逻辑说明: [VUEN-234]密码重置添加敏感日志------------
            baseCommonService.addLog("重置 "+username+" 的密码，操作人： " +sysUser.getUsername() ,CommonConstant.LOG_TYPE_2, 2);
            result.setSuccess(true);
            result.setMessage("密码重置完成！");
            //修改完密码后清空redis
            redisUtil.removeAll(redisKey);
            return result;
        }
    }
	

	/**
	 * 根据TOKEN获取用户的部分信息（返回的数据是可供表单设计器使用的数据）
	 * 
	 * @return
	 */
	@GetMapping("/getUserSectionInfoByToken")
	public Result<?> getUserSectionInfoByToken(HttpServletRequest request, @RequestParam(name = "token", required = false) String token) {
		try {
			String username = null;
			// 如果没有传递token，就从header中获取token并获取用户信息
			if (oConvertUtils.isEmpty(token)) {
				 username = JwtUtil.getUserNameByToken(request);
			} else {
				 username = JwtUtil.getUsername(token);				
			}

			log.debug(" ------ 通过令牌获取部分用户信息，当前用户： " + username);

			// 根据用户名查询用户信息
			SysUser sysUser = sysUserService.getUserByName(username);
			Map<String, Object> map = new HashMap<String, Object>();
			map.put("sysUserId", sysUser.getId());
			map.put("sysUserCode", sysUser.getUsername()); // 当前登录用户登录账号
			map.put("sysUserName", sysUser.getRealname()); // 当前登录用户真实名称
			map.put("sysOrgCode", sysUser.getOrgCode()); // 当前登录用户部门编号

            // 【QQYUN-12930】设置部门名称
            if (oConvertUtils.isNotEmpty(sysUser.getOrgCode())) {
                SysDepart sysDepart = sysDepartService.lambdaQuery().select(SysDepart::getDepartName).eq(SysDepart::getOrgCode, sysUser.getOrgCode()).one();
                if (sysDepart != null) {
                    map.put("sysOrgName", sysDepart.getDepartName()); // 当前登录用户部门名称
                }
            }

			log.debug(" ------ 通过令牌获取部分用户信息，已获取的用户信息： " + map);

			return Result.ok(map);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			return Result.error(500, "查询失败:" + e.getMessage());
		}
	}
	
	/**
	 * 【APP端接口】获取用户列表  根据用户名和真实名 模糊匹配
	 * @param keyword
	 * @param pageNo
	 * @param pageSize
	 * @return
	 */
	@GetMapping("/appUserList")
	public Result<?> appUserList(@RequestParam(name = "keyword", required = false) String keyword,
            @RequestParam(name = "username", required = false) String username,
			@RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
			@RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
            @RequestParam(name = "syncFlow", required = false) String syncFlow) {
		try {
			//TODO 从查询效率上将不要用mp的封装的page分页查询 建议自己写分页语句
			LambdaQueryWrapper<SysUser> query = new LambdaQueryWrapper<SysUser>();
			if(oConvertUtils.isNotEmpty(syncFlow)){
                query.eq(SysUser::getActivitiSync, CommonConstant.ACT_SYNC_1);
            }
			query.eq(SysUser::getDelFlag,CommonConstant.DEL_FLAG_0);
			if(oConvertUtils.isNotEmpty(username)){
			    if(username.contains(",")){
                    query.in(SysUser::getUsername,username.split(","));
                }else{
                    query.eq(SysUser::getUsername,username);
                }
            }else{
                query.and(i -> i.like(SysUser::getUsername, keyword).or().like(SysUser::getRealname, keyword));
            }
			Page<SysUser> page = new Page<>(pageNo, pageSize);
			IPage<SysUser> res = this.sysUserService.page(page, query);
			return Result.ok(res);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			return Result.error(500, "查询失败:" + e.getMessage());
		}
		
	}

    /**
     * 获取被逻辑删除的用户列表，无分页
     *
     * @return logicDeletedUserList
     */
    @GetMapping("/recycleBin")
    public Result getRecycleBin() {
        List<SysUser> logicDeletedUserList = sysUserService.queryLogicDeleted();
        if (logicDeletedUserList.size() > 0) {
            // 批量查询用户的所属部门
            // step.1 先拿到全部的 userIds
            List<String> userIds = logicDeletedUserList.stream().map(SysUser::getId).collect(Collectors.toList());
            // step.2 通过 userIds，一次性查询用户的所属部门名字
            Map<String, String> useDepNames = sysUserService.getDepNamesByUserIds(userIds);
            logicDeletedUserList.forEach(item -> item.setOrgCode(useDepNames.get(item.getId())));
        }
        return Result.ok(logicDeletedUserList);
    }

    /**
     * 还原被逻辑删除的用户
     *
     * @param jsonObject
     * @return
     */
    @RequestMapping(value = "/putRecycleBin", method = RequestMethod.PUT)
    public Result putRecycleBin(@RequestBody JSONObject jsonObject, HttpServletRequest request) {
        String userIds = jsonObject.getString("userIds");
        if (StringUtils.isNotBlank(userIds)) {
            SysUser updateUser = new SysUser();
            updateUser.setUpdateBy(JwtUtil.getUserNameByToken(request));
            updateUser.setUpdateTime(new Date());
            sysUserService.revertLogicDeleted(Arrays.asList(userIds.split(",")), updateUser);
        }
        return Result.ok("还原成功");
    }

    /**
     * 彻底删除用户
     *
     * @param userIds 被删除的用户ID，多个id用半角逗号分割
     * @return
     */
    @RequiresPermissions("system:user:deleteRecycleBin")
    @RequestMapping(value = "/deleteRecycleBin", method = RequestMethod.DELETE)
    public Result deleteRecycleBin(@RequestParam("userIds") String userIds) {
        if (StringUtils.isNotBlank(userIds)) {
            sysUserService.removeLogicDeleted(Arrays.asList(userIds.split(",")));
        }
        return Result.ok("删除成功");
    }


    /**
     * 移动端修改用户信息
     * @param jsonObject
     * @return
     */
    @RequiresPermissions("system:user:app:edit")
    @RequestMapping(value = "/appEdit", method = {RequestMethod.PUT,RequestMethod.POST})
    public Result<SysUser> appEdit(HttpServletRequest request,@RequestBody JSONObject jsonObject) {
        Result<SysUser> result = new Result<SysUser>();
        try {
            String username = JwtUtil.getUserNameByToken(request);
            SysUser sysUser = sysUserService.getUserByName(username);
            baseCommonService.addLog("移动端编辑用户，id： " +jsonObject.getString("id") ,CommonConstant.LOG_TYPE_2, 2);
            String realname=jsonObject.getString("realname");
            String avatar=jsonObject.getString("avatar");
            String sex=jsonObject.getString("sex");
            String phone=jsonObject.getString("phone");
            String email=jsonObject.getString("email");
            Date birthday=jsonObject.getDate("birthday");
            SysUser userPhone = sysUserService.getUserByPhone(phone);
            if(sysUser==null) {
                result.error500("未找到对应用户!");
            }else {
                if(userPhone!=null){
                    String userPhonename = userPhone.getUsername();
                    if(!userPhonename.equals(username)){
                        result.error500("手机号已存在!");
                        return result;
                    }
                }
                if(StringUtils.isNotBlank(realname)){
                    sysUser.setRealname(realname);
                }
                if(StringUtils.isNotBlank(avatar)){
                    sysUser.setAvatar(avatar);
                }
                if(StringUtils.isNotBlank(sex)){
                    sysUser.setSex(Integer.parseInt(sex));
                }
                if(StringUtils.isNotBlank(phone)){
                    sysUser.setPhone(phone);
                }
                if(StringUtils.isNotBlank(email)){
                    // 代码逻辑说明: [VUEN-1528]积木官网邮箱重复，应该提示准确------------
                    LambdaQueryWrapper<SysUser> emailQuery = new LambdaQueryWrapper<>();
                    emailQuery.eq(SysUser::getEmail,email);
                    long count = sysUserService.count(emailQuery);
                    if (!email.equals(sysUser.getEmail()) && count!=0) {
                        result.error500("保存失败，邮箱已存在!");
                        return result;
                    }
                    sysUser.setEmail(email);
                }
                if(null != birthday){
                    sysUser.setBirthday(birthday);
                }
                sysUser.setUpdateTime(new Date());
                sysUserService.updateById(sysUser);
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            result.error500("保存失败!");
        }
        return result;
    }
    /**
     * 移动端保存设备信息
     * @param clientId
     * @return
     */
    @RequestMapping(value = "/saveClientId", method = RequestMethod.GET)
    public Result<SysUser> saveClientId(HttpServletRequest request,@RequestParam(value = "clientId",required = false)String clientId) {
        Result<SysUser> result = new Result<SysUser>();
        try {
            String username = JwtUtil.getUserNameByToken(request);
            SysUser sysUser = sysUserService.getUserByName(username);
            if(sysUser==null) {
                result.error500("未找到对应用户!");
            }else {
                sysUserService.updateClientId(clientId,sysUser.getId());
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            result.error500("操作失败!");
        }
        return result;
    }
    /**
     * 根据userid获取用户信息和部门员工信息
     *
     * @return Result
     */
    @GetMapping("/queryChildrenByUsername")
    public Result queryChildrenByUsername(@RequestParam("userId") String userId) {
        //获取用户信息
        Map<String,Object> map=new HashMap(5);
        SysUser sysUser = sysUserService.getById(userId);
        String username = sysUser.getUsername();
        Integer identity = sysUser.getUserIdentity();
        map.put("sysUser",sysUser);
        if(identity!=null && identity==2){
            //获取部门用户信息
            String departIds = sysUser.getDepartIds();
            if(StringUtils.isNotBlank(departIds)){
                List<String> departIdList = Arrays.asList(departIds.split(","));
                List<SysUser> childrenUser = sysUserService.queryByDepIds(departIdList,username);
                map.put("children",childrenUser);
            }
        }
        return Result.ok(map);
    }
    /**
     * 移动端查询部门用户信息
     * @param departId
     * @return
     */
    @GetMapping("/appQueryByDepartId")
    public Result<List<SysUser>> appQueryByDepartId(@RequestParam(name="departId", required = false) String departId) {
        Result<List<SysUser>> result = new Result<List<SysUser>>();
        List<String> list=new ArrayList<String> ();
        list.add(departId);
        List<SysUser> childrenUser = sysUserService.queryByDepIds(list,null);
        result.setResult(childrenUser);
        return result;
    }
    /**
     * 移动端查询用户信息(通过用户名模糊查询)
     * @param keyword
     * @return
     */
    @GetMapping("/appQueryUser")
    public Result<List<SysUser>> appQueryUser(@RequestParam(name = "keyword", required = false) String keyword,
                                              @RequestParam(name = "username", required = false) String username,
                                              @RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
                                              @RequestParam(name="pageSize", defaultValue="10") Integer pageSize,HttpServletRequest request) {
        Result<List<SysUser>> result = new Result<List<SysUser>>();
        LambdaQueryWrapper<SysUser> queryWrapper =new LambdaQueryWrapper<SysUser>();
        // 外部模拟登陆临时账号，列表不显示
        queryWrapper.ne(SysUser::getUsername,"_reserve_user_external");
        //增加 username传参
        if(oConvertUtils.isNotEmpty(username)){
            if(username.contains(",")){
                queryWrapper.in(SysUser::getUsername,username.split(","));
            }else{
                queryWrapper.eq(SysUser::getUsername,username);
            }
        }else if(StringUtils.isNotBlank(keyword)){
            queryWrapper.and(i -> i.like(SysUser::getUsername, keyword).or().like(SysUser::getRealname, keyword));
        }
        //------------------------------------------------------------------------------------------------
        //是否开启系统管理模块的多租户数据隔离【SAAS多租户模式】
        if (MybatisPlusSaasConfig.OPEN_SYSTEM_TENANT_CONTROL) {
            String tenantId = oConvertUtils.getString(TokenUtils.getTenantIdByRequest(request),"-1");
            // 代码逻辑说明: [QQYUN-3371]租户逻辑改造，改成关系表------------
            List<String> userIds = userTenantService.getUserIdsByTenantId(Integer.valueOf(tenantId));
            if (oConvertUtils.listIsNotEmpty(userIds)) {
                queryWrapper.in(SysUser::getId, userIds);
            }
        }
        //------------------------------------------------------------------------------------------------
        Page<SysUser> page = new Page<>(pageNo, pageSize);

        // 代码逻辑说明: JHHB-812 【移动端】人员按照排序展示 选择人员，通讯录等 123正序排
        queryWrapper.orderByAsc(SysUser::getSort);
        queryWrapper.orderByDesc(SysUser::getCreateTime);

        IPage<SysUser> pageList = this.sysUserService.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 = sysUserService.getDepNamesByUserIds(userIds);
            pageList.getRecords().forEach(item->{
                item.setOrgCodeTxt(useDepNames.get(item.getId()));
            });
        }
        result.setResult(pageList.getRecords());
        return result;
    }

    /**
     * 根据用户名修改手机号[该方法未使用]
     * @param json
     * @return
     */
    @RequestMapping(value = "/updateMobile", method = RequestMethod.PUT)
    public Result<?> changMobile(@RequestBody JSONObject json,HttpServletRequest request) {
        String smscode = json.getString("smscode");
        String phone = json.getString("phone");
        Result<SysUser> result = new Result<SysUser>();
        //获取登录用户名
        String username = JwtUtil.getUserNameByToken(request);
        if(oConvertUtils.isEmpty(username) || oConvertUtils.isEmpty(smscode) || oConvertUtils.isEmpty(phone)) {
            result.setMessage("修改手机号失败！");
            result.setSuccess(false);
            return result;
        }
        // 代码逻辑说明: VUEN-2245 【漏洞】发现新漏洞待处理20220906
        String redisKey = CommonConstant.PHONE_REDIS_KEY_PRE+phone;
        Object object= redisUtil.get(redisKey);
        if(null==object) {
            result.setMessage("短信验证码失效！");
            result.setSuccess(false);
            return result;
        }
        if(!smscode.equals(object.toString())) {
            result.setMessage("短信验证码不匹配！");
            result.setSuccess(false);
            return result;
        }
        SysUser user = sysUserService.getUserByName(username);
        if(user==null) {
            return Result.error("用户不存在！");
        }
        user.setPhone(phone);
        sysUserService.updateById(user);
        return Result.ok("手机号设置成功!");
    }


    /**
     * 根据对象里面的属性值作in查询 属性可能会变 用户组件用到
     * @param sysUser
     * @return
     */
    @GetMapping("/getMultiUser")
    public List<SysUser> getMultiUser(SysUser sysUser){
        QueryWrapper<SysUser> queryWrapper = QueryGenerator.initQueryWrapper(sysUser, null);
        // 代码逻辑说明: [JTC-297]已冻结用户仍可设置为代理人------------
        queryWrapper.eq("status",Integer.parseInt(CommonConstant.STATUS_1));
        List<SysUser> ls = this.sysUserService.list(queryWrapper);
        for(SysUser user: ls){
            user.setPassword(null);
            user.setSalt(null);
        }
        return ls;
    }
    
    /**
     * 聊天 创建聊天组件专用  根据用户账号、用户姓名、部门id分页查询
     * @param departId 部门id
     * @param keyword 搜索值
     * @return
     */
    @GetMapping(value = "/getUserInformation")
    public Result<IPage<SysUser>> getUserInformation(
            @RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
            @RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
            @RequestParam(name = "departId", required = false) String departId,
            @RequestParam(name="keyword",required=false) String keyword) {
        //------------------------------------------------------------------------------------------------
        Integer tenantId = null;
        //是否开启系统管理模块的多租户数据隔离【SAAS多租户模式】
        if(MybatisPlusSaasConfig.OPEN_SYSTEM_TENANT_CONTROL){
            tenantId = oConvertUtils.getInt(TenantContext.getTenant(),0);
        }
        //------------------------------------------------------------------------------------------------
        IPage<SysUser> pageList = sysUserDepartService.getUserInformation(tenantId,departId, keyword, pageSize, pageNo);
        return Result.OK(pageList);
    }

    /**
     * 简版流程用户选择组件
     * @param departId 部门id
     * @param roleId 角色id
     * @param keyword 搜索值
     * @return
     */
    @GetMapping(value = "/selectUserList")
    public Result<IPage<SysUser>> selectUserList(
            @RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
            @RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
            @RequestParam(name = "departId", required = false) String departId,
            @RequestParam(name = "roleId", required = false) String roleId,
            @RequestParam(name="keyword",required=false) String keyword,
            @RequestParam(name="excludeUserIdList",required = false) String excludeUserIdList,
            @RequestParam(name="includeUsernameList",required = false) String includeUsernameList,
            HttpServletRequest req) {
        //------------------------------------------------------------------------------------------------
        Integer tenantId = null;
        //是否开启系统管理模块的多租户数据隔离【SAAS多租户模式】
        if(MybatisPlusSaasConfig.OPEN_SYSTEM_TENANT_CONTROL){
            String tenantStr = TenantContext.getTenant();
            tenantId = oConvertUtils.getInteger(tenantStr, oConvertUtils.getInt(TokenUtils.getTenantIdByRequest(req), -1));
            log.info("---------简流中选择用户接口，通过租户筛选，租户ID={}", tenantId);
        }
        //------------------------------------------------------------------------------------------------
        IPage<SysUser> pageList = sysUserDepartService.getUserInformation(tenantId, departId,roleId, keyword, pageSize, pageNo,excludeUserIdList,includeUsernameList);
        return Result.OK(pageList);
    }

    /**
     * 获取被逻辑删除的用户列表，无分页【低代码应用专用接口】
     *
     * @return List<SysUser>
     */
    @GetMapping("/getQuitList")
    public Result<List<SysUser>> getQuitList(HttpServletRequest req) {
        Integer tenantId = oConvertUtils.getInt(TokenUtils.getTenantIdByRequest(req),0);
        List<SysUser> quitList = sysUserService.getQuitList(tenantId);
        if (null != quitList && quitList.size() > 0) {
            // 批量查询用户的所属部门
            // step.1 先拿到全部的 userIds
            List<String> userIds = quitList.stream().map(SysUser::getId).collect(Collectors.toList());
            // step.2 通过 userIds，一次性查询用户的所属部门名字
            Map<String, String> useDepNames = sysUserService.getDepNamesByUserIds(userIds);
            quitList.forEach(item -> item.setOrgCode(useDepNames.get(item.getId())));
        }
        return Result.ok(quitList);
    }

    /**
     * 更新刪除状态和离职状态【低代码应用专用接口】
     * @param jsonObject
     * @return Result<String>
     */
    @PutMapping("/putCancelQuit")
    public Result<String> putCancelQuit(@RequestBody JSONObject jsonObject, HttpServletRequest request){
        String userIds = jsonObject.getString("userIds");
        String usernames = jsonObject.getString("usernames");
        Integer tenantId = oConvertUtils.getInt(TokenUtils.getTenantIdByRequest(request),0);
        //将状态改成未删除
        if (StringUtils.isNotBlank(userIds)) {
            userTenantService.putCancelQuit(Arrays.asList(userIds.split(SymbolConstant.COMMA)),tenantId);
        }
        return Result.ok("取消离职成功");
    }

    /**
     * 获取用户信息(vue3用户设置专用)【低代码应用专用接口】
     * @return
     */
    @GetMapping("/login/setting/getUserData")
    public Result<SysUser> getUserData(HttpServletRequest request) {
        String username = JwtUtil.getUserNameByToken(request);
        SysUser user = sysUserService.getUserByName(username);
        if(user==null) {
            return Result.error("未找到该用户数据");
        }

        //获取用户id通过职位数据
        List<SysPosition> sysPositionList = sysPositionService.getPositionList(user.getId());
        if(null != sysPositionList && sysPositionList.size()>0){
            StringBuilder nameBuilder = new StringBuilder();
            StringBuilder idBuilder = new StringBuilder();
            String verticalBar = " | ";
            for (SysPosition sysPosition:sysPositionList){
                nameBuilder.append(sysPosition.getName()).append(verticalBar);
                idBuilder.append(sysPosition.getId()).append(SymbolConstant.COMMA);
            }
            String names = nameBuilder.toString();
            if(oConvertUtils.isNotEmpty(names)){
                names = names.substring(0,names.lastIndexOf(verticalBar));
                user.setPostText(names);
            }
            //拼接职位id
            String ids = idBuilder.toString();
            if(oConvertUtils.isNotEmpty(ids)){
                ids = ids.substring(0,ids.lastIndexOf(SymbolConstant.COMMA));
                user.setPost(ids);
            }
        }
        return Result.ok(user);
    }

    /**
     * 用户编辑(vue3用户设置专用)【低代码应用专用接口】
     * @param sysUser
     * @return
     */
    @PostMapping("/login/setting/userEdit")
    @RequiresPermissions("system:user:setting:edit")
    public Result<String> userEdit(@RequestBody SysUser sysUser, HttpServletRequest request) {
        String username = JwtUtil.getUserNameByToken(request);
        SysUser user = sysUserService.getById(sysUser.getId());
        if(user==null) {
           return Result.error("未找到该用户数据");
        }
        if(!username.equals(user.getUsername())){
            return Result.error("只能修改自己的数据");
        }
        sysUserService.updateById(sysUser);
        return Result.ok("更新个人信息成功");
    }

    /**
     * 批量修改 【low-app】
     * @param jsonObject
     * @return
     */
    @PutMapping("/batchEditUsers")
    public Result<SysUser> batchEditUsers(@RequestBody JSONObject jsonObject) {
        Result<SysUser> result = new Result<SysUser>();
        try {
            sysUserService.batchEditUsers(jsonObject);
            result.setSuccess(true);
            result.setMessage("操作成功！");
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            result.error500("操作失败");
        }
        return result;
    }

    /**
     * 根据关键词搜索部门和用户【low-app】
     * @param keyword
     * @return
     */
    @GetMapping("/searchByKeyword")
    public Result<DepartAndUserInfo> searchByKeyword(@RequestParam(name="keyword",required=false) String keyword) {
        DepartAndUserInfo info = sysUserService.searchByKeyword(keyword);
        return Result.ok(info);
    }

    /**
     * 编辑部门前获取部门相关信息 【low-app】
     * @param id
     * @return
     */
    @GetMapping("/getUpdateDepartInfo")
    public Result<UpdateDepartInfo> getUpdateDepartInfo(@RequestParam(name="id",required=false) String id) {
        UpdateDepartInfo info = sysUserService.getUpdateDepartInfo(id);
        return Result.ok(info);
    }

    /**
     * 编辑部门 【low-app】
     * @param updateDepartInfo
     * @return
     */
    @PutMapping("/doUpdateDepartInfo")
    public Result<?> doUpdateDepartInfo(@RequestBody UpdateDepartInfo updateDepartInfo) {
        sysUserService.doUpdateDepartInfo(updateDepartInfo);
        return Result.ok();
    }

    /**
     * 设置负责人 取消负责人
     * @param json
     * @return
     */
    @PutMapping("/changeDepartChargePerson")
    public Result<?> changeDepartChargePerson(@RequestBody JSONObject json) {
        sysUserService.changeDepartChargePerson(json);
        return Result.ok();
    }

    /**
     * 修改租户下的用户【低代码应用专用接口】
     * @param sysUser
     * @param req
     * @return
     */
    @RequestMapping(value = "/editTenantUser", method = {RequestMethod.PUT,RequestMethod.POST})
    public Result<String> editTenantUser(@RequestBody SysUser sysUser,HttpServletRequest req){
        Result<String> result = new Result<>();
        String tenantId = TokenUtils.getTenantIdByRequest(req);
        if(oConvertUtils.isEmpty(tenantId)){
            return result.error500("无权修改他人信息！");
        }
        LambdaQueryWrapper<SysUserTenant> query = new LambdaQueryWrapper<>();
        query.eq(SysUserTenant::getTenantId,Integer.valueOf(tenantId));
        query.eq(SysUserTenant::getUserId,sysUser.getId());
        SysUserTenant one = userTenantService.getOne(query);
        if(null == one){
            return result.error500("非当前租户下的用户，不允许修改！");
        }
        String departs = req.getParameter("selecteddeparts");
        sysUserService.editTenantUser(sysUser,tenantId,departs,null);
        return Result.ok("修改成功");
    }

    /**
     * 切换租户时 需要修改 loginTenantId
     * QQYUN-4491 【应用】一些小问题  1、上次选中登录的租户，下次登录未记忆
     * @param sysUser
     * @return
     */
    @PutMapping("/changeLoginTenantId")
    public Result<?> changeLoginTenantId(@RequestBody SysUser sysUser){
        Result<String> result = new Result<>();
        Integer tenantId = sysUser.getLoginTenantId();
        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        String userId = loginUser.getId();
        
        // 判断 指定的租户ID是不是当前登录用户的租户
        LambdaQueryWrapper<SysUserTenant> query = new LambdaQueryWrapper<>();
        query.eq(SysUserTenant::getTenantId, tenantId);
        query.eq(SysUserTenant::getUserId, userId);
        SysUserTenant one = userTenantService.getOne(query);
        if(null == one){
            return result.error500("非租户下的用户，不允许修改！");
        }
        
        // 修改 loginTenantId
        LambdaQueryWrapper<SysUser> update = new LambdaQueryWrapper<SysUser>()
                .eq(SysUser::getId, userId);
        SysUser updateUser = new SysUser();
        updateUser.setLoginTenantId(tenantId);
        sysUserService.update(updateUser, update);
        return Result.ok();
    } 

    /**
     * 应用用户导出
     * @param request
     * @return
     */
    @RequestMapping(value = "/exportAppUser")
    public ModelAndView exportAppUser(HttpServletRequest request) {
        return sysUserService.exportAppUser(request);
    }
    
   /**
     * 应用用户导入
     * @param request
     * @return
     */
    @RequestMapping(value = "/importAppUser", method = RequestMethod.POST)
    public Result<?> importAppUser(HttpServletRequest request, HttpServletResponse response)throws IOException {
        return sysUserService.importAppUser(request);
    }

    /**
     * 更改手机号（敲敲云个人设置专用）
     *
     * @param json
     * @param request
     */
    @PutMapping("/changePhone")
    public Result<String> changePhone(@RequestBody JSONObject json, HttpServletRequest request){
        //获取登录用户名
        String username = JwtUtil.getUserNameByToken(request);
        sysUserService.changePhone(json,username);
        return Result.ok("修改手机号成功！");
    }

    /**
     * 发送短信验证码接口(修改手机号)
     *
     * @param jsonObject
     * @return
     */
    @PostMapping(value = "/sendChangePhoneSms")
    public Result<String> sendChangePhoneSms(@RequestBody JSONObject jsonObject, HttpServletRequest request) {
        //获取登录用户名
        String username = JwtUtil.getUserNameByToken(request);
        String ipAddress = IpUtils.getIpAddr(request);
        sysUserService.sendChangePhoneSms(jsonObject, username, ipAddress);
        return Result.ok("发送验证码成功！");
    }

    /**
     * 发送注销用户手机号验证密码[敲敲云专用]
     *
     * @param jsonObject
     * @return
     */
    @PostMapping(value = "/sendLogOffPhoneSms")
    public Result<String> sendLogOffPhoneSms(@RequestBody JSONObject jsonObject, HttpServletRequest request) {
        Result<String> result = new Result<>();
        //获取登录用户名
        String username = JwtUtil.getUserNameByToken(request);
        String name = jsonObject.getString("username");
        if (oConvertUtils.isEmpty(name) || !name.equals(username)) {
            result.setSuccess(false);
            result.setMessage("发送验证码失败，用户不匹配！");
            return result;
        }
        String ipAddress = IpUtils.getIpAddr(request);
        sysUserService.sendLogOffPhoneSms(jsonObject, username, ipAddress);
        result.setSuccess(true);
        result.setMessage("发送验证码成功！");
        return result;
    }

    /**
     * 没有绑定手机号 直接修改密码
     * @param oldPassword
     * @param password
     * @return
     */
    @PutMapping("/updatePasswordNotBindPhone")
    public Result<String> updatePasswordNotBindPhone(@RequestParam(value="oldPassword") String oldPassword,
                                                     @RequestParam(value="password") String password,
                                                     @RequestParam(value="username") String username){
        sysUserService.updatePasswordNotBindPhone(oldPassword, password, username);
        return Result.OK("修改密码成功！");
    }

    /**
     * 根据部门岗位选择用户【部门岗位选择用户专用】
     * @return
     */
    @GetMapping("/queryDepartPostUserPageList")
    public Result<IPage<SysUser>> queryDepartPostUserPageList( @RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
                                                        @RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
                                                        @RequestParam(name = "departId", required = false) String departId,
                                                        @RequestParam(name="realname",required=false) String realname,
                                                        @RequestParam(name="username",required=false) String username,
                                                        @RequestParam(name="isMultiTranslate",required=false) String isMultiTranslate,
                                                        @RequestParam(name="id",required = false) String id){
        String[] arr = new String[]{departId, realname, username, id};
        SqlInjectionUtil.filterContent(arr, SymbolConstant.SINGLE_QUOTATION_MARK);
        IPage<SysUser> pageList = sysUserDepartService.queryDepartPostUserPageList(departId, username, realname, pageSize, pageNo,id,isMultiTranslate);
        return Result.OK(pageList);
    }

    /**
     * 获取上传文件的进度
     * 
     * @param fileKey
     * @param type
     * @return
     */
    @GetMapping("/getUploadFileProgress")
    public Result<Double> getUploadFileProgress(@RequestParam(name = "fileKey") String fileKey,
                                                @RequestParam("type") String type){
        Double progress = ImportSysUserCache.getImportSysUserMap(fileKey, type);
        if(progress == 100){
            ImportSysUserCache.removeImportLowAppMap(fileKey);
        }
        return Result.ok(progress);
    }

    /**
     * 验证当前登录用户是否仍使用系统默认初始密码。
     * 返回值说明:
     *   yes_{URL编码后的默认密码} -> 用户当前密码为默认初始密码，前端需弹出强制修改提示
     *   no -> 用户密码不是默认密码，或未开启默认密码检测开关
     */
    @GetMapping("/verifyIzDefaultPwd")
    public Result<String> verifyIzDefaultPwd() throws UnsupportedEncodingException {
        // 未配置 Firewall 或已关闭默认密码检测开关 (enableDefaultPwdCheck=false) 时，直接返回 "no" 表示无需提示
        if (jeecgBaseConfig.getFirewall() == null || Boolean.FALSE.equals((jeecgBaseConfig.getFirewall().getEnableDefaultPwdCheck()))) {
            return Result.OK("no");
        }
        
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        SysUser user = sysUserService.getById(sysUser.getId());
        String passwordEncode = PasswordUtil.encrypt(user.getUsername(), PasswordConstant.DEFAULT_PASSWORD, user.getSalt());
        if(passwordEncode.equals(user.getPassword())){
            String encode = URLEncoder.encode(PasswordConstant.DEFAULT_PASSWORD, "UTF-8");
            return Result.OK("yes_" + encode);
        }
        return Result.OK("no");
    }
}
