顶部导航栏个人信息显示
接口文档
接口请求与绑定
导航栏下拉菜单功能
路由实现
退出登录和路由跳转实现
基本资料修改
页面结构
接口文档
接口请求与绑定
修改头像
页面结构
头像回显
头像上传
接口文档
重置密码
页面结构
接口文档
接口请求与绑定
顶部导航栏个人信息显示
在Layout.vue中,页面加载完就发送请求,获取个人信息展示,并存储到pinia中,因为将来在个人中心中修改信息的时候还需要使用 。
接口文档
接口请求与绑定
在stores目录下新建userInfo.js并定义Store用于将数据存储到pinia中
import { defineStore } from "pinia"
import {ref} from 'vue'
export const useUserInfoStore = defineStore('userInfo',()=>{
//1.定义用户信息
const info = ref({})
//2.定义修改用户信息的方法
const setInfo = (newInfo)=>{
info.value = newInfo
}
//3.定义清空用户信息的方法
const removeInfo = ()=>{
info.value={}
}
return{info,setInfo,removeInfo}
},{
persist:true
})
在user.js中提供获取个人信息的函数
//获取个人信息
export const userInfoGetService = ()=>{
return request.get('/user/userInfo');
}
在Layout.vue中获取个人信息,并存储到pinia中
//导入接口函数
import {userInfoGetService} from '@/api/user.js'
//导入pinia
import {useUserInfoStore} from '@/stores/userInfo.js'
const userInfoStore = useUserInfoStore();
import {ref} from 'vue'
//获取个人信息
const getUserInf = async ()=>{
let result = await userInfoGetService();
if(result.code === 0){
//成功
//存储pinia
userInfoStore.info =result.data;
}else{
//失败
alert('获取信息失败')
}
}
getUserInf()
Layout.vue的顶部导航栏中,绑定展示昵称和头像
<div>用户:<strong>{{ userInfoStore.info.nickname ? userInfoStore.info.nickname : userInfoStore.info.usrename }}</strong></div>
<el-avatar :src="userInfoStore.info.userPic ? userInfoStore.info.userPic : avatar" />
保存后刷新页面可以看到用户名称和头像正常显示
导航栏下拉菜单功能
在el-dropdown中有四个子条目
- 基本资料
- 更换头像
- 重置密码
- 退出登录
其中其三个起到路由功能,跟左侧菜单中【个人中心】下面的二级菜单是同样的功能,退出登录需要删除本地pinia中存储的token以及userInfo
路由实现
在el-dropdown标签上绑定command事件,当有条目被点击后,会触发这个事件
<el-dropdown placement="bottom-end" @command="handleCommand">
在el-dropdown-item标签上添加command属性,属性值和路由表中/user/xxx保持一致
<el-dropdown-item command="info" :icon="User">基本资料</el-dropdown-item>
<el-dropdown-item command="avatar" :icon="Crop">更换头像</el-dropdown-item>
<el-dropdown-item command="password" :icon="EditPen">重置密码</el-dropdown-item>
<el-dropdown-item command="logout" :icon="SwitchButton">退出登录</el-dropdown-item>
退出登录和路由跳转实现
定义并编写handleCommand函数
import {useRouter} from 'vue-router'
const router = useRouter();
import {ElMessage,ElMessageBox} from 'element-plus'
import { useTokenStore } from '@/stores/token.js'
const tokenStore = useTokenStore()
const handleCommand = (command) => {
if (command === 'logout') {
//退出登录
ElMessageBox.confirm(
'是否退出登录',
'提示',
{
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(async () => {
//用户点击了确认
//清空pinia中的token和个人信息
userInfoStore.info={}
tokenStore.token=''
//跳转到登录页
router.push('/login')
ElMessage.success('成功退出登录')
})
.catch(() => {
//用户点击了取消
ElMessage({
type: 'info',
message: '取消退出',
})
})
} else {
//路由
router.push('/user/' + command)
}
}
保存后刷新既可以完成跳转和退出登录
基本资料修改
页面结构
在UserInfo.vue文件中完成用户资料修改的页面结构组件
<script setup>
import { ref } from 'vue'
const userInfo = ref({
id: 0,
username: 'zhangsan',
nickname: 'zs',
email: 'zs@163.com',
})
const rules = {
nickname: [
{ required: true, message: '请输入用户昵称', trigger: 'blur' },
{
pattern: /^\S{2,10}$/,
message: '昵称必须是2-10位的非空字符串',
trigger: 'blur'
}
],
email: [
{ required: true, message: '请输入用户邮箱', trigger: 'blur' },
{ type: 'email', message: '邮箱格式不正确', trigger: 'blur' }
]
}
</script>
<template>
<el-card class="page-container">
<template #header>
<div class="header">
<span>基本资料</span>
</div>
</template>
<el-row>
<el-col :span="12">
<el-form :model="userInfo" :rules="rules" label-width="100px" size="large">
<el-form-item label="登录名称">
<el-input v-model="userInfo.username" disabled></el-input>
</el-form-item>
<el-form-item label="用户昵称" prop="nickname">
<el-input v-model="userInfo.nickname"></el-input>
</el-form-item>
<el-form-item label="用户邮箱" prop="email">
<el-input v-model="userInfo.email"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary">提交修改</el-button>
</el-form-item>
</el-form>
</el-col>
</el-row>
</el-card>
</template>
个人信息之前已经存储到了pinia中,只需要从pinia中获取个人信息,替换模板数据即可
import { ref } from 'vue'
//导入Store
import { useUserInfoStore } from '@/stores/userInfo.js';
const userInfoStore = useUserInfoStore()
//数据模型
const userInfo = ref({...userInfoStore.info}) //...用于展开可迭代对象 拆出其中的每个元素
接口文档
接口请求与绑定
在src/api/user.js中提供修改基本资料的函数
//修改个人信息
export const userInfoUpdateService = (userInfo)=>{
return request.put('/user/update',userInfo)
}
在UserInfo.vue文件中提供updateUserInfo请求函数
//修改用户信息
import {userInfoUpdateService} from '@/api/user.js'
import { ElMessage } from 'element-plus';
const updateUserInfo = async ()=>{
let result = await userInfoUpdateService(userInfo.value)
ElMessage.success(result.message? result.message:'修改成功')
//更新pinia中的数据
userInfoStore.info.nickname=userInfo.value.nickname
userInfoStore.info.email = userInfo.value.email
}
给修改按钮绑定单击事件
<el-button type="primary" @click="updateUserInfo">提交修改</el-button>
保存刷新后能正常完成用户信息的数据回显和更新
修改头像
页面结构
在UserAvatar.vue文件中完成用户资料修改的页面结构组件
<script setup>
import { Plus, Upload } from '@element-plus/icons-vue'
import {ref} from 'vue'
import avatar from '@/assets/default.png'
const uploadRef = ref()
//用户头像地址
const imgUrl= avatar
</script>
<template>
<el-card class="page-container">
<template #header>
<div class="header">
<span>更换头像</span>
</div>
</template>
<el-row>
<el-col :span="12">
<el-upload
ref="uploadRef"
class="avatar-uploader"
:show-file-list="false"
>
<img v-if="imgUrl" :src="imgUrl" class="avatar" />
<img v-else src="avatar" width="278" />
</el-upload>
<br />
<el-button type="primary" :icon="Plus" size="large" @click="uploadRef.$el.querySelector('input').click()">
选择图片
</el-button>
<el-button type="success" :icon="Upload" size="large">
上传头像
</el-button>
</el-col>
</el-row>
</el-card>
</template>
<style lang="scss" scoped>
.avatar-uploader {
:deep() {
.avatar {
width: 278px;
height: 278px;
display: block;
}
.el-upload {
border: 1px dashed var(--el-border-color);
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
transition: var(--el-transition-duration-fast);
}
.el-upload:hover {
border-color: var(--el-color-primary);
}
.el-icon.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 278px;
height: 278px;
text-align: center;
}
}
}
</style>
头像回显
从pinia中读取用户的头像数据
//读取用户信息
//导入Store
import {useUserInfoStore} from '@/stores/userInfo.js'
const userInfoStore = useUserInfoStore()
//用户头像地址
const imgUrl=ref(userInfoStore.info.userPic)
img标签上绑定图片地址(三元运输符判断)
<img v-if="imgUrl" :src="imgUrl" class="avatar" />
<img v-else :src="avatar" width="278" />
保存刷新查看头像回显
头像上传
- action: 服务器接口路径
- headers: 设置请求头,需要携带token
- on-success: 上传成功的回调函数
- name: 上传图片的字段名称
为el-upload指定属性值
<el-upload
ref="uploadRef"
class="avatar-uploader"
:show-file-list="false"
:auto-upload="true"
action="/api/upload"
name="'file'"
:headers="{'Authorization':tokenStore.token}"
:on-success="uploadSuccess"
>
提供上传成功的回调函数
//导入tokenStore
import {useTokenStore} from '@/stores/token.js'
const tokenStore = useTokenStore();
//头像上传成功回调函数
const uploadSuccess = (result)=>{
//回显图片
imgUrl.value = result.data
}
接口文档
接口请求与绑定
在user.js中提供修改头像的函数
//修改头像
export const userAvatarUpdateService=(avatarUrl)=>{
let params = new URLSearchParams();
params.append('avatarUrl',avatarUrl)
return request.patch('/user/updateAvatar',params)
}
在UserAvatar.vue文件中提供updateAvatar函数,完成头像更新
//调用接口,更新头像url
import {userAvatarUpdateService} from '@/api/user.js'
//导入Element-Plus提示框组件
import {ElMessage} from 'element-plus'
const updateAvatar = async ()=>{
let result = await userAvatarUpdateService(imgUrl.value)
if(result.code === 0){
//成功
ElMessage.success(result.message? result.message:'修改成功')
//更新pinia中的数据
userInfoStore.info.userPic=imgUrl.value
}else{
ElMessage.error('修改失败')
}
}
在【上传头像】按钮绑定单击事件
<el-button type="success" :icon="Upload" size="large" @click="updateAvatar">
上传头像
</el-button>
如果是用的网络存储服务器那么到这一步修改头像就完成了!
练习项目后端使用的是本地文件存储,所以没有用到网络url,传入本地文件地址后端会报如下错误
点击上传由于这里练习项目没有网络服务器 数据是上传到本地的所以浏览器会拦截本地文件加载导致不能造成数据回显,但是目录下是有图片成功上传到的。
后续继续完成项目建议修改src中的值为模拟的固定网络图片url地址:https://ts1.cn.mm.bing.net/th/id/R-C.4bdc8f7f0e0201905fe400fb5156b7c7?rik=MVFo1SU7cYgFqg&riu=http%3A%2F%2Fwww.spasvo.com%2Fckfinder%2Fuserfiles%2Fimages%2F2020061536450116.jpg&ehk=r7Pp%2FX3wIOhP%2FcuW0ITLAHeD0sZPNatsyfpC3XWOM0s%3D&risl=&pid=ImgRaw&r=0
如果自己有网络服务器可以使用网络服务器的图片url
重置密码
页面结构
在UserResetPassword.vue文件中完成重置密码的页面的结构组件
<script setup>
import { ref } from 'vue'
const password = ref({
"old_pwd":"",
"new_pwd":"",
"re_pwd":""
})
const rules = {
oldPassword: [
{ required: true, message: '请输入原密码', trigger: 'blur' },
{
pattern: /^\S{5,12}$/,
message: '密码必须是5-12位的非空字符串',
trigger: 'blur'
}
],
newPassword: [
{ required: true, message: '请输入新密码', trigger: 'blur' },
{
pattern: /^\S{5,12}$/,
message: '密码必须是5-12位的非空字符串',
trigger: 'blur'
}
],
rePassword: [
{ required: true, message: '请输入确认新密码', trigger: 'blur' },
{
pattern: /^\S{5,12}$/,
message: '密码必须是5-12位的非空字符串',
trigger: 'blur'
}
]
}
</script>
<template>
<el-card class="page-container">
<template #header>
<div class="header">
<span>重置密码</span>
</div>
</template>
<el-row>
<el-col :span="12">
<el-form :model="password" :rules="rules" label-width="100px" size="large">
<el-form-item label="原密码" prop="oldPassword">
<el-input type="password" placeholder="请输入原密码" show-password v-model="password.old_pwd"></el-input>
</el-form-item>
<el-form-item label="新密码" prop="newPassword">
<el-input type="password" placeholder="请输入新密码" show-password v-model="password.new_pwd"></el-input>
</el-form-item>
<el-form-item label="确认新密码" prop="rePassword">
<el-input type="password" placeholder="请输入确认密码" show-password v-model="password.re_pwd"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary">修改密码</el-button>
<el-button type="primary">重置</el-button>
</el-form-item>
</el-form>
</el-col>
</el-row>
</el-card>
</template>
定义清空数据模型的函数
在重置按钮处绑定清空文本框数据的单击事件
<el-button type="primary" @click="clearData()">重置</el-button>
接口文档
接口请求与绑定
在src/api/user.js中提供重置密码的函数
//重置密码
export const userPasswordUpdateService = (password) => {
return request.patch('/user/updatePwd',password)
}
在UserResetPassword.vue文件中提供userPasswordUpdate请求函数
//导入路由
import {useRouter} from 'vue-router'
const router = useRouter();
//导入element提示框组件
import { ElMessage,ElMessageBox } from 'element-plus';
//导入userPasswordUpdateService函数
import {userPasswordUpdateService} from '@/api/user.js'
const userPasswordUpdate = async() => {
ElMessageBox.confirm(
'确认是否重置密码,重置之后将退出登录',
'提示',
{
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(async () => {
//用户点击了确认
let result = userPasswordUpdateService(password.value)
if(result.code ===0){
//成功
//跳转到登录页
router.push('/login')
ElMessage.success(result.message?result.message:'重置成功')
ElMessage.success('退出登录')
}else{
ElMessage.error('操作失败')
}
})
.catch(() => {
//用户点击了取消
ElMessage({
type: 'info',
message: '取消重置',
})
})
}
在修改密码按钮处绑定该函数单击事件
<el-button type="primary" @click="userPasswordUpdate()">修改密码</el-button>
保存后查看效果
项目练习完结