diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java index 065ae4818..d3ff7a22b 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java @@ -2,6 +2,7 @@ package com.ruoyi.system.service.impl; import java.util.ArrayList; import java.util.List; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -27,86 +28,38 @@ import com.ruoyi.system.service.ISysUserService; /** * 用户 业务层处理 - * + * * @author ruoyi */ @Service -public class SysUserServiceImpl implements ISysUserService -{ - private static final Logger log = LoggerFactory.getLogger(SysUserServiceImpl.class); - - @Autowired - private SysUserMapper userMapper; - - @Autowired - private SysRoleMapper roleMapper; - - @Autowired - private SysPostMapper postMapper; - - @Autowired - private SysUserRoleMapper userRoleMapper; - - @Autowired - private SysUserPostMapper userPostMapper; - - @Autowired - private ISysConfigService configService; +public class SysUserServiceImpl implements ISysUserService { /** * 根据条件分页查询用户列表 - * + * * @param user 用户信息 * @return 用户信息集合信息 */ @Override @DataScope(deptAlias = "d", userAlias = "u") - public List selectUserList(SysUser user) - { + public List selectUserList(SysUser user) { return userMapper.selectUserList(user); } - /** - * 通过用户名查询用户 - * - * @param userName 用户名 - * @return 用户对象信息 - */ - @Override - public SysUser selectUserByUserName(String userName) - { - return userMapper.selectUserByUserName(userName); - } - - /** - * 通过用户ID查询用户 - * - * @param userId 用户ID - * @return 用户对象信息 - */ - @Override - public SysUser selectUserById(Long userId) - { - return userMapper.selectUserById(userId); - } - /** * 查询用户所属角色组 - * + * * @param userName 用户名 * @return 结果 */ @Override - public String selectUserRoleGroup(String userName) - { + public String selectUserRoleGroup(String userName) { List list = roleMapper.selectRolesByUserName(userName); StringBuffer idsStr = new StringBuffer(); - for (SysRole role : list) - { + for (SysRole role : list) { idsStr.append(role.getRoleName()).append(","); } - if (StringUtils.isNotEmpty(idsStr.toString())) - { + if (StringUtils.isNotEmpty(idsStr.toString())) { return idsStr.substring(0, idsStr.length() - 1); } return idsStr.toString(); @@ -114,61 +67,23 @@ public class SysUserServiceImpl implements ISysUserService /** * 查询用户所属岗位组 - * + * * @param userName 用户名 * @return 结果 */ @Override - public String selectUserPostGroup(String userName) - { + public String selectUserPostGroup(String userName) { List list = postMapper.selectPostsByUserName(userName); StringBuffer idsStr = new StringBuffer(); - for (SysPost post : list) - { + for (SysPost post : list) { idsStr.append(post.getPostName()).append(","); } - if (StringUtils.isNotEmpty(idsStr.toString())) - { + if (StringUtils.isNotEmpty(idsStr.toString())) { return idsStr.substring(0, idsStr.length() - 1); } return idsStr.toString(); } - /** - * 校验用户名称是否唯一 - * - * @param userName 用户名称 - * @return 结果 - */ - @Override - public String checkUserNameUnique(String userName) - { - int count = userMapper.checkUserNameUnique(userName); - if (count > 0) - { - return UserConstants.NOT_UNIQUE; - } - return UserConstants.UNIQUE; - } - - /** - * 校验用户名称是否唯一 - * - * @param user 用户信息 - * @return - */ - @Override - public String checkPhoneUnique(SysUser user) - { - Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId(); - SysUser info = userMapper.checkPhoneUnique(user.getPhonenumber()); - if (StringUtils.isNotNull(info) && info.getUserId().longValue() != userId.longValue()) - { - return UserConstants.NOT_UNIQUE; - } - return UserConstants.UNIQUE; - } - /** * 校验email是否唯一 * @@ -176,12 +91,10 @@ public class SysUserServiceImpl implements ISysUserService * @return */ @Override - public String checkEmailUnique(SysUser user) - { + public String checkEmailUnique(SysUser user) { Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId(); SysUser info = userMapper.checkEmailUnique(user.getEmail()); - if (StringUtils.isNotNull(info) && info.getUserId().longValue() != userId.longValue()) - { + if (StringUtils.isNotNull(info) && info.getUserId().longValue() != userId.longValue()) { return UserConstants.NOT_UNIQUE; } return UserConstants.UNIQUE; @@ -189,28 +102,25 @@ public class SysUserServiceImpl implements ISysUserService /** * 校验用户是否允许操作 - * + * * @param user 用户信息 */ @Override - public void checkUserAllowed(SysUser user) - { - if (StringUtils.isNotNull(user.getUserId()) && user.isAdmin()) - { + public void checkUserAllowed(SysUser user) { + if (StringUtils.isNotNull(user.getUserId()) && user.isAdmin()) { throw new CustomException("不允许操作超级管理员用户"); } } /** * 新增保存用户信息 - * + * * @param user 用户信息 * @return 结果 */ @Override @Transactional - public int insertUser(SysUser user) - { + public int insertUser(SysUser user) { // 新增用户信息 int rows = userMapper.insertUser(user); // 新增用户岗位关联 @@ -222,14 +132,13 @@ public class SysUserServiceImpl implements ISysUserService /** * 修改保存用户信息 - * + * * @param user 用户信息 * @return 结果 */ @Override @Transactional - public int updateUser(SysUser user) - { + public int updateUser(SysUser user) { Long userId = user.getUserId(); // 删除用户与角色关联 userRoleMapper.deleteUserRoleByUserId(userId); @@ -242,89 +151,69 @@ public class SysUserServiceImpl implements ISysUserService return userMapper.updateUser(user); } - /** - * 修改用户状态 - * - * @param user 用户信息 - * @return 结果 - */ - @Override - public int updateUserStatus(SysUser user) - { - return userMapper.updateUser(user); - } - /** * 修改用户基本信息 - * + * * @param user 用户信息 * @return 结果 */ @Override - public int updateUserProfile(SysUser user) - { + public int updateUserProfile(SysUser user) { return userMapper.updateUser(user); } /** * 修改用户头像 - * + * * @param userName 用户名 - * @param avatar 头像地址 + * @param avatar 头像地址 * @return 结果 */ @Override - public boolean updateUserAvatar(String userName, String avatar) - { + public boolean updateUserAvatar(String userName, String avatar) { return userMapper.updateUserAvatar(userName, avatar) > 0; } /** * 重置用户密码 - * + * * @param user 用户信息 * @return 结果 */ @Override - public int resetPwd(SysUser user) - { + public int resetPwd(SysUser user) { return userMapper.updateUser(user); } /** * 重置用户密码 - * + * * @param userName 用户名 * @param password 密码 * @return 结果 */ @Override - public int resetUserPwd(String userName, String password) - { + public int resetUserPwd(String userName, String password) { return userMapper.resetUserPwd(userName, password); } /** * 新增用户角色信息 - * + * * @param user 用户对象 */ - public void insertUserRole(SysUser user) - { + public void insertUserRole(SysUser user) { Long[] roles = user.getRoleIds(); - if (StringUtils.isNotNull(roles)) - { + if (StringUtils.isNotNull(roles)) { // 新增用户与角色管理 List list = new ArrayList(); - for (Long roleId : roles) - { + for (Long roleId : roles) { SysUserRole ur = new SysUserRole(); ur.setUserId(user.getUserId()); ur.setRoleId(roleId); list.add(ur); } - if (list.size() > 0) - { + if (list.size() > 0) { userRoleMapper.batchUserRole(list); } } @@ -332,25 +221,21 @@ public class SysUserServiceImpl implements ISysUserService /** * 新增用户岗位信息 - * + * * @param user 用户对象 */ - public void insertUserPost(SysUser user) - { + public void insertUserPost(SysUser user) { Long[] posts = user.getPostIds(); - if (StringUtils.isNotNull(posts)) - { + if (StringUtils.isNotNull(posts)) { // 新增用户与岗位管理 List list = new ArrayList(); - for (Long postId : posts) - { + for (Long postId : posts) { SysUserPost up = new SysUserPost(); up.setUserId(user.getUserId()); up.setPostId(postId); list.add(up); } - if (list.size() > 0) - { + if (list.size() > 0) { userPostMapper.batchUserPost(list); } } @@ -358,14 +243,13 @@ public class SysUserServiceImpl implements ISysUserService /** * 通过用户ID删除用户 - * + * * @param userId 用户ID * @return 结果 */ @Override @Transactional - public int deleteUserById(Long userId) - { + public int deleteUserById(Long userId) { // 删除用户与角色关联 userRoleMapper.deleteUserRoleByUserId(userId); // 删除用户与岗位表 @@ -375,16 +259,14 @@ public class SysUserServiceImpl implements ISysUserService /** * 批量删除用户信息 - * + * * @param userIds 需要删除的用户ID * @return 结果 */ @Override @Transactional - public int deleteUserByIds(Long[] userIds) - { - for (Long userId : userIds) - { + public int deleteUserByIds(Long[] userIds) { + for (Long userId : userIds) { checkUserAllowed(new SysUser(userId)); } // 删除用户与角色关联 @@ -396,17 +278,15 @@ public class SysUserServiceImpl implements ISysUserService /** * 导入用户数据 - * - * @param userList 用户数据列表 + * + * @param userList 用户数据列表 * @param isUpdateSupport 是否更新支持,如果已存在,则进行更新数据 - * @param operName 操作用户 + * @param operName 操作用户 * @return 结果 */ @Override - public String importUser(List userList, Boolean isUpdateSupport, String operName) - { - if (StringUtils.isNull(userList) || userList.size() == 0) - { + public String importUser(List userList, Boolean isUpdateSupport, String operName) { + if (StringUtils.isNull(userList) || userList.size() == 0) { throw new CustomException("导入用户数据不能为空!"); } int successNum = 0; @@ -414,48 +294,36 @@ public class SysUserServiceImpl implements ISysUserService StringBuilder successMsg = new StringBuilder(); StringBuilder failureMsg = new StringBuilder(); String password = configService.selectConfigByKey("sys.user.initPassword"); - for (SysUser user : userList) - { - try - { + for (SysUser user : userList) { + try { // 验证是否存在这个用户 SysUser u = userMapper.selectUserByUserName(user.getUserName()); - if (StringUtils.isNull(u)) - { + if (StringUtils.isNull(u)) { user.setPassword(SecurityUtils.encryptPassword(password)); user.setCreateBy(operName); this.insertUser(user); successNum++; successMsg.append("
" + successNum + "、账号 " + user.getUserName() + " 导入成功"); - } - else if (isUpdateSupport) - { + } else if (isUpdateSupport) { user.setUpdateBy(operName); this.updateUser(user); successNum++; successMsg.append("
" + successNum + "、账号 " + user.getUserName() + " 更新成功"); - } - else - { + } else { failureNum++; failureMsg.append("
" + failureNum + "、账号 " + user.getUserName() + " 已存在"); } - } - catch (Exception e) - { + } catch (Exception e) { failureNum++; String msg = "
" + failureNum + "、账号 " + user.getUserName() + " 导入失败:"; failureMsg.append(msg + e.getMessage()); log.error(msg, e); } } - if (failureNum > 0) - { + if (failureNum > 0) { failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:"); throw new CustomException(failureMsg.toString()); - } - else - { + } else { successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:"); } return successMsg.toString(); diff --git a/ruoyi-ui/src/api/system/user.js b/ruoyi-ui/src/api/system/user.js index 7f8db39ee..aa92d8b7b 100644 --- a/ruoyi-ui/src/api/system/user.js +++ b/ruoyi-ui/src/api/system/user.js @@ -4,7 +4,7 @@ import { praseStrEmpty } from "@/utils/ruoyi"; // 查询用户列表 export function listUser(query) { return request({ - url: '/system/user/list', + url: '/system/user/page', method: 'get', params: query }) @@ -13,7 +13,7 @@ export function listUser(query) { // 查询用户详细 export function getUser(userId) { return request({ - url: '/system/user/' + praseStrEmpty(userId), + url: '/system/user/get?id=' + praseStrEmpty(userId), method: 'get' }) } @@ -21,7 +21,7 @@ export function getUser(userId) { // 新增用户 export function addUser(data) { return request({ - url: '/system/user', + url: '/system/user/create', method: 'post', data: data }) @@ -30,7 +30,7 @@ export function addUser(data) { // 修改用户 export function updateUser(data) { return request({ - url: '/system/user', + url: '/system/user/update', method: 'put', data: data }) @@ -39,7 +39,7 @@ export function updateUser(data) { // 删除用户 export function delUser(userId) { return request({ - url: '/system/user/' + userId, + url: '/system/user/delete?id=' + userId, method: 'delete' }) } @@ -73,7 +73,7 @@ export function changeUserStatus(userId, status) { status } return request({ - url: '/system/user/changeStatus', + url: '/system/user/updateStatus', method: 'put', data: data }) diff --git a/ruoyi-ui/src/views/system/user/index.vue b/ruoyi-ui/src/views/system/user/index.vue index d126f59e4..ab05e47ae 100644 --- a/ruoyi-ui/src/views/system/user/index.vue +++ b/ruoyi-ui/src/views/system/user/index.vue @@ -28,9 +28,9 @@ - + - + @@ -92,26 +92,6 @@ v-hasPermi="['system:user:add']" >新增 - - 修改 - - - 删除 - - - - - - - - + + + + + + @@ -170,7 +149,7 @@ v-hasPermi="['system:user:edit']" >修改 @@ -203,8 +182,8 @@ - - + + @@ -215,8 +194,8 @@ - - + + @@ -227,12 +206,12 @@ - - + + - + @@ -344,6 +323,11 @@ import { treeselect } from "@/api/system/dept"; import Treeselect from "@riophae/vue-treeselect"; import "@riophae/vue-treeselect/dist/vue-treeselect.css"; +import {listSimpleDepts} from "@/api/system/dept"; + +import {SysCommonStatusEnum} from "@/utils/constants"; +import {DICT_TYPE, getDictDatas} from "@/utils/dict"; + export default { name: "User", components: { Treeselect }, @@ -351,12 +335,6 @@ export default { return { // 遮罩层 loading: true, - // 选中数组 - ids: [], - // 非单个禁用 - single: true, - // 非多个禁用 - multiple: true, // 显示搜索条件 showSearch: true, // 总条数 @@ -387,7 +365,7 @@ export default { form: {}, defaultProps: { children: "children", - label: "label" + label: "name" }, // 用户导入参数 upload: { @@ -406,19 +384,19 @@ export default { }, // 查询参数 queryParams: { - pageNum: 1, + pageNo: 1, pageSize: 10, - userName: undefined, - phonenumber: undefined, + username: undefined, + mobile: undefined, status: undefined, deptId: undefined }, // 表单校验 rules: { - userName: [ + username: [ { required: true, message: "用户名称不能为空", trigger: "blur" } ], - nickName: [ + nickname: [ { required: true, message: "用户昵称不能为空", trigger: "blur" } ], password: [ @@ -431,14 +409,19 @@ export default { trigger: ["blur", "change"] } ], - phonenumber: [ + mobile: [ { pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/, message: "请输入正确的手机号码", trigger: "blur" } ] - } + }, + + // 枚举 + SysCommonStatusEnum: SysCommonStatusEnum, + // 数据字典 + statusDictDatas: getDictDatas(DICT_TYPE.SYS_COMMON_STATUS), }; }, watch: { @@ -450,12 +433,6 @@ export default { created() { this.getList(); this.getTreeselect(); - this.getDicts("sys_normal_disable").then(response => { - this.statusOptions = response.data; - }); - this.getDicts("sys_user_sex").then(response => { - this.sexOptions = response.data; - }); this.getConfigKey("sys.user.initPassword").then(response => { this.initPassword = response.msg; }); @@ -464,23 +441,28 @@ export default { /** 查询用户列表 */ getList() { this.loading = true; - listUser(this.addDateRange(this.queryParams, this.dateRange)).then(response => { - this.userList = response.rows; - this.total = response.total; + listUser(this.addDateRange(this.queryParams, [ + this.dateRange[0] ? this.dateRange[0] + ' 00:00:00' : undefined, + this.dateRange[1] ? this.dateRange[1] + ' 23:59:59' : undefined, + ])).then(response => { + this.userList = response.data.list; + this.total = response.data.list; this.loading = false; } ); }, /** 查询部门下拉树结构 */ getTreeselect() { - treeselect().then(response => { - this.deptOptions = response.data; + listSimpleDepts().then(response => { + // 处理 menuOptions 参数 + this.deptOptions = []; + this.deptOptions.push(...this.handleTree(response.data, "id")); }); }, // 筛选节点 filterNode(value, data) { if (!value) return true; - return data.label.indexOf(value) !== -1; + return data.name.indexOf(value) !== -1; }, // 节点单击事件 handleNodeClick(data) { @@ -490,12 +472,12 @@ export default { // 用户状态修改 handleStatusChange(row) { let text = row.status === "0" ? "启用" : "停用"; - this.$confirm('确认要"' + text + '""' + row.userName + '"用户吗?', "警告", { + this.$confirm('确认要"' + text + '""' + row.username + '"用户吗?', "警告", { confirmButtonText: "确定", cancelButtonText: "取消", type: "warning" }).then(function() { - return changeUserStatus(row.userId, row.status); + return changeUserStatus(row.id, row.status); }).then(() => { this.msgSuccess(text + "成功"); }).catch(function() { @@ -510,12 +492,12 @@ export default { // 表单重置 reset() { this.form = { - userId: undefined, + id: undefined, deptId: undefined, - userName: undefined, - nickName: undefined, + username: undefined, + nickname: undefined, password: undefined, - phonenumber: undefined, + mobile: undefined, email: undefined, sex: undefined, status: "0", @@ -536,12 +518,6 @@ export default { this.resetForm("queryForm"); this.handleQuery(); }, - // 多选框选中数据 - handleSelectionChange(selection) { - this.ids = selection.map(item => item.userId); - this.single = selection.length != 1; - this.multiple = !selection.length; - }, /** 新增按钮操作 */ handleAdd() { this.reset(); @@ -558,8 +534,8 @@ export default { handleUpdate(row) { this.reset(); this.getTreeselect(); - const userId = row.userId || this.ids; - getUser(userId).then(response => { + const id = row.id; + getUser(id).then(response => { this.form = response.data; this.postOptions = response.posts; this.roleOptions = response.roles; @@ -572,11 +548,11 @@ export default { }, /** 重置密码按钮操作 */ handleResetPwd(row) { - this.$prompt('请输入"' + row.userName + '"的新密码', "提示", { + this.$prompt('请输入"' + row.username + '"的新密码', "提示", { confirmButtonText: "确定", cancelButtonText: "取消" }).then(({ value }) => { - resetUserPwd(row.userId, value).then(response => { + resetUserPwd(row.id, value).then(response => { this.msgSuccess("修改成功,新密码是:" + value); }); }).catch(() => {}); @@ -585,7 +561,7 @@ export default { submitForm: function() { this.$refs["form"].validate(valid => { if (valid) { - if (this.form.userId != undefined) { + if (this.form.id != undefined) { updateUser(this.form).then(response => { this.msgSuccess("修改成功"); this.open = false; @@ -603,13 +579,13 @@ export default { }, /** 删除按钮操作 */ handleDelete(row) { - const userIds = row.userId || this.ids; - this.$confirm('是否确认删除用户编号为"' + userIds + '"的数据项?', "警告", { + const ids = row.id || this.ids; + this.$confirm('是否确认删除用户编号为"' + ids + '"的数据项?', "警告", { confirmButtonText: "确定", cancelButtonText: "取消", type: "warning" }).then(function() { - return delUser(userIds); + return delUser(ids); }).then(() => { this.getList(); this.msgSuccess("删除成功"); @@ -657,4 +633,4 @@ export default { } } }; - \ No newline at end of file + diff --git a/src/main/java/cn/iocoder/dashboard/common/pojo/PageResult.java b/src/main/java/cn/iocoder/dashboard/common/pojo/PageResult.java index 182ebad1f..fa7d109d9 100644 --- a/src/main/java/cn/iocoder/dashboard/common/pojo/PageResult.java +++ b/src/main/java/cn/iocoder/dashboard/common/pojo/PageResult.java @@ -5,6 +5,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.io.Serializable; +import java.util.ArrayList; import java.util.List; @ApiModel("分页结果") @@ -17,4 +18,17 @@ public final class PageResult implements Serializable { @ApiModelProperty(value = "总量", required = true) private Long total; + public PageResult() { + } + + public PageResult(List list, Long total) { + this.list = list; + this.total = total; + } + + public PageResult(Long total) { + this.list = new ArrayList<>(); + this.total = total; + } + } diff --git a/src/main/java/cn/iocoder/dashboard/framework/security/core/LoginUser.java b/src/main/java/cn/iocoder/dashboard/framework/security/core/LoginUser.java index b18e574bb..d8b060469 100644 --- a/src/main/java/cn/iocoder/dashboard/framework/security/core/LoginUser.java +++ b/src/main/java/cn/iocoder/dashboard/framework/security/core/LoginUser.java @@ -21,7 +21,7 @@ public class LoginUser implements UserDetails { /** * 用户编号 */ - private Long userId; + private Long id; /** * 科室编号 */ diff --git a/src/main/java/cn/iocoder/dashboard/framework/security/core/handler/AccessDeniedHandlerImpl.java b/src/main/java/cn/iocoder/dashboard/framework/security/core/handler/AccessDeniedHandlerImpl.java index 8698ef2de..cd9c7a39e 100644 --- a/src/main/java/cn/iocoder/dashboard/framework/security/core/handler/AccessDeniedHandlerImpl.java +++ b/src/main/java/cn/iocoder/dashboard/framework/security/core/handler/AccessDeniedHandlerImpl.java @@ -6,7 +6,6 @@ import cn.iocoder.dashboard.framework.security.core.util.SecurityUtils; import cn.iocoder.dashboard.util.servlet.ServletUtils; import lombok.extern.slf4j.Slf4j; import org.springframework.security.access.AccessDeniedException; -import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.access.AccessDeniedHandler; import org.springframework.security.web.access.ExceptionTranslationFilter; import org.springframework.stereotype.Component; @@ -36,7 +35,7 @@ public class AccessDeniedHandlerImpl implements AccessDeniedHandler { throws IOException, ServletException { // 打印 warn 的原因是,不定期合并 warn,看看有没恶意破坏 log.warn("[commence][访问 URL({}) 时,用户({}) 权限不够]", request.getRequestURI(), - SecurityUtils.getLoginUser().getUserId(), e); + SecurityUtils.getLoginUser().getId(), e); // 返回 403 ServletUtils.writeJSON(response, CommonResult.error(UNAUTHORIZED)); } diff --git a/src/main/java/cn/iocoder/dashboard/framework/security/core/util/SecurityUtils.java b/src/main/java/cn/iocoder/dashboard/framework/security/core/util/SecurityUtils.java index 5d333ed84..4107b8724 100644 --- a/src/main/java/cn/iocoder/dashboard/framework/security/core/util/SecurityUtils.java +++ b/src/main/java/cn/iocoder/dashboard/framework/security/core/util/SecurityUtils.java @@ -50,7 +50,7 @@ public class SecurityUtils { * @return 用户编号 */ public static Long getLoginUserId() { - return getLoginUser().getUserId(); + return getLoginUser().getId(); } public static Set getLoginUserRoleIds() { diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserController.java b/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserController.java index 03b831574..550acf644 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserController.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserController.java @@ -1,18 +1,64 @@ package cn.iocoder.dashboard.modules.system.controller.user; +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.dashboard.common.pojo.CommonResult; +import cn.iocoder.dashboard.common.pojo.PageResult; +import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserPageItemRespVO; +import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserPageReqVO; +import cn.iocoder.dashboard.modules.system.convert.user.SysUserConvert; +import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.dept.SysDeptDO; +import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.user.SysUserDO; +import cn.iocoder.dashboard.modules.system.service.dept.SysDeptService; +import cn.iocoder.dashboard.modules.system.service.user.SysUserService; +import cn.iocoder.dashboard.util.collection.CollectionUtils; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import java.util.*; + +import static cn.iocoder.dashboard.common.pojo.CommonResult.success; + +@Api(tags = "用户 API") +@RestController +@RequestMapping("/system/user") public class SysUserController { -// /** -// * 获取用户列表 -// */ + @Resource + private SysUserService userService; + @Resource + private SysDeptService deptService; + + @ApiOperation("获得用户分页列表") + @GetMapping("/page") // @PreAuthorize("@ss.hasPermi('system:user:list')") -// @GetMapping("/list") -// public TableDataInfo list(SysUser user) -// { -// startPage(); -// List list = userService.selectUserList(user); -// return getDataTable(list); -// } + public CommonResult> pageUsers(SysUserPageReqVO reqVO) { + // 获得用户分页列表 + PageResult pageResult = userService.pageUsers(reqVO); + if (CollUtil.isEmpty(pageResult.getList())) { + return success(new PageResult<>(pageResult.getTotal())); // 返回空 + } + + // 获得拼接需要的数据 + Map deptMap; + Collection deptIds = CollectionUtils.convertList(pageResult.getList(), SysUserDO::getDeptId); + if (CollUtil.isNotEmpty(deptIds)) { + deptMap = CollectionUtils.convertMap(deptService.listDepts(deptIds), SysDeptDO::getId); + } else { + deptMap = Collections.emptyMap(); + } + // 拼接结果返回 + List userList = new ArrayList<>(pageResult.getList().size()); + pageResult.getList().forEach(user -> { + SysUserPageItemRespVO respVO = SysUserConvert.INSTANCE.convert(user); + respVO.setDept(SysUserConvert.INSTANCE.convert(deptMap.get(user.getDeptId()))); + userList.add(respVO); + }); + return success(new PageResult<>(userList, pageResult.getTotal())); + } // // @Log(title = "用户管理", businessType = BusinessType.EXPORT) // @PreAuthorize("@ss.hasPermi('system:user:export')") diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserPageItemRespVO.java b/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserPageItemRespVO.java new file mode 100644 index 000000000..e98b07298 --- /dev/null +++ b/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserPageItemRespVO.java @@ -0,0 +1,34 @@ +package cn.iocoder.dashboard.modules.system.controller.user.vo.user; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +@ApiModel(value = "用户分页时的信息 Response VO", description = "相比用户基本信息来说,会多部门信息") +@Data +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class SysUserPageItemRespVO extends SysUserRespVO { + + /** + * 所在部门 + */ + private Dept dept; + + @ApiModel("部门") + @Data + public static class Dept { + + @ApiModelProperty(value = "部门编号", required = true, example = "1") + private Integer id; + + @ApiModelProperty(value = "部门名称", required = true, example = "研发部") + private String name; + + } + +} diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserPageReqVO.java b/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserPageReqVO.java new file mode 100644 index 000000000..03efb8ceb --- /dev/null +++ b/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserPageReqVO.java @@ -0,0 +1,43 @@ +package cn.iocoder.dashboard.modules.system.controller.user.vo.user; + +import cn.iocoder.dashboard.common.pojo.PageParam; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +import static cn.iocoder.dashboard.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@ApiModel("用户分页 Request VO") +@Data +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class SysUserPageReqVO extends PageParam { + + @ApiModelProperty(value = "用户账号", example = "yudao", notes = "模糊匹配") + private String username; + + @ApiModelProperty(value = "手机号码", example = "yudao", notes = "模糊匹配") + private String mobile; + + @ApiModelProperty(value = "展示状态", example = "1", notes = "参见 SysCommonStatusEnum 枚举类") + private Integer status; + + @ApiModelProperty(value = "开始时间", example = "2020-10-24") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private Date beginTime; + + @ApiModelProperty(value = "结束时间", example = "2020-10-24") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private Date endTime; + + @ApiModelProperty(value = "部门编号", example = "1024", notes = "同时筛选子部门") + private Long deptId; + +} diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/convert/user/SysUserConvert.java b/src/main/java/cn/iocoder/dashboard/modules/system/convert/user/SysUserConvert.java new file mode 100644 index 000000000..e79f51b3f --- /dev/null +++ b/src/main/java/cn/iocoder/dashboard/modules/system/convert/user/SysUserConvert.java @@ -0,0 +1,24 @@ +package cn.iocoder.dashboard.modules.system.convert.user; + +import cn.iocoder.dashboard.common.pojo.PageResult; +import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserPageItemRespVO; +import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.dept.SysDeptDO; +import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.user.SysUserDO; +import com.baomidou.mybatisplus.core.metadata.IPage; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.factory.Mappers; + +@Mapper +public interface SysUserConvert { + + SysUserConvert INSTANCE = Mappers.getMapper(SysUserConvert.class); + + SysUserPageItemRespVO convert(SysUserDO bean); + + SysUserPageItemRespVO.Dept convert(SysDeptDO bean); + + @Mapping(source = "records", target = "list") + PageResult convertPage(IPage page); + +} diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dao/user/SysUserMapper.java b/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dao/user/SysUserMapper.java index de4bbfd69..26c52322e 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dao/user/SysUserMapper.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dao/user/SysUserMapper.java @@ -1,10 +1,16 @@ package cn.iocoder.dashboard.modules.system.dal.mysql.dao.user; +import cn.iocoder.dashboard.framework.mybatis.core.query.QueryWrapperX; +import cn.iocoder.dashboard.framework.mybatis.core.util.MyBatisUtils; +import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserPageReqVO; import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.user.SysUserDO; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; import org.apache.ibatis.annotations.Mapper; +import java.util.List; + @Mapper public interface SysUserMapper extends BaseMapper { @@ -12,4 +18,14 @@ public interface SysUserMapper extends BaseMapper { return selectOne(new QueryWrapper().eq("username", username)); } + default IPage selectList(SysUserPageReqVO reqVO, List deptIds) { + return selectPage(MyBatisUtils.buildPage(reqVO), + new QueryWrapperX().likeIfPresent("username", reqVO.getUsername()) + .likeIfPresent("mobile", reqVO.getMobile()) + .eqIfPresent("status", reqVO.getStatus()) + .betweenIfPresent("create_time", reqVO.getBeginTime(), reqVO.getEndTime()) + .inIfPresent("dept_id", deptIds)); + } + } + diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/auth/impl/SysAuthServiceImpl.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/auth/impl/SysAuthServiceImpl.java index f733eb46f..825022001 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/service/auth/impl/SysAuthServiceImpl.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/auth/impl/SysAuthServiceImpl.java @@ -80,7 +80,7 @@ public class SysAuthServiceImpl implements SysAuthService { // 创建 LoginUser 对象 LoginUser loginUser = SysAuthConvert.INSTANCE.convert(user); loginUser.setUpdateTime(new Date()); - loginUser.setRoleIds(this.getUserRoleIds(loginUser.getUserId())); + loginUser.setRoleIds(this.getUserRoleIds(loginUser.getId())); return loginUser; } @@ -94,7 +94,7 @@ public class SysAuthServiceImpl implements SysAuthService { // 缓存登陆用户到 Redis 中 String sessionId = IdUtil.fastSimpleUUID(); loginUser.setUpdateTime(new Date()); - loginUser.setRoleIds(this.getUserRoleIds(loginUser.getUserId())); + loginUser.setRoleIds(this.getUserRoleIds(loginUser.getId())); loginUserRedisDAO.set(sessionId, loginUser); // 创建 Token @@ -197,7 +197,7 @@ public class SysAuthServiceImpl implements SysAuthService { } // 重新加载 SysUserDO 信息 - SysUserDO user = userService.getUser(loginUser.getUserId()); + SysUserDO user = userService.getUser(loginUser.getId()); if (user == null || CommonStatusEnum.DISABLE.getStatus().equals(user.getStatus())) { throw exception(TOKEN_EXPIRED); // 校验 token 时,用户被禁用的情况下,也认为 token 过期,方便前端跳转到登陆界面 } @@ -205,7 +205,7 @@ public class SysAuthServiceImpl implements SysAuthService { // 刷新 LoginUser 缓存 loginUser.setDeptId(user.getDeptId()); loginUser.setUpdateTime(new Date()); - loginUser.setRoleIds(this.getUserRoleIds(loginUser.getUserId())); + loginUser.setRoleIds(this.getUserRoleIds(loginUser.getId())); loginUserRedisDAO.set(sessionId, loginUser); } diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/dept/SysDeptService.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/dept/SysDeptService.java index 95e430302..c8ba0625b 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/service/dept/SysDeptService.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/dept/SysDeptService.java @@ -3,6 +3,7 @@ package cn.iocoder.dashboard.modules.system.service.dept; import cn.iocoder.dashboard.modules.system.controller.dept.vo.dept.SysDeptListReqVO; import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.dept.SysDeptDO; +import java.util.Collection; import java.util.List; /** @@ -12,6 +13,11 @@ import java.util.List; */ public interface SysDeptService { + /** + * 初始化 + */ + void init(); + /** * 获得所有部门列表 * @@ -19,6 +25,14 @@ public interface SysDeptService { */ List listDepts(); + /** + * 获得指定编号的部门列表 + * + * @param ids 部门编号数组 + * @return 部门列表 + */ + List listDepts(Collection ids); + /** * 筛选部门列表 * @@ -27,4 +41,13 @@ public interface SysDeptService { */ List listDepts(SysDeptListReqVO reqVO); + /** + * 获得所有子部门,从缓存中 + * + * @param parentId 部门编号 + * @param recursive 是否递归获取所有 + * @return 子部门列表 + */ + List listDeptsByParentIdFromCache(Long parentId, boolean recursive); + } diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/dept/impl/SysDeptServiceImpl.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/dept/impl/SysDeptServiceImpl.java index 9c4cd98b8..ab486fb4e 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/service/dept/impl/SysDeptServiceImpl.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/dept/impl/SysDeptServiceImpl.java @@ -1,13 +1,22 @@ package cn.iocoder.dashboard.modules.system.service.dept.impl; +import cn.hutool.core.collection.CollUtil; import cn.iocoder.dashboard.modules.system.controller.dept.vo.dept.SysDeptListReqVO; import cn.iocoder.dashboard.modules.system.dal.mysql.dao.dept.SysDeptMapper; import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.dept.SysDeptDO; import cn.iocoder.dashboard.modules.system.service.dept.SysDeptService; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.Multimap; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import javax.annotation.PostConstruct; import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.Collection; import java.util.List; +import java.util.Map; /** * 部门 Service 实现类 @@ -15,19 +24,94 @@ import java.util.List; * @author 芋道源码 */ @Service +@Slf4j public class SysDeptServiceImpl implements SysDeptService { + /** + * 部门缓存 + * key:部门编号 {@link SysDeptDO#getId()} + * + * 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向 + */ + private volatile Map deptCache; + /** + * 父部门缓存 + * key:部门编号 {@link SysDeptDO#getParentId()} + * value: 直接子部门列表 + * + * 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向 + */ + private volatile Multimap parentDeptCache; + @Resource private SysDeptMapper deptMapper; + @Override + @PostConstruct + public void init() { + // 从数据库中读取 + List sysDeptDOList = deptMapper.selectList(); + // 构建缓存 + ImmutableMap.Builder builder = ImmutableMap.builder(); + ImmutableMultimap.Builder parentBuilder = ImmutableMultimap.builder(); + sysDeptDOList.forEach(sysRoleDO -> { + builder.put(sysRoleDO.getId(), sysRoleDO); + parentBuilder.put(sysRoleDO.getParentId(), sysRoleDO); + }); + // 设置缓存 + deptCache = builder.build(); + parentDeptCache = parentBuilder.build(); + log.info("[init][初始化 Dept 数量为 {}]", sysDeptDOList.size()); + } + @Override public List listDepts() { return deptMapper.selectList(); } + @Override + public List listDepts(Collection ids) { + return deptMapper.selectBatchIds(ids); + } + @Override public List listDepts(SysDeptListReqVO reqVO) { return deptMapper.selectList(reqVO); } + @Override + public List listDeptsByParentIdFromCache(Long parentId, boolean recursive) { + List result = new ArrayList<>(); + // 递归,简单粗暴 + this.listDeptsByParentIdFromCache(result, parentId, + recursive ? Integer.MAX_VALUE : 1, // 如果递归获取,则无限;否则,只递归 1 次 + parentDeptCache); + return result; + } + + /** + * 递归获取所有的子部门,添加到 result 结果 + * + * @param result 结果 + * @param parentId 父编号 + * @param recursiveCount 递归次数 + * @param parentDeptMap 父部门 Map,使用缓存,避免变化 + */ + private void listDeptsByParentIdFromCache(List result, Long parentId, int recursiveCount, + Multimap parentDeptMap) { + // 递归次数为 0,结束! + if (recursiveCount == 0) { + return; + } + // 获得子部门 + Collection depts = parentDeptMap.get(parentId); + if (CollUtil.isEmpty(depts)) { + return; + } + result.addAll(depts); + // 继续递归 + depts.forEach(dept -> listDeptsByParentIdFromCache(result, dept.getId(), + recursiveCount - 1, parentDeptMap)); + } + } diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysRoleServiceImpl.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysRoleServiceImpl.java index eeff67cab..ae40775e2 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysRoleServiceImpl.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysRoleServiceImpl.java @@ -37,12 +37,6 @@ import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.*; @Slf4j public class SysRoleServiceImpl implements SysRoleService { - @Resource - private SysPermissionService permissionService; - - @Resource - private SysRoleMapper roleMapper; - /** * 角色缓存 * key:角色编号 {@link SysRoleDO#getId()} @@ -51,6 +45,12 @@ public class SysRoleServiceImpl implements SysRoleService { */ private volatile Map roleCache; + @Resource + private SysPermissionService permissionService; + + @Resource + private SysRoleMapper roleMapper; + /** * 初始化 {@link #roleCache} 缓存 */ diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserService.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserService.java index f9d34486b..16e66a66b 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserService.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserService.java @@ -1,11 +1,13 @@ package cn.iocoder.dashboard.modules.system.service.user; +import cn.iocoder.dashboard.common.pojo.PageResult; +import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserPageReqVO; import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.user.SysUserDO; /** * 用户 Service 接口 * - * @author ruoyi + * @author 芋道源码 */ public interface SysUserService { // /** @@ -32,6 +34,14 @@ public interface SysUserService { */ SysUserDO getUser(Long userId); + /** + * 获得用户分页列表 + * + * @param reqVO 分页条件 + * @return 分页列表 + */ + PageResult pageUsers(SysUserPageReqVO reqVO); + // // /** // * 根据用户ID查询用户所属角色组 diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserServiceImpl.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserServiceImpl.java index 09afeb521..85d4f2a5f 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserServiceImpl.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserServiceImpl.java @@ -1,17 +1,25 @@ package cn.iocoder.dashboard.modules.system.service.user; +import cn.iocoder.dashboard.common.pojo.PageResult; +import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserPageReqVO; +import cn.iocoder.dashboard.modules.system.convert.user.SysUserConvert; import cn.iocoder.dashboard.modules.system.dal.mysql.dao.user.SysUserMapper; +import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.dept.SysDeptDO; import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.user.SysUserDO; +import cn.iocoder.dashboard.modules.system.service.dept.SysDeptService; +import cn.iocoder.dashboard.util.collection.CollectionUtils; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import javax.annotation.Resource; +import java.util.Collections; +import java.util.List; /** - * 用户 业务层处理 + * 用户 Service 实现类 * - * @author ruoyi + * @author 芋道源码 */ @Service @Slf4j @@ -20,6 +28,9 @@ public class SysUserServiceImpl implements SysUserService { @Resource private SysUserMapper userMapper; + @Resource + private SysDeptService deptService; + // @Autowired // private SysUserMapper userMapper; // @@ -61,6 +72,19 @@ public class SysUserServiceImpl implements SysUserService { return userMapper.selectById(userId); } + @Override + public PageResult pageUsers(SysUserPageReqVO reqVO) { + // 处理部门查询条件 + List deptIds = Collections.emptyList(); + if (reqVO.getDeptId() != null) { + deptIds = CollectionUtils.convertList(deptService.listDeptsByParentIdFromCache(reqVO.getDeptId(), true), + SysDeptDO::getId); + deptIds.add(reqVO.getDeptId()); + } + // 执行查询 + return SysUserConvert.INSTANCE.convertPage(userMapper.selectList(reqVO, deptIds)); + } + // /** // * 通过用户ID查询用户 // *