# AuthorityManagement
**Repository Path**: sunchang0101/AuthorityManagement
## Basic Information
- **Project Name**: AuthorityManagement
- **Description**: SpringBoot + Vue2
- **Primary Language**: Java
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2023-08-02
- **Last Updated**: 2024-03-08
## Categories & Tags
**Categories**: Uncategorized
**Tags**: SpringBoot, vue2, mybatis-plus
## README
# 0.博客
[CSDN](https://blog.csdn.net/qq_43336396/article/details/132133822?spm=1001.2014.3001.5502)
# 1.文件(夹)说明
前后端分离
# 2.参考
[视频](https://www.bilibili.com/video/BV1ad4y1y7LU/?spm_id_from=333.999.0.0)
[资源](https://pan.baidu.com/s/1faiMIENEgBDPTM661BUXLQ?pwd=yyds)
# 3.技术栈
|技术|功能|
|--|--|
|SSM|Java EE框架|
|Spring Boot|Java EE框架|
|MyBatis-Plus|ORM框架|
|MySQL|数据库|
|Redis|数据缓存|
|Swagger|RESTful风格的API工具|
|Vue2|JS框架|
|HTML|页面|
|Element-UI|样式|
|Axios|网络异步|
|vue-element-admin|Vue框架|
# 4.项目简介
|/|0/1 |
|--|--|
|前后端分离|1|
|模块化开发|0|
|技术侧重|全栈|
|||
# 5.业务实现
### 1)角色管理:CUDR
### 2)用户管理:CUDR
### 3)菜单管理:CUDR
### 4)权限管理
(1)用户是否被禁用
(2)用户分配角色
(3)角色分配权限
# 6.业务分析
## 6.0 跨域
### 1)什么是跨域:前端后端项目访问接口地址不一致
### 2)如何解决跨域:
前端:代理服务器
后端:CORS、JSONP
### 3)跨域被解决的示例

## 6.1 登陆
### 6.1.1 效验
#### 前端:
1)事件绑定:login/index.vue

2)vuex判断:store/modules/user.js

3)接口请求:api/user.js

4)Axios二次封装:util/request.js
_
总:vuex取(缓存)信息(token)判断,再用Axios向后端发送请求_
#### 后端:
##### 1)Controller:
0)地址映射

_【注】
请求方法与请求路径相对应;
前端:传参并(修改)呈现
后端:接收参数并返回_
1)效验
2)状态判断
3)生成并存储token
```java
@PostMapping("login")
public Result login(@RequestBody LoginVo loginVo) {
// 1.判断用户是否存在
SysUser sysUser = sysUserService.getUserInfoByUserName(loginVo.getUsername());
if(sysUser == null) {
throw new GuiguException(20001,"用户名错误");
}
// 2.判断密码是否正确
String password = loginVo.getPassword();
// 加密
String md5Password = MD5.encrypt(password);
if(!sysUser.getPassword().equals(md5Password)) {
throw new GuiguException(20001,"密码不正确");
}
// 3.判断用户是否被禁用
if(sysUser.getStatus().intValue()==0) {
throw new GuiguException(20001,"用户已经被禁用");
}
// 4.生成token 根据userid和username生成token字符串,通过map返回
String token = JwtHelper.createToken(sysUser.getId(), sysUser.getUsername());
Map map = new HashMap<>();
map.put("token",token);
return Result.ok(map);
}
```
##### 2)Impl:
```java
// 更改用户状态
@Override
public void updateStatus(String id, Integer status) {
// 根据用户id查询
SysUser sysUser = baseMapper.selectById(id);
// 更新用户状态
sysUser.setStatus(status);
// 调用方法修改
baseMapper.updateById(sysUser);
}
// username查询
@Override
public SysUser getUserInfoByUserName(String username) {
// SELECT * FROM sys_user WHERE username = 'username';
QueryWrapper wrapper = new QueryWrapper<>();
wrapper.eq("username",username);
return baseMapper.selectOne(wrapper);
}
```
_**【注】如下功能点不再考虑地址映射并弱化前端描述**_
## 6.2 登陆后页面呈现
**
【思路】
0)前端请求传值
1)获取token
2)根据token获取身份
3)根据身份获取权限
4)构建树形结构
**
### 6.2.1 Controller
```java
@GetMapping("info")
public Result info(HttpServletRequest request) {
// 1.获取请求头token字符串
String token = request.getHeader("token");
// 2.从token字符串获取用户名称(id)
String username = JwtHelper.getUsername(token);
// 3.根据用户名称获取用户信息(基本信息 和 菜单权限 和 按钮权限数据)
Map map = sysUserService.getUserInfo(username);
return Result.ok(map);
}
```
### 6.2.2 Impl
**_User:_**
```java
// 根据用户名称获取用户信息(基本信息 和 菜单权限 和 按钮权限数据)
@Override
public Map getUserInfo(String username) {
// 根据username查询用户基本信息
SysUser sysUser = this.getUserInfoByUserName(username);
// 根据userid查询菜单权限值
List routerVolist = sysMenuService.getUserMenuList(sysUser.getId());
// 根据userid查询按钮权限值
List permsList = sysMenuService.getUserButtonList(sysUser.getId());
Map result = new HashMap<>();
result.put("name",username);
result.put("avatar","https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif");
result.put("roles","[\"admin\"]");
// 菜单权限数据
result.put("routers",routerVolist);
// 按钮权限数据
result.put("buttons",permsList);
return result;
}
```
**_Menu:_**
```java
// 根据userid查询菜单权限值
@Override
public List getUserMenuList(String userId) {
// admin 1 超级管理员 查询所有权限数据
// !admin !1 !超级管理员 查询相关用户权限
List sysMenuList = null;
// 1.判断用户身份
if("1".equals(userId)) {
QueryWrapper wrapper = new QueryWrapper<>();
wrapper.eq("status",1);
wrapper.orderByAsc("sort_value");
sysMenuList = baseMapper.selectList(wrapper);
} else {
// 如果userid不是1,其他类型用户,查询这个用户权限
sysMenuList = baseMapper.findMenuListUserId(userId);
}
// 2.构建树形结构
List sysMenuTreeList = MenuHelper.bulidTree(sysMenuList);
// 3.构建路由结构
List routerVoList = RouterHelper.buildRouters(sysMenuTreeList);
return routerVoList;
}
//根据userid查询按钮权限值
@Override
public List getUserButtonList(String userId) {
List sysMenuList = null;
//判断是否管理员
if("1".equals(userId)) {
sysMenuList =
baseMapper.selectList(new QueryWrapper().eq("status",1));
} else {
sysMenuList = baseMapper.findMenuListUserId(userId);
}
//sysMenuList遍历
List permissionList = new ArrayList<>();
for (SysMenu sysMenu:sysMenuList) {
// type=2
if(sysMenu.getType()==2) {
String perms = sysMenu.getPerms();
permissionList.add(perms);
}
}
return permissionList;
}
```
## 6.3 分页
### 6.3.1 思路

### 6.3.2 前端
```vue
搜索
重置
// 分页
// 控制:每页展示数据
handleSizeChange(limit) {
// 每页大小变化的逻辑
this.page = 1; // 重置页码为1
this.limit = limit;
this.fetchData(this.page); // 根据新的每页大小重新获取数据
},
// 控制:跳转页
handlePageChange(page) {
// 页码变化的逻辑
this.page = page;
this.fetchData(this.page); // 获取指定页码的数据
},
// 分页查询
fetchData(page = 1) {
this.page = page;
// 日期筛选
if (this.createTimes && this.createTimes.length == 2) {
this.searchObj.createTimeBegin = this.createTimes[0];
this.searchObj.createTimeEnd = this.createTimes[1];
}
api.getPageList(this.page, this.limit, this.searchObj)
.then((response) => {
this.list = response.data.records;
this.total = response.data.total;
// this.list.forEach((item) => {
// item.updateTime = this.searchObj.updateTime;
// });
});
// console.log(this.searchObj);
// console.log(this.searchObj.updateTime);
// this.searchObj.updateTime = new Date().toLocaleString();
},
```
### 6.3.3 后端
**_Controller:_**
```java
// page: 当前页码
// limit: 每页记录数
@ApiOperation("用户列表")
@GetMapping("/{page}/{limit}")
public Result list(@PathVariable Long page,
@PathVariable Long limit,
SysUserQueryVo sysUserQueryVo) {
// 创建page对象
Page pageParam = new Page<>(page,limit);
// 调用service方法
IPage pageModel = sysUserService.selectPage(pageParam,sysUserQueryVo);
return Result.ok(pageModel);
}
```
**_Impl:_**
```java
@Override
public IPage selectPage(Page pageParam, SysUserQueryVo sysUserQueryVo) {
return baseMapper.selectPage(pageParam,sysUserQueryVo);
}
```
**_【注】使用MP的Page和Ipage对象接收并处理分页_**
## 6.4 批量删除
### 6.4.1 思路

### 6.4.2 前端
```vue
添 加
批量删除
// 事件
batchRemove() {
// 批量删除
// 1.判断:选框是否选中数据
if(this.selectValue.length==0) {
this.$message.warning('请选择要删除的记录!')
return
}
// 2.提示
this.$confirm('此操作将永久删除该角色, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
// 3.取值:获取(handleSelectionChange)复选框变化的值
// 定义数组
// 获取多个复选框对应id,封装到数组里面:[1,2,3]
var idList = []
for(var i=0;i {
// 5.提示
this.$message({
type: 'success',
message: '删除成功!'
});
// 6.刷新
this.fetchData()
})
})
},
```
### 6.4.3 后端
```java
// 多个id值 [1,2,3]
// json数组格式 --- java的list集合
@PreAuthorize("hasAuthority('bnt.sysRole.remove')")
@ApiOperation("批量删除")
@DeleteMapping("batchRemove")
public Result batchRemove(@RequestBody List ids) {
sysRoleService.removeByIds(ids);
return Result.ok();
}
```
**_【注】逻辑删除的实现:_**

## 6.5 状态更改
### 6.5.1 思路

### 6.5.2 前端
```vue
// 事件
// 【更改用户状态】
switchStatus(row) {
// 判断,如果当前用户可用,修改禁用
row.status = row.status === 1 ? 0 : 1;
api.updateStatus(row.id, row.status).then((response) => {
this.$message.success(response.message || "操作成功");
this.fetchData();
});
},
```
**_【注】前端CUD操作后均需要进行再次(分页)查询_**
### 6.5.3 后端
**_Controller:_**
```java
@ApiOperation("更改用户状态")
@GetMapping("updateStatus/{id}/{status}")
public Result updateStatus(@PathVariable String id,
@PathVariable Integer status) {
sysUserService.updateStatus(id,status);
return Result.ok();
}
```
**_Impl:_**
```java
// 更改用户状态
@Override
public void updateStatus(String id, Integer status) {
// 根据用户id查询
SysUser sysUser = baseMapper.selectById(id);
// 更新用户状态
sysUser.setStatus(status);
// 调用方法修改
baseMapper.updateById(sysUser);
}
```
## 6.6 用户分配角色
### 6.6.1 思路

### 6.6.2 前端
```vue
```
### 6.6.3 后端
**_Controller:_**
```java
@ApiOperation("用户分配角色")
@PostMapping("doAssign")
public Result doAssign(@RequestBody AssginRoleVo assginRoleVo) {
sysRoleService.doAssign(assginRoleVo);
return Result.ok();
}
```
**_Impl:_**
```java
// 用户分配角色
@Override
public void doAssign(AssginRoleVo assginRoleVo) {
// 1.-:根据用户id删除之前分配的角色
QueryWrapper wrapper = new QueryWrapper<>();
wrapper.eq("user_id",assginRoleVo.getUserId());
sysUserRoleMapper.delete(wrapper);
// 2.+:获取所有的角色id,添加到角色用户关系表中表
//角色id列表
List roleIdList = assginRoleVo.getRoleIdList();
for (String roleId:roleIdList) {
SysUserRole userRole = new SysUserRole();
userRole.setUserId(assginRoleVo.getUserId());
userRole.setRoleId(roleId);
sysUserRoleMapper.insert(userRole);
}
}
```