feat(personal): 新增个人中心核心功能
- 添加UserCenter用户头像下拉菜单组件 - 新增个人信息相关API接口封装 - 提供完整的个人信息管理功能接口
This commit is contained in:
parent
49e5a1e018
commit
2c5e2234d8
112
src/components/common/UserCenter.vue
Normal file
112
src/components/common/UserCenter.vue
Normal file
@ -0,0 +1,112 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, h } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useAuthStore } from '@/store/auth'
|
||||
import { coiMsgBox } from '@/utils/coi'
|
||||
import IconUser from '~icons/icon-park-outline/user'
|
||||
import IconLogout from '~icons/icon-park-outline/logout'
|
||||
|
||||
const authStore = useAuthStore()
|
||||
const router = useRouter()
|
||||
|
||||
// 获取用户信息
|
||||
const userInfo = computed(() => authStore.userInfo)
|
||||
|
||||
// 获取用户显示名称
|
||||
const displayName = computed(() => {
|
||||
if (!userInfo.value)
|
||||
return '未知用户'
|
||||
return userInfo.value.userName || '未知用户'
|
||||
})
|
||||
|
||||
// 获取用户头像
|
||||
const avatar = computed(() => {
|
||||
if (!userInfo.value?.avatar)
|
||||
return ''
|
||||
return userInfo.value.avatar
|
||||
})
|
||||
|
||||
// 处理个人中心点击
|
||||
function handlePersonalCenter() {
|
||||
router.push('/personal-center')
|
||||
}
|
||||
|
||||
// 处理退出登录
|
||||
function handleLogout() {
|
||||
coiMsgBox('确定要退出登录吗?', '退出确认').then(() => {
|
||||
authStore.logout()
|
||||
}).catch(() => {
|
||||
// 取消操作
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<n-dropdown
|
||||
placement="bottom-end"
|
||||
:options="[
|
||||
{
|
||||
label: '个人中心',
|
||||
key: 'personal-center',
|
||||
icon: () => h(IconUser),
|
||||
},
|
||||
{
|
||||
type: 'divider',
|
||||
},
|
||||
{
|
||||
label: '退出登录',
|
||||
key: 'logout',
|
||||
icon: () => h(IconLogout),
|
||||
},
|
||||
]"
|
||||
@select="(key) => {
|
||||
if (key === 'personal-center') {
|
||||
handlePersonalCenter()
|
||||
}
|
||||
else if (key === 'logout') {
|
||||
handleLogout()
|
||||
}
|
||||
}"
|
||||
>
|
||||
<div class="flex items-center gap-2 cursor-pointer hover:bg-gray-50 hover:bg-opacity-80 rounded-lg px-3 py-2 transition-colors">
|
||||
<!-- 用户头像 -->
|
||||
<n-avatar
|
||||
:size="32"
|
||||
:src="avatar"
|
||||
fallback-src=""
|
||||
round
|
||||
class="border border-gray-200"
|
||||
>
|
||||
<template #placeholder>
|
||||
<icon-park-outline-user class="text-lg" />
|
||||
</template>
|
||||
</n-avatar>
|
||||
|
||||
<!-- 用户名称 -->
|
||||
<span class="text-sm font-medium text-gray-700 max-w-20 truncate">
|
||||
{{ displayName }}
|
||||
</span>
|
||||
|
||||
<!-- 下拉箭头 -->
|
||||
<icon-park-outline-down class="text-xs text-gray-500" />
|
||||
</div>
|
||||
</n-dropdown>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.dark .hover\:bg-gray-50:hover {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.dark .text-gray-700 {
|
||||
color: #e5e7eb;
|
||||
}
|
||||
|
||||
.dark .text-gray-500 {
|
||||
color: #9ca3af;
|
||||
}
|
||||
|
||||
.dark .border-gray-200 {
|
||||
border-color: #374151;
|
||||
}
|
||||
</style>
|
||||
64
src/service/api/personal/index.ts
Normal file
64
src/service/api/personal/index.ts
Normal file
@ -0,0 +1,64 @@
|
||||
import { request } from '../../http'
|
||||
|
||||
// 个人资料数据类型
|
||||
export interface PersonalDataVo {
|
||||
userId: number
|
||||
userName: string
|
||||
loginName: string
|
||||
email?: string
|
||||
phone?: string
|
||||
sex?: string
|
||||
avatar?: string
|
||||
userStatus?: string
|
||||
createTime?: string
|
||||
}
|
||||
|
||||
// 修改个人资料请求类型
|
||||
export interface UpdatePersonalBo {
|
||||
userName?: string
|
||||
email?: string
|
||||
phone?: string
|
||||
sex?: string
|
||||
avatar?: string
|
||||
}
|
||||
|
||||
// 修改密码请求类型
|
||||
export interface UpdatePasswordBo {
|
||||
password: string
|
||||
newPassword: string
|
||||
confirmPassword: string
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取个人资料
|
||||
*/
|
||||
export function getPersonalData() {
|
||||
return request.Get<Service.ResponseResult<PersonalDataVo>>('/coder/sysLoginUser/getPersonalData')
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改个人基本资料
|
||||
*/
|
||||
export function updateBasicData(data: UpdatePersonalBo) {
|
||||
return request.Post<Service.ResponseResult<string>>('/coder/sysLoginUser/updateBasicData', data)
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改登录密码
|
||||
*/
|
||||
export function updatePassword(data: UpdatePasswordBo) {
|
||||
return request.Post<Service.ResponseResult<string>>('/coder/sysLoginUser/updateUserPwd', data)
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传头像文件
|
||||
* @param file 文件
|
||||
* @param fileSize 文件大小限制(MB)
|
||||
*/
|
||||
export function uploadAvatar(file: File, fileSize: number = 5) {
|
||||
const formData = new FormData()
|
||||
formData.append('file', file)
|
||||
// 注意:不要手动设置 Content-Type,让浏览器自动设置以包含正确的 boundary
|
||||
// 使用数字标识符 "1" 代表头像类型,避免数据库字段长度限制
|
||||
return request.Post<Service.ResponseResult<any>>(`/coder/file/uploadFile/${fileSize}/pictures/1`, formData)
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user