后台用户管理模块主要分为数据展示和分页、查询、操作这三大部分,各部分具体需求如下。
数据展示和分页:展示所有用户的数据,默认十条数据作为一页。分页栏展示一共有几条数据,可以选择每页的条数为10、20、30或40;可以点击页数进行页面数据切换
查询:根据用户姓名进行模糊查询,查询结果也进行分页,默认十条数据作为一页。
操作:操作部分包括删除用户和批量删除用户、修改用户信息(用户名【用户名修改时需要判重】、头像)
分页
后端使用pagehelper进行分页
- 在pom.xml中添加分页插件依赖
<!--分页插件-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.3</version>
</dependency>
2.在application.properties中配置参数
#pagehelper
pagehelper.helper-dialect=mysql //指定了 PageHelper 使用的数据库方言为 MySQL。这样,PageHelper 将根据 MySQL 数据库的规则进行分页查询。
pagehelper.reasonable=true //配置分页参数合理化功能,启用合理化,如果 pageNum<1 会查询第一页,如果 pageNum>总页数 会查询最后一页
pagehelper.support-methods-arguments=true //支持通过Mapper接口参数来传递分页参数,设置为 true,则可以在方法中直接传入分页参数(如 pageNum 和 pageSize)
pagehelper.params=count=countSql //这个属性用于指定查询总记录数的 SQL 语句
#运行循环调用,不添加运行会报错
spring.main.allow-circular-references=true
- 在UserService中添加PageHelper.startPage(pageNum, pageSize);
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public List<User> getAllUser(int pageNum, int pageSize) {
//会对查询结果进行分页处理
PageHelper.startPage(pageNum, pageSize);
return userMapper.getAllUser();
}
}
- 定义PageBaseInfo类,存储分页查询结果,和查询相关信息
public class PageBaseInfo<T> {
private List<T> listData; //分页查询到的数据
private long total ; //总数据
public List<T> getListData() {
return listData;
}
public void setListData(List<T> listDate) {
this.listData = listDate;
}
public long getTotal() {
return total;
}
public void setTotal(long total) {
this.total = total;
}
}
- . 在controller中使用,PageInfo类是分页插件提供的类,保存当前页数、总页数、总条数等信息,可通过相应的get方法获取
@LoginToken
@RequestMapping(value = "/all/{pageNum}/{pageSize}" ,method = RequestMethod.GET)
public PageBaseInfo userAll(@PathVariable("pageNum") int pageNum, @PathVariable("pageSize") int pageSize){
List<User> userList = userService.getAllUser(pageNum,pageSize);
PageInfo<User> pageInfo = new PageInfo<>(userList);
PageBaseInfo pageBaseInfo = new PageBaseInfo();
pageBaseInfo.setListData(userList);
pageBaseInfo.setTotal(pageInfo.getTotal());
System.out.println(pageBaseInfo);
return pageBaseInfo;
}
PageInfo类的属性如下
"pageNum":1, //当前页码
"pageSize":50, //每页个数
"size":1, //当前页个数
"startRow":1, //由第几条开始
"endRow":1, //到第几条结束
"total":1, //总条数
"pages":1, //总页数
"list":[{"dateTime":"2020-03-21","operationType":1}],//查出出来的数据集合
"prePage":0, //上一页
"nextPage":0, //下一页
"isFirstPage":true, //是否为首页
"isLastPage":true, //是否为尾页
"hasPreviousPage":false, //是否有上一页
"hasNextPage":false, //是否有下一页
"navigatePages":8, //每页显示的页码个数
"navigatepageNums":[1], //首页
"navigateFirstPage":1, //尾页
"navigateLastPage":1, //页码数
"firstPage":1,
"lastPage":1
至此后端的分页就完成了,前端收到的数据如下
前端使用el-pagination分页
- 在el-table下方添加分页
<el-pagination
style="float: right;"
v-model:current-page="pageNum"
v-model:page-size="pageSize"
:page-sizes="[10, 20, 30, 40]"
layout="total,sizes, prev, pager, next"
:total="total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
- 添加el-pagination所需的数据和方法
//分页
let pageNum = ref(1);
let pageSize = ref(10);
let total = ref(0);
const handleSizeChange = (val: number) => {
console.log(`${val} items per page`)
pageSize.value = val;
userList.length = 0;
getAllUser();
}
const handleCurrentChange = (val: number) => {
console.log(`current page: ${val}`)
pageNum.value = val;
//因为是通过push给数组赋值的,所以换页时要把数组清空
userList.length = 0;
getAllUser();
}
同时在向后端发送请求时需要添加pageNum、pageSize这两个参数,修改alluser方法
const getAllUser = ()=>{
loginRegister.alluser(pageNum.value,pageSize.value).then((res:any)=>{
//要用push的方法给数组赋值,不然会出现数组渲染不了的情况
userList.push(...res.data.listData);
total.value = res.data.total;
})
}
修改src\api\loginRegister.ts文件中的alluser方法
alluser:(pageNum:number,pageSize:number)=>{
return request.get('user/all/'+pageNum+'/'+pageSize);
},
至此列表分页的前后端都写好了,效果如下
查询
根据输入的用户名进行模糊查询,也对查询结果进行分页处理
后端
因为根据用户名模糊查询和获取全部用户的返回数据格式是一样的,只是多了一个查询条件,所以我把这个两个查询放在user/all接口,改为post,增加一个用户对象参数,如果用户对象的姓名为空,则查询所有用户;如果不为空,则根据用户名进行模糊查询。
//获得所有用户和根据用户名搜索用户
@LoginToken
@RequestMapping(value = "/all/{pageNum}/{pageSize}" ,method = RequestMethod.POST)
public PageBaseInfo userAll(@RequestBody User user,@PathVariable("pageNum") int pageNum, @PathVariable("pageSize") int pageSize){
List<User> userList = new ArrayList<>();
if (user.getUserName() == null){
userList = userService.getAllUser(pageNum,pageSize);
}else {
userList = userService.vagueSearchUserName(user.getUserName(),pageNum,pageSize);
}
PageInfo<User> pageInfo = new PageInfo<>(userList);
PageBaseInfo pageBaseInfo = new PageBaseInfo();
pageBaseInfo.setListData(userList);
pageBaseInfo.setTotal(pageInfo.getTotal());
return pageBaseInfo;
}
模糊查询语句如下
<!-- 用户名模糊查询用户-->
<select id="vagueSearchUserName" parameterType="java.lang.String" resultMap="BaseResultMap">
select
<include refid="Base_Column_List" />
from user
where user_name like concat('%', #{userName,jdbcType=INTEGER}, '%')
</select>
前端
前端方法也做相应更改
<el-form :model="form">
<el-row>
<el-col :span="6">
<el-form-item label="输入查找用户名">
<el-input style="width: 300px;" v-model.trim="form.userName" />
</el-form-item>
</el-col>
<el-col :span="2" :offset="1">
<el-form-item>
<el-button type="primary" @click="onSearch">Create</el-button>
</el-form-item>
</el-col>
</el-row>
</el-form>
const form = reactive(new UserClass());
//查询所有用户和根据用户名查找用户
const getAllUser = ()=>{
loginRegister.alluser(pageNum.value,pageSize.value,form).then((res:any)=>{
//因为是通过push给数组赋值的,所以换页时要把数组清空
userList.length = 0;
//要用push的方法给数组赋值,不然会出现数组渲染不了的情况
userList.push(...res.data.listData);
total.value = res.data.total;
})
}
//点击查询按钮后
const onSearch = (()=>{
pageNum.value = 1;
pageSize.value = 2;
getAllUser();
})
const form = reactive(new UserClass()); 中的 UserClass(),是创建src\type\userData.ts中的一个类,userData.ts文件如下
export interface UserFrom {
userName: string;
passward: string;
}
export class UserClass {
headImg:'';
passward?: '';
roleId: 0;
userId: 0;
userName: '';
}
至此,根据用户名模糊查询用户完成了
操作
删除用户
后端接口如下,接收一个用户id数组,根据数组中的用户id删除相应用户
controller
//删除用户(包括单个删除和批量删除)
@LoginToken
@RequestMapping(value = "/delete" ,method = RequestMethod.POST)
public String userDelete( @RequestBody List<Integer> idList){
System.out.println(idList);
userService.deleteBatch(idList);
return "用户删除成功";
}
userMapper
int deleteBatch(List<Integer> idList);
userService
public int deleteBatch(List<Integer> idList) {
return userMapper.deleteBatch(idList);
}
userMapper.xml
<!-- 批量删除用户-->
<delete id="deleteBatch" parameterType="Integer">
delete from user where user_id in
<foreach item="idList" collection="list" index="index" open="(" separator="," close=")">
#{idList}
</foreach>
</delete>
前端代码如下
- 在src\api\loginRegister.ts添加方法
deleteUser:(userId:string)=>{
console.log(userId);
return request.get('user/delete/'+userId);
},
- 增加el-table-column操作栏,可对相应的用户进行删除和用户编辑的操作,这里的删除是单个删除
<el-table-column label="操作">
<template #default="scope">
<el-button size="small" @click="handleEdit(scope.row.userId)"
>编辑</el-button
>
<el-button
size="small"
type="danger"
@click="deleteUser(scope.row.userId)"
>删除</el-button
>
</template>
</el-table-column>
- 给table添加选择框栏和@selection-change事件,当点击选择框时触发该事件
<el-table
:data="userList"
style="width: 100%"
height="500px"
border
@selection-change="handleSelectionChange" //@selection-change事件
>
//添加的选择框栏
<el-table-column type="selection" width="40"></el-table-column>
<el-table-column type="index" width="50" />
<el-table-column prop="headImg" label="头像">
<template #default="scope">
<el-avatar :size="50" :src="scope.headImg">
<img
src="https://cube.elemecdn.com/9/c2/f0ee8a3c7c9638a54940382568c9dpng.png"/>
</el-avatar>
</template>
</el-table-column>
<el-table-column prop="userName" label="用户名" />
<el-table-column prop="roleId" label="角色">
<template #default="scope">
{{ userRole(scope.row.roleId) }}
</template>
</el-table-column>
<el-table-column label="操作">
<template #default="scope">
<el-button size="small" @click="handleEdit(scope.row.userId)"
>编辑</el-button
>
<el-button
size="small"
type="danger"
@click="deleteUser(scope.row.userId)"
>删除</el-button
>
</template>
</el-table-column>
</el-table>
- 删除用户相关代码
/*删除用户*/
//选择框勾选的行内容存在selectUsers中
const selectUsers= ref([]);
const handleSelectionChange = (sel:[] )=>{
selectUsers.value = sel;
}
//当点击批量删除时,将勾选用户的id从selectUsers中取出,发送给后端
const deleteUser = (userId?:number)=>{
ElMessageBox.confirm(
'是否要删除该用户?',
{
confirmButtonText: '删除',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(() => {
let IdList:number[] = [];
//单个删除
if(typeof userId == 'number'){
IdList.push(userId)
}else{
//批量删除
for(let i=0;i<selectUsers.value.length;i++){
IdList.push(selectUsers.value[i]['userId']);
}
}
loginRegister.deleteUser(IdList).then((res)=>{
console.log(res)
getAllUser();
ElMessage.success(res.data as string);
});
})
.catch(() => {
ElMessage({
type: 'info',
message:'已取消',
})
})
6.在src\api\loginRegister.ts中添加删除用户的方法
deleteUser:(idList:number[])=>{
return request.post('user/delete/',idList);
},
删除单个用户和批量删除用户功能完成
编辑用户信息
可以修改用户的头像和用户名,因为图片上传还没写好,所有现在只能修改用户名,修改后的用户名不能与数据库中的其他用户名相同。
点击修改,获取用户信息后自动填充表单,修改信息后提交表单,修改用户信息。
后端接口
//根据id查找用户
@LoginToken
@RequestMapping(value = "/getUser/{userId}" ,method = RequestMethod.GET)
public User selectByPrimaryKey(@PathVariable("userId") int userId){
return userService.selectByPrimaryKey(userId);
}
//修改用户信息
@LoginToken
@RequestMapping(value = "/update" ,method = RequestMethod.POST)
public String updateUserInfo(@RequestBody User user){
System.out.println(user);
//根据即将修改的用户名查找,如果该用户名已经存在,则修改失败并抛出错误
User userDB = userService.selectUserByName(user.getUserName());
if (userDB == null){
userService.updateByPrimaryKeySelective(user);
return "修改成功";
}else {
throw new BaseException(ResponseCode.NAMA_REPEAT);
}
}
前端代码
- 在src\api\loginRegister.ts添加方法
getUserById:(userId:string)=>{
return request.get('user/getUser/'+userId);
},
updateUserInfo:(user:UserClass)=>{
return request.post('user/update',user);
}
- 添加展示和修改用户信息的对话框
<el-dialog v-model="editDialog" title="修改用户信息" width="30%" draggable>
<el-form :model="userInfo" label-width="60px">
<el-form-item label="头像">
<el-avatar :size="50" :src="userInfo.headImg">
<img
src="https://cube.elemecdn.com/9/c2/f0ee8a3c7c9638a54940382568c9dpng.png"/>
</el-avatar>
</el-form-item>
<el-form-item label="用户名">
<el-input style="width: 300px;" v-model.trim="userInfo.userName" />
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="editDialog = false">取消</el-button>
<el-button type="primary" @click="updateInfo">
修改
</el-button>
</span>
</template>
</el-dialog>
- 添加相关方法
//编辑用户信息
const editDialog = ref(false);
let userInfo = reactive(new UserClass());
const handleEdit = (userId:number)=>{
console.log(userId)
loginRegister.getUserById(userId.toString()).then((res:any)=>{
console.log(res.data);
Object.assign(userInfo,res.data);
editDialog.value = true;
})
}
const updateInfo = ()=>{
editDialog.value = false;
console.log(userInfo);
loginRegister.updateUserInfo(userInfo).then((res)=>{
console.log(res);
ElMessage.success(res.data as string);
getAllUser();
})
}
至此,修改用户名完成。
后台用户管理模块的大致功能已经完成了,接下来就是博客、用户、留言的管理啦。