给项目中的用户头像,添加用户的历史头像记录功能
目录
一.前提要求
二.期望的效果
1.用户更换头像以后,所有使用过的头像,都会保存为该用户的历史头像。
2.点击某个历史头像以后,可以切换回为该历史头像。
三、实现步骤
(1)编写前端布局
1.使用Tabs 标签页组件(el-tabs),实现当前头像、历史头像的切换功能
2.在【历史头像】标签页中,使用el-row和el-col进行布局,提前为历史头像占个地方。
(2)设计数据库表,用来记录用户的历史头像
(3)编写后端端口,根据用户id查询该用户的全部历史头像记录
1.编写controller层
2.编写service层
3.编写mapper层
(4)在前端打开头像预览对话框的打开函数中,查询当前登录用户的历史头像记录即可。
(5)使用v-for语句,根据userAvatarHistory动态渲染上面的el-col
(6)在上传头像的业务中,加上一条添加该为历史头像的业务
四.效果展示
五.添加功能:当点击某个历史头像后,就能切换为该历史头像
1.给历史头像外边,包一层Popconfirm 气泡确认框组件(el-popconfirm)
2.编写气泡确认框的确认事件,在该事件中,将所点击的历史头像的url地址赋值给当前登录用户的当前头像字段。
六.最终效果展示
结语
一.前提要求
读本篇文章之前,先要看一下前提文章(这篇文章讲解了如何上传用户头像):
element-plus中,Upload上传组件的使用 + 后端处理-CSDN博客
二.期望的效果
1.用户更换头像以后,所有使用过的头像,都会保存为该用户的历史头像。
2.点击某个历史头像以后,可以切换回为该历史头像。
三、实现步骤
(1)编写前端布局
1.使用Tabs 标签页组件(el-tabs),实现当前头像、历史头像的切换功能
html代码:
<!-- 预览登录用户头像的弹窗 -->
<el-dialog
v-model="showAvatar"
title="头像预览"
style="width:500px;height:580px;"
append-to-body
@open="openShowAvatarDialog"
@closed="closedShowAvatarDialog"
>
<!-- 这个弹窗,应该包含两个部分:①当前头像 + ②历史头像记录 -->
<!-- 第一部分:当前头像 -->
<el-tabs v-model="activeName" class="demo-tabs">
<el-tab-pane label="当前头像" name="first">
<!-- 第一个页面:当前头像 -->
<!-- 文件上传组件 -->
<el-upload
:action="`http://localhost:8848/api/user/${user.id}/updateUserAvatar`"
name="userAvatar"
:show-file-list="false"
:before-upload="beforeUpload"
:on-success="handleAvatarSuccess"
>
<!-- 当前的用户头像 -->
<!-- 如果此时该用户有头像,则显示头像 -->
<img v-if="user.avatar != null" :src=user.avatar alt="头像" title="点击更换头像" style="width: 465px;height: 450px;border-radius:10px;"/>
<!-- 如果此时该用户没有头像,则显示自定义span -->
<span v-else style="display: inline-block;width:465px;height:450px;background-color: #EEEEEE;border-radius:10px;" title="暂无头像,点击上传头像">
<el-icon style="margin-top: 200px;margin-left:220px"><icon-picture /></el-icon>
</span>
</el-upload>
</el-tab-pane>
<!-- 第二部分:历史头像 -->
<el-tab-pane label="历史头像" name="second" style="height:450px;overflow-y: auto;overflow-x: hidden;">
<span>历史头像</span>
</el-tab-pane>
</el-tabs>
</el-dialog>
js代码:
//一开始,令头像弹出框的第一个页面(即:【当前头像】页面)是激活状态
const activeName = ref("first")
展示效果:
注意一个细节:当对话框关闭时的激活的页面是【历史头像】标签页,那么等下次打开时,激活页面还是【历史头像】标签页。
这显然是不合适的。效果应该是:不管关闭对话框时哪个标签页处于激活状态,等下次打开对话框时,激活的标签页都应该是第一个,即:【当前头像】。
这就需要在头像预览对话框的关闭事件中,编写如下代码:
2.在【历史头像】标签页中,使用el-row和el-col进行布局,提前为历史头像占个地方。
<!-- 第二部分:历史头像 -->
<el-tab-pane label="历史头像" name="second" >
<!-- 第二个页面:历史头像(只展示最近的9张) -->
<!-- 第一行头像 -->
<el-row :gutter="5" >
<el-col :span="8">
<div style="width:100%;height:148px;background-color: pink;">
<img src="https://casually-his.oss-cn-beijing.aliyuncs.com/944b707a-f653-4c86-bd85-25f221fd704b.png" title="更换该头像" style="cursor: pointer;border: 2px solid #F5F7FA;" width="100%" height="100%">
</div>
</el-col>
<el-col :span="8">
<div style="width:100%;height:148px;background-color: pink;">
<img src="https://casually-his.oss-cn-beijing.aliyuncs.com/944b707a-f653-4c86-bd85-25f221fd704b.png" title="更换该头像" style="cursor: pointer;border: 2px solid #F5F7FA;" width="100%" height="100%">
</div>
</el-col>
<el-col :span="8">
<div style="width:100%;height:148px;background-color: pink;">
<img src="https://casually-his.oss-cn-beijing.aliyuncs.com/944b707a-f653-4c86-bd85-25f221fd704b.png" title="更换该头像" style="cursor: pointer;border: 2px solid #F5F7FA;" width="100%" height="100%">
</div>
</el-col>
<el-col :span="8">
<div style="width:100%;height:148px;background-color: pink;">
<img src="https://casually-his.oss-cn-beijing.aliyuncs.com/944b707a-f653-4c86-bd85-25f221fd704b.png" title="更换该头像" style="cursor: pointer;border: 2px solid #F5F7FA;" width="100%" height="100%">
</div>
</el-col>
<el-col :span="8">
<div style="width:100%;height:148px;background-color: pink;">
<img src="https://casually-his.oss-cn-beijing.aliyuncs.com/944b707a-f653-4c86-bd85-25f221fd704b.png" title="更换该头像" style="cursor: pointer;border: 2px solid #F5F7FA;" width="100%" height="100%">
</div>
</el-col>
<el-col :span="8">
<div style="width:100%;height:148px;background-color: pink;">
<img src="https://casually-his.oss-cn-beijing.aliyuncs.com/944b707a-f653-4c86-bd85-25f221fd704b.png" title="更换该头像" style="cursor: pointer;border: 2px solid #F5F7FA;" width="100%" height="100%">
</div>
</el-col>
<el-col :span="8">
<div style="width:100%;height:148px;background-color: pink;">
<img src="https://casually-his.oss-cn-beijing.aliyuncs.com/944b707a-f653-4c86-bd85-25f221fd704b.png" title="更换该头像" style="cursor: pointer;border: 2px solid #F5F7FA;" width="100%" height="100%">
</div>
</el-col>
<el-col :span="8">
<div style="width:100%;height:148px;background-color: pink;">
<img src="https://casually-his.oss-cn-beijing.aliyuncs.com/944b707a-f653-4c86-bd85-25f221fd704b.png" title="更换该头像" style="cursor: pointer;border: 2px solid #F5F7FA;" width="100%" height="100%">
</div>
</el-col>
<el-col :span="8">
<div style="width:100%;height:148px;background-color: pink;">
<img src="https://casually-his.oss-cn-beijing.aliyuncs.com/944b707a-f653-4c86-bd85-25f221fd704b.png" title="更换该头像" style="cursor: pointer;border: 2px solid #F5F7FA;" width="100%" height="100%">
</div>
</el-col>
<el-col :span="8">
<div style="width:100%;height:148px;background-color: pink;">
<img src="https://casually-his.oss-cn-beijing.aliyuncs.com/944b707a-f653-4c86-bd85-25f221fd704b.png" title="更换该头像" style="cursor: pointer;border: 2px solid #F5F7FA;" width="100%" height="100%">
</div>
</el-col>
<el-col :span="8">
<div style="width:100%;height:148px;background-color: pink;">
<img src="https://casually-his.oss-cn-beijing.aliyuncs.com/944b707a-f653-4c86-bd85-25f221fd704b.png" title="更换该头像" style="cursor: pointer;border: 2px solid #F5F7FA;" width="100%" height="100%">
</div>
</el-col>
</el-row>
</el-tab-pane>
效果展示:
存在的问题1:标签页内容超出了。
应当改为:当标签页内容超出时,就显示纵向拉条。解决代码如下:
展示修改后的效果:
注意:
①我们设置了每个el-col的:span值为8,代表每行有24/8=3个头像。(这个24是官方定义的一行的总体宽度)。
②我们只写了一个el-row,也就是说只有一行,但是却写了11个el-col,此时很显然超出了3个(即:一行的最多头像数量)。此时重点来了,当el-col在第一行排不下时,就会自动换行到第二行,以此类推(这是实现历史头像排布的最关键的一点)。
(2)设计数据库表,用来记录用户的历史头像
(3)编写后端端口,根据用户id查询该用户的全部历史头像记录
1.编写controller层
@RestController//表明这是一个controller层,并且自动将对象转为JSON格式返回
@RequestMapping("/api/userAvatarHistory")//该controller的访问路径
public class UserAvatarHistoryController {
@Autowired
private UserAvatarHistoryService userAvatarHistoryService;
//根据用户id,查询该用户的全部历史头像记录
@GetMapping("/queryAllAvatarByUserId")
public Result<List<UserAvatarHistory>> queryAllAvatarByUserId(@RequestParam("userId") Integer userId){
List<UserAvatarHistory> userAvatarHistories = userAvatarHistoryService.queryAllAvatarByUserId(userId);
return new Result<List<UserAvatarHistory>>(200, "ok", userAvatarHistories);
}
}
2.编写service层
service层:
public interface UserAvatarHistoryService {
//根据用户id,查询该用户的所有历史头像记录
public List<UserAvatarHistory> queryAllAvatarByUserId(Integer userId);
}
serviceImpl层:
@Service
public class UserAvatarHistoryServiceImpl implements UserAvatarHistoryService {
@Autowired
private UserAvatarHistoryMapper userAvatarHistoryMapper;
//根据用户id,查询该用户的所有历史头像记录
public List<UserAvatarHistory> queryAllAvatarByUserId(Integer userId) {
return userAvatarHistoryMapper.queryAllAvatarByUserId(userId);
}
}
3.编写mapper层
@Mapper
public interface UserAvatarHistoryMapper {
//根据用户id,查询该用户的全部历史头像(顺序为:最近的头像排在前面,即:按照id降序,id大的在前面)
@Select("select * " +
"from user_avatar_history " +
"where user_id = #{userId} " +
"order by id desc ")
public List<UserAvatarHistory> queryAllAvatarByUserId(Integer userId);
}
(4)在前端打开头像预览对话框的打开函数中,查询当前登录用户的历史头像记录即可。
//当前登录用户的全部历史头像
const userAvatarHistory = ref();
//打开头像预览对话框前,触发的事件
const openShowAvatarDialog = async () => {
//alert("打开头像预览对话框")
//发送请求,查询当前登录用户的全部历史头像
const res = await queryAllAvatarByUserId(user.id);
if(res.code == 200){
//alert(JSON.stringify(res.data))
//给用户的历史头像赋值
userAvatarHistory.value = res.data;
}
}
(5)使用v-for语句,根据userAvatarHistory动态渲染上面的el-col
<!-- 第二部分:历史头像 -->
<el-tab-pane label="历史头像" name="second" style="height:450px;overflow-y: auto;overflow-x: hidden;">
<!-- 第二个页面:历史头像(只展示最近的9张) -->
<!-- 第一行头像 -->
<el-row :gutter="5" >
<el-col v-for="userAvatar in userAvatarHistory" :key="userAvatar.id" :span="8">
<div style="width:100%;height:150px;background-color: pink;">
<img :src=userAvatar.avatar title="更换该头像" style="cursor: pointer;border: 2px solid #F5F7FA;border-radius:15px;" width="100%" height="100%" >
</div>
</el-row>
</el-tab-pane>
(6)在上传头像的业务中,加上一条添加该为历史头像的业务
serviceImpl层:
mapper层:
四.效果展示
五.添加功能:当点击某个历史头像后,就能切换为该历史头像
步骤如下:
1.给历史头像外边,包一层Popconfirm 气泡确认框组件(el-popconfirm)
<!-- 第二部分:历史头像 -->
<el-tab-pane label="历史头像" name="second" style="height:450px;overflow-y: auto;overflow-x: hidden;">
<!-- 第二个页面:历史头像(只展示最近的9张) -->
<!-- 第一行头像 -->
<el-row :gutter="5" >
<el-col v-for="userAvatar in userAvatarHistory" :key="userAvatar.id" :span="8">
<div style="width:100%;height:150px;">
<el-popconfirm title="确定要更换该头像么?" confirm-button-text="确定" cancel-button-text="取消" @confirm="changeAvatar(userAvatar)">
<template #reference>
<img :src=userAvatar.avatar title="更换该头像" style="cursor: pointer;border: 2px solid #F5F7FA;border-radius:15px;" width="100%" height="100%" >
</template>
</el-popconfirm>
</div>
</el-row>
</el-tab-pane>
2.编写气泡确认框的确认事件,在该事件中,将所点击的历史头像的url地址赋值给当前登录用户的当前头像字段。
//点击某个历史头像的确认按钮时,触发事件@click="changeAvatar(userAvatar)"
const changeAvatar = async (userAvatar) => {
//alert(JSON.stringify(userAvatar));//此时id是点击的那个历史头像(对象形式)
//将当前登录用户的当前头像,改为现在点击的这个历史头像的url地址
//构造请求参数
const data = {
avatar: userAvatar.avatar
}
const res = await updateUserAvatar(user.id, data);
if(res.code == 200){
ElMessage.success("更换头像成功~");
//将当前登录用户在pinia中的头像url地址改为所点击的历史头像的地址
user.avatar = userAvatar.avatar;
//关闭头像预览对话框
showAvatar.value = false;
}else{
ElMessage.error("更换头像失败~");
}
}
六.最终效果展示
结语
以上就是给项目中的用户头像,添加用户的历史头像记录功能的大致流程。
要想读懂本篇文章,就需要大家充分地了解Element-Plus组件库中,各组件的使用方法和特点。
读不懂没关系,了解大致流程就行,而且实现方式绝对不只这一种。
喜欢本篇文章的话,可以留个免费的关注~