实现个人中心和修改密码

个人中心

基础搭建页面

添加点击事件

1
<el-dropdown-item @click="router.push('/manager/person')">个人信息</el-dropdown-item>

新建一个Person.vue

1
2
3
4
5
6
7
8
9
10
<template>
<div>
个人中心
</div>
</template>

<script setup>


</script>

路由:

1
2
3
4
5
6
7
8
9
10
routes: [
{path: '/',redirect: '/manager/home'},
{path: '/manager', component:() =>import('../views/Manager.vue'),
children: [
{path: 'home',meta:{name:'主页'}, component:() =>import('../views/Home.vue'),},
{path: 'admin',meta:{name:'管理员信息'}, component:() =>import('../views/Admin.vue'),},
{path: 'user',meta:{name:'普通用户信息'}, component:() =>import('../views/User.vue'),},
{path: 'person',meta:{name:'个人信息'}, component:() =>import('../views/Person.vue'),},
]
...

image-20250304200407796.png

接下来我们来做这个页面:

我们直接复制User.vue中的表单

遇到问题:

Cannot read properties of undefined (reading ‘username’)

image-20250304201528734.png

搜索一下: xxx.username 然后xxx是一个undefined 或者null 就能排查这个问题了,因为复制过来的时候没有改form为user

改完即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
<template>
<div class="card" style="width: 50%;">
<div>个人中心</div>

<el-form ref="formRef" :model="data.user" label-width="80px" style="padding: 20px 30px 10px 0">
<el-form-item prop="username" label="账号">
<el-input v-model="data.user.username" autocomplete="off" placeholder="请输入账号"/>
</el-form-item>

<el-form-item prop="name" label="名称">
<el-input v-model="data.user.name" autocomplete="off" placeholder="请输入名称"/>
</el-form-item>

<el-form-item prop="name" label="电话">
<el-input v-model="data.user.phone" autocomplete="off" placeholder="请输入电话"/>
</el-form-item>

<el-form-item prop="name" label="邮箱" placeholder="请输入邮箱">
<el-input v-model="data.user.email" autocomplete="off" />
</el-form-item>

<el-form-item prop="avatar" label="头像" >
<el-upload
action="http://localhost:9999/files/upload"
:headers="{ token: data.user.token }"
:on-success="handleFileSuccess"
list-type="picture"
>
<el-button type="primary">上传头像</el-button>
</el-upload>
</el-form-item>
</el-form>

<div style="text-align: center;">
<el-button type="primary" style="padding: 18px 35px" @click="update">
保存
</el-button>
</div>
</div>
</template>

<script setup>
import {reactive} from "vue";
import request from "@/utils/request.js";
import {ElMessage} from "element-plus";

const data = reactive({
user: JSON.parse(localStorage.getItem("code2025_user") || '{}'),

})

const handleFileSuccess = (res) => {
data.user.avatar = res.data
}

const update = () => {
let url;
if(data.user.role === 'ADMIN'){
url = '/admin/update'
}
else if(data.user.role === 'USER'){
url = '/user/update'
}
request.put(url,data.user).then(res => {
if(res.code === '200') {
ElMessage.success('更新成功!')
//更新localstorage
localStorage.setItem("code2025_user",JSON.stringify(data.user)) //转成字符串存进去
}
})
}

</script>

这样写完后的效果是这样: image-20250304204951366.png

问题是每次保存完 我们上面的头像和名字不会立即更改,那是因为顶部是属于Manager.vue的

解决方法: 设计到数据的传递

Person.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const emit = defineEmits(['updateUser'])


const update = () => {
let url;
if(data.user.role === 'ADMIN'){
url = '/admin/update'
}
else if(data.user.role === 'USER'){
url = '/user/update'
}
request.put(url,data.user).then(res => {
if(res.code === '200') {
ElMessage.success('更新成功!')
//更新localstorage
localStorage.setItem("code2025_user",JSON.stringify(data.user)) //转成字符串存进去
emit('updateUser')
}
})
}

Manager.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
... 
<!-- 菜单区域结束 -->

<!-- 数据渲染区域开始 -->
<div style="flex: 1;width: 0; padding: 10px; background-color: #faf4fa">
<RouterView @updateUser="updateUser"/>
</div>
<!-- 数据渲染区域结束 -->
</div>
<!-- 下方区域结束 -->
</div>
</template>

<script setup>
import router from "@/router/index.js";
import {reactive} from "vue"

const data = reactive({
user: JSON.parse(localStorage.getItem('code2025_user') || "{}")
})

const updateUser = () => {
//因为传过来这边的时候localstorage已经更新了在这里直接拿就可以
data.user = JSON.parse(localStorage.getItem("code2025_user") || '{}')
}
...

修改密码

基础搭建页面

manager.vue

1
2
<el-dropdown-item @click="router.push('/manager/updatePassword')">修改密码</el-dropdown-item>

updatePassword.vue

1
2
3
4
5
6
7
8
9
<template>
<div>

</div>
</template>

<script setup>

</script>

路由

1
2
3
4
5
6
7
8
9
{path: '/manager', component:() =>import('../views/Manager.vue'),
children: [
{path: 'home',meta:{name:'主页'}, component:() =>import('../views/Home.vue'),},
{path: 'admin',meta:{name:'管理员信息'}, component:() =>import('../views/Admin.vue'),},
{path: 'user',meta:{name:'普通用户信息'}, component:() =>import('../views/User.vue'),},
{path: 'person',meta:{name:'个人信息'}, component:() =>import('../views/Person.vue'),},
{path: 'updatePassword',meta:{name:'修改密码'}, component:() =>import('../views/updatePassword.vue'),},
]
},

Debug发现前端没有传递过来

image-20250304212937448.png

image-20250304213813619

点击页面没有反应怎么办?

1.打开f12看看前端控制台有没有报错,有报错就看一下,没有就下一步

2.确定一下有没有调用到后端接口 (打断点) ,如果没有走到那就排查一下接口,如果走到了,跟着断点跟到逻辑哪里看看是不是正确的走向.

3.再打开f12,看看该接口返回的数据

定位发现:

image-20250304222410563.png

所以我们知道就是前端的问题,因为我们前端没有对返回500 做处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
<template>
<div class="card" style="width: 50%">
<div style="font-size: 16px;">修改密码</div>
<el-form ref="formRef" :rules="data.rules" :model="data.user" label-width="80px" style="padding: 20px 30px 10px 0;">
<el-form-item prop="password" label="原密码">
<el-input size="large" show-password v-model="data.user.password" auto-complete="off" prefix-icon="Lock" placeholder="请输入密码">
</el-input>
</el-form-item>

<el-form-item prop="newPassword" label="新密码">
<el-input size="large" show-password v-model="data.user.newPassword" auto-complete="off" prefix-icon="Lock" placeholder="请输入密码">
</el-input>
</el-form-item>

<el-form-item prop="new2Password" label="确认密码">
<el-input size="large" show-password v-model="data.user.new2Password" auto-complete="off" prefix-icon="Lock" placeholder="请输入密码">
</el-input>
</el-form-item>
</el-form>

<div style="text-align: center;">
<el-button type="primary" style="padding: 20px 30px;" @click="updatePassword">保存</el-button>
</div>
</div>
</template>

<script setup>

import {reactive,ref} from "vue";
import request from "@/utils/request.js";
import {ElMessage} from "element-plus";

const data = reactive({
user: JSON.parse(localStorage.getItem("code2025_user") || '{}'),
rules: {
password: [
{ required: true, message: '请输入原密码', trigger: 'blur' }
],
newPassword: [
{required: true,message: '请填写新密码',trigger: 'blur'}
],
new2Password: [
{required: true,message: '请确认新密码',trigger: 'blur'}
],

// newPassword: [
// { required: true, message: '请填写新密码', trigger: 'blur' },
// { min: 8, message: '密码至少8位', trigger: 'blur' },
// { pattern: /^(?=.*[A-Za-z])(?=.*\d).+$/,
// message: '需包含字母和数字',
// trigger: 'blur'
// }
// ]
}



})

const formRef = ref()

const updatePassword = () => {
formRef.value.validate(valid => {
if (valid) {
request.post('/updatePassword', data.user)
.then(res => {
try {
if (res.code === '200') {
ElMessage.success('修改成功');
setInterval(()=>{
localStorage.removeItem('code2025_user');
location.href = '/login';
},500)

} else {
ElMessage.error(res.msg);
}
} catch (error) {
console.error(error);
ElMessage.error('请求失败');
}
})
.catch(error => {
console.error(error);
ElMessage.error('请求失败');
});
}
});
};
</script>