完成用户列表的前后端对接

This commit is contained in:
YunaiV
2021-01-10 12:19:39 +08:00
parent cdaa0d9195
commit f5b7142ab6
18 changed files with 480 additions and 319 deletions

View File

@ -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<T> implements Serializable {
@ApiModelProperty(value = "总量", required = true)
private Long total;
public PageResult() {
}
public PageResult(List<T> list, Long total) {
this.list = list;
this.total = total;
}
public PageResult(Long total) {
this.list = new ArrayList<>();
this.total = total;
}
}

View File

@ -21,7 +21,7 @@ public class LoginUser implements UserDetails {
/**
* 用户编号
*/
private Long userId;
private Long id;
/**
* 科室编号
*/

View File

@ -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));
}

View File

@ -50,7 +50,7 @@ public class SecurityUtils {
* @return 用户编号
*/
public static Long getLoginUserId() {
return getLoginUser().getUserId();
return getLoginUser().getId();
}
public static Set<Long> getLoginUserRoleIds() {

View File

@ -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<SysUser> list = userService.selectUserList(user);
// return getDataTable(list);
// }
public CommonResult<PageResult<SysUserPageItemRespVO>> pageUsers(SysUserPageReqVO reqVO) {
// 获得用户分页列表
PageResult<SysUserDO> pageResult = userService.pageUsers(reqVO);
if (CollUtil.isEmpty(pageResult.getList())) {
return success(new PageResult<>(pageResult.getTotal())); // 返回空
}
// 获得拼接需要的数据
Map<Long, SysDeptDO> deptMap;
Collection<Long> deptIds = CollectionUtils.convertList(pageResult.getList(), SysUserDO::getDeptId);
if (CollUtil.isNotEmpty(deptIds)) {
deptMap = CollectionUtils.convertMap(deptService.listDepts(deptIds), SysDeptDO::getId);
} else {
deptMap = Collections.emptyMap();
}
// 拼接结果返回
List<SysUserPageItemRespVO> 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')")

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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<SysUserDO> convertPage(IPage<SysUserDO> page);
}

View File

@ -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<SysUserDO> {
@ -12,4 +18,14 @@ public interface SysUserMapper extends BaseMapper<SysUserDO> {
return selectOne(new QueryWrapper<SysUserDO>().eq("username", username));
}
default IPage<SysUserDO> selectList(SysUserPageReqVO reqVO, List<Long> deptIds) {
return selectPage(MyBatisUtils.buildPage(reqVO),
new QueryWrapperX<SysUserDO>().likeIfPresent("username", reqVO.getUsername())
.likeIfPresent("mobile", reqVO.getMobile())
.eqIfPresent("status", reqVO.getStatus())
.betweenIfPresent("create_time", reqVO.getBeginTime(), reqVO.getEndTime())
.inIfPresent("dept_id", deptIds));
}
}

View File

@ -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);
}

View File

@ -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<SysDeptDO> listDepts();
/**
* 获得指定编号的部门列表
*
* @param ids 部门编号数组
* @return 部门列表
*/
List<SysDeptDO> listDepts(Collection<Long> ids);
/**
* 筛选部门列表
*
@ -27,4 +41,13 @@ public interface SysDeptService {
*/
List<SysDeptDO> listDepts(SysDeptListReqVO reqVO);
/**
* 获得所有子部门,从缓存中
*
* @param parentId 部门编号
* @param recursive 是否递归获取所有
* @return 子部门列表
*/
List<SysDeptDO> listDeptsByParentIdFromCache(Long parentId, boolean recursive);
}

View File

@ -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<Long, SysDeptDO> deptCache;
/**
* 父部门缓存
* key部门编号 {@link SysDeptDO#getParentId()}
* value: 直接子部门列表
*
* 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向
*/
private volatile Multimap<Long, SysDeptDO> parentDeptCache;
@Resource
private SysDeptMapper deptMapper;
@Override
@PostConstruct
public void init() {
// 从数据库中读取
List<SysDeptDO> sysDeptDOList = deptMapper.selectList();
// 构建缓存
ImmutableMap.Builder<Long, SysDeptDO> builder = ImmutableMap.builder();
ImmutableMultimap.Builder<Long, SysDeptDO> 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<SysDeptDO> listDepts() {
return deptMapper.selectList();
}
@Override
public List<SysDeptDO> listDepts(Collection<Long> ids) {
return deptMapper.selectBatchIds(ids);
}
@Override
public List<SysDeptDO> listDepts(SysDeptListReqVO reqVO) {
return deptMapper.selectList(reqVO);
}
@Override
public List<SysDeptDO> listDeptsByParentIdFromCache(Long parentId, boolean recursive) {
List<SysDeptDO> 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<SysDeptDO> result, Long parentId, int recursiveCount,
Multimap<Long, SysDeptDO> parentDeptMap) {
// 递归次数为 0结束
if (recursiveCount == 0) {
return;
}
// 获得子部门
Collection<SysDeptDO> depts = parentDeptMap.get(parentId);
if (CollUtil.isEmpty(depts)) {
return;
}
result.addAll(depts);
// 继续递归
depts.forEach(dept -> listDeptsByParentIdFromCache(result, dept.getId(),
recursiveCount - 1, parentDeptMap));
}
}

View File

@ -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<Long, SysRoleDO> roleCache;
@Resource
private SysPermissionService permissionService;
@Resource
private SysRoleMapper roleMapper;
/**
* 初始化 {@link #roleCache} 缓存
*/

View File

@ -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<SysUserDO> pageUsers(SysUserPageReqVO reqVO);
//
// /**
// * 根据用户ID查询用户所属角色组

View File

@ -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<SysUserDO> pageUsers(SysUserPageReqVO reqVO) {
// 处理部门查询条件
List<Long> 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查询用户
// *