頂部導航欄個人信息顯示
接口文檔
接口請求與綁定?
導航欄下拉菜單功能
路由實現
退出登錄和路由跳轉實現
基本資料修改
頁面結構
?接口文檔
?接口請求與綁定?
修改頭像
頁面結構?
頭像回顯
頭像上傳
?接口文檔
重置密碼
頁面結構
接口文檔
接口請求與綁定
?
頂部導航欄個人信息顯示
????????在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){//成功//存儲piniauserInfoStore.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.nicknameuserInfoStore.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>
?保存后查看效果
項目練習完結