代码拉取完成,页面将自动刷新
前后端分离
技术 | 功能 |
---|---|
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框架 |
/ | 0/1 |
---|---|
前后端分离 | 1 |
模块化开发 | 0 |
技术侧重 | 全栈 |
(1)用户是否被禁用 (2)用户分配角色 (3)角色分配权限
前端:代理服务器 后端:CORS、JSONP
1)事件绑定:login/index.vue 2)vuex判断:store/modules/user.js 3)接口请求:api/user.js 4)Axios二次封装:util/request.js _ 总:vuex取(缓存)信息(token)判断,再用Axios向后端发送请求_
0)地址映射 【注】 请求方法与请求路径相对应; 前端:传参并(修改)呈现 后端:接收参数并返回
1)效验
2)状态判断
3)生成并存储token
@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<String,Object> map = new HashMap<>();
map.put("token",token);
return Result.ok(map);
}
// 更改用户状态
@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<SysUser> wrapper = new QueryWrapper<>();
wrapper.eq("username",username);
return baseMapper.selectOne(wrapper);
}
【注】如下功能点不再考虑地址映射并弱化前端描述
**
【思路】
0)前端请求传值
1)获取token
2)根据token获取身份
3)根据身份获取权限
4)构建树形结构
**
@GetMapping("info")
public Result info(HttpServletRequest request) {
// 1.获取请求头token字符串
String token = request.getHeader("token");
// 2.从token字符串获取用户名称(id)
String username = JwtHelper.getUsername(token);
// 3.根据用户名称获取用户信息(基本信息 和 菜单权限 和 按钮权限数据)
Map<String,Object> map = sysUserService.getUserInfo(username);
return Result.ok(map);
}
User:
// 根据用户名称获取用户信息(基本信息 和 菜单权限 和 按钮权限数据)
@Override
public Map<String, Object> getUserInfo(String username) {
// 根据username查询用户基本信息
SysUser sysUser = this.getUserInfoByUserName(username);
// 根据userid查询菜单权限值
List<RouterVo> routerVolist = sysMenuService.getUserMenuList(sysUser.getId());
// 根据userid查询按钮权限值
List<String> permsList = sysMenuService.getUserButtonList(sysUser.getId());
Map<String,Object> 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:
// 根据userid查询菜单权限值
@Override
public List<RouterVo> getUserMenuList(String userId) {
// admin 1 超级管理员 查询所有权限数据
// !admin !1 !超级管理员 查询相关用户权限
List<SysMenu> sysMenuList = null;
// 1.判断用户身份
if("1".equals(userId)) {
QueryWrapper<SysMenu> wrapper = new QueryWrapper<>();
wrapper.eq("status",1);
wrapper.orderByAsc("sort_value");
sysMenuList = baseMapper.selectList(wrapper);
} else {
// 如果userid不是1,其他类型用户,查询这个用户权限
sysMenuList = baseMapper.findMenuListUserId(userId);
}
// 2.构建树形结构
List<SysMenu> sysMenuTreeList = MenuHelper.bulidTree(sysMenuList);
// 3.构建路由结构
List<RouterVo> routerVoList = RouterHelper.buildRouters(sysMenuTreeList);
return routerVoList;
}
//根据userid查询按钮权限值
@Override
public List<String> getUserButtonList(String userId) {
List<SysMenu> sysMenuList = null;
//判断是否管理员
if("1".equals(userId)) {
sysMenuList =
baseMapper.selectList(new QueryWrapper<SysMenu>().eq("status",1));
} else {
sysMenuList = baseMapper.findMenuListUserId(userId);
}
//sysMenuList遍历
List<String> permissionList = new ArrayList<>();
for (SysMenu sysMenu:sysMenuList) {
// type=2
if(sysMenu.getType()==2) {
String perms = sysMenu.getPerms();
permissionList.add(perms);
}
}
return permissionList;
}
<!-- 搜索框 -->
<el-row style="display: flex">
<el-button
type="primary"
icon="el-icon-search"
size="mini"
@click="fetchData()"
>搜索</el-button
>
<el-button icon="el-icon-refresh" size="mini" @click="resetData"
>重置</el-button
>
</el-row>
<!-- 分页 -->
<el-pagination
:current-page="page"
:total="total"
:page-size="limit"
:page-sizes="[1, 3, 5, 7]"
:page-size.sync="limit"
style="padding: 30px 0; text-align: center"
layout="total, sizes, prev, pager, next, jumper"
@size-change="handleSizeChange"
@current-change="handlePageChange"
/>
<!-- 事件 -->
// 分页
// 控制:每页展示数据
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();
},
Controller:
// page: 当前页码
// limit: 每页记录数
@ApiOperation("用户列表")
@GetMapping("/{page}/{limit}")
public Result list(@PathVariable Long page,
@PathVariable Long limit,
SysUserQueryVo sysUserQueryVo) {
// 创建page对象
Page<SysUser> pageParam = new Page<>(page,limit);
// 调用service方法
IPage<SysUser> pageModel = sysUserService.selectPage(pageParam,sysUserQueryVo);
return Result.ok(pageModel);
}
Impl:
@Override
public IPage<SysUser> selectPage(Page<SysUser> pageParam, SysUserQueryVo sysUserQueryVo) {
return baseMapper.selectPage(pageParam,sysUserQueryVo);
}
【注】使用MP的Page和Ipage对象接收并处理分页
<!-- 可选框:在列表左端增加了一列可选框-->
<el-table-column type="selection"/>
<!-- 按钮 -->
<div class="tools-div">
<el-button type="success" icon="el-icon-plus" size="mini" @click="add">添 加</el-button>
<el-button class="btn-add" size="mini" @click="batchRemove()" >批量删除</el-button>
</div>
// 事件
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<this.selectValue.length;i++) {
// 获取选框数据
var obj = this.selectValue[i]
// 获取其值的id
var id = obj.id
// 将其id存储到数组中
idList.push(id)
}
// 4.传值
api.batchRemove(idList).then(response => {
// 5.提示
this.$message({
type: 'success',
message: '删除成功!'
});
// 6.刷新
this.fetchData()
})
})
},
// 多个id值 [1,2,3]
// json数组格式 --- java的list集合
@PreAuthorize("hasAuthority('bnt.sysRole.remove')")
@ApiOperation("批量删除")
@DeleteMapping("batchRemove")
public Result batchRemove(@RequestBody List<Long> ids) {
sysRoleService.removeByIds(ids);
return Result.ok();
}
【注】逻辑删除的实现:
<!-- 表格 -->
<el-table-column label="状态" width="80" align="center">
<template slot-scope="scope">
<el-switch
v-model="scope.row.status === 1"
@change="switchStatus(scope.row)"
>
</el-switch>
</template>
</el-table-column>
// 事件
// 【更改用户状态】
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操作后均需要进行再次(分页)查询
Controller:
@ApiOperation("更改用户状态")
@GetMapping("updateStatus/{id}/{status}")
public Result updateStatus(@PathVariable String id,
@PathVariable Integer status) {
sysUserService.updateStatus(id,status);
return Result.ok();
}
Impl:
// 更改用户状态
@Override
public void updateStatus(String id, Integer status) {
// 根据用户id查询
SysUser sysUser = baseMapper.selectById(id);
// 更新用户状态
sysUser.setStatus(status);
// 调用方法修改
baseMapper.updateById(sysUser);
}
<!--
scope.$index 从0开始迭代获取索引
scope.row 获取当前行
scope.row.id 获取当前行id
不使用插槽 $table.$refs.table[$index].row(获取当前行) 更加复杂
-->
<template slot-scope="scope">
<el-button type="primary" icon="el-icon-edit" size="mini"
@click="edit(scope.row.id)" title="修改"/>
<el-button type="danger" icon="el-icon-delete" size="mini"
@click="removeDataById(scope.row.id)" title="删除"/>
<el-button type="warning" icon="el-icon-baseball" size="mini"
@click="showAssignAuth(scope.row)" title="分配权限"/>
</template>
Controller:
@ApiOperation("用户分配角色")
@PostMapping("doAssign")
public Result doAssign(@RequestBody AssginRoleVo assginRoleVo) {
sysRoleService.doAssign(assginRoleVo);
return Result.ok();
}
Impl:
// 用户分配角色
@Override
public void doAssign(AssginRoleVo assginRoleVo) {
// 1.-:根据用户id删除之前分配的角色
QueryWrapper<SysUserRole> wrapper = new QueryWrapper<>();
wrapper.eq("user_id",assginRoleVo.getUserId());
sysUserRoleMapper.delete(wrapper);
// 2.+:获取所有的角色id,添加到角色用户关系表中表
//角色id列表
List<String> roleIdList = assginRoleVo.getRoleIdList();
for (String roleId:roleIdList) {
SysUserRole userRole = new SysUserRole();
userRole.setUserId(assginRoleVo.getUserId());
userRole.setRoleId(roleId);
sysUserRoleMapper.insert(userRole);
}
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。