基本完成了用户相关前端页面的编写,经过测试能够实现相关功能
This commit is contained in:
242
src/pages/user/ProfilePage.vue
Normal file
242
src/pages/user/ProfilePage.vue
Normal file
@@ -0,0 +1,242 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import {
|
||||
ElCard,
|
||||
ElDescriptions,
|
||||
ElDescriptionsItem,
|
||||
ElTag,
|
||||
ElButton,
|
||||
ElMessage,
|
||||
} from "element-plus";
|
||||
import {
|
||||
Iphone,
|
||||
Message,
|
||||
Male,
|
||||
Female,
|
||||
UserFilled,
|
||||
} from "@element-plus/icons-vue";
|
||||
import { getUserProfile } from "@/apis/user";
|
||||
import { useUserStore } from "@/stores/UserStore";
|
||||
import type { UserInfo } from "@/types/user";
|
||||
|
||||
// 用户信息
|
||||
const userInfo = ref<UserInfo | null>(null);
|
||||
const loading = ref(true);
|
||||
const router = useRouter();
|
||||
const userStore = useUserStore();
|
||||
|
||||
// 性别映射
|
||||
const genderMap: { [key: number]: string } = {
|
||||
0: "未知",
|
||||
1: "男",
|
||||
2: "女",
|
||||
};
|
||||
|
||||
// 状态映射
|
||||
const statusMap: {
|
||||
[key: number]: { label: string; type: "danger" | "success" | "info" };
|
||||
} = {
|
||||
0: { label: "禁用", type: "danger" },
|
||||
1: { label: "正常", type: "success" },
|
||||
};
|
||||
|
||||
// 格式化时间显示
|
||||
const formatDateTime = (dateTime: string | undefined | null): string => {
|
||||
if (!dateTime) return "-";
|
||||
// 如果是完整的日期时间字符串,可以直接返回
|
||||
// 如果需要特定格式,可以使用 date-fns 或 dayjs 等库进行格式化
|
||||
return dateTime;
|
||||
};
|
||||
|
||||
// 获取用户信息
|
||||
const fetchUserProfile = async () => {
|
||||
try {
|
||||
if (!userStore.userInfo?.id) {
|
||||
ElMessage.error("用户信息不存在");
|
||||
router.push("/user/login");
|
||||
return;
|
||||
}
|
||||
|
||||
const response = await getUserProfile(userStore.userInfo.id);
|
||||
if (response.code === 200) {
|
||||
userInfo.value = response.data;
|
||||
} else {
|
||||
ElMessage.error(response.message || "获取用户信息失败");
|
||||
}
|
||||
} catch (err: unknown) {
|
||||
console.error(err);
|
||||
ElMessage.error("获取用户信息失败");
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 编辑个人信息
|
||||
const handleEditProfile = () => {
|
||||
ElMessage.info("编辑功能开发中");
|
||||
};
|
||||
|
||||
// 修改密码
|
||||
const handleChangePassword = () => {
|
||||
ElMessage.info("修改密码功能开发中");
|
||||
};
|
||||
|
||||
// 退出登录
|
||||
const handleLogout = () => {
|
||||
userStore.clearUserInfo();
|
||||
ElMessage.success("退出登录成功");
|
||||
router.push("/user/login");
|
||||
};
|
||||
|
||||
// 获取性别文本
|
||||
const getGenderText = (gender: number | undefined | null): string => {
|
||||
if (gender === undefined || gender === null) return "-";
|
||||
return genderMap[gender] || "未知";
|
||||
};
|
||||
|
||||
// 获取状态标签信息
|
||||
const getStatusInfo = (
|
||||
status: number | undefined,
|
||||
): { label: string; type: "danger" | "success" | "info" } => {
|
||||
if (status === undefined) return { label: "未知", type: "info" };
|
||||
return statusMap[status] || { label: "未知", type: "info" };
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
fetchUserProfile();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="profile-page">
|
||||
<div class="container mx-auto px-4 py-8">
|
||||
<el-card class="profile-card">
|
||||
<template #header>
|
||||
<div
|
||||
class="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-4"
|
||||
>
|
||||
<span class="text-xl font-bold">个人中心</span>
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<el-button @click="handleEditProfile" size="small">
|
||||
编辑信息
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="handleChangePassword"
|
||||
size="small"
|
||||
>
|
||||
修改密码
|
||||
</el-button>
|
||||
<el-button type="danger" @click="handleLogout" size="small">
|
||||
退出登录
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div v-if="loading" class="text-center py-10">
|
||||
<i class="el-icon-loading text-2xl"></i>
|
||||
<p class="mt-2">加载中...</p>
|
||||
</div>
|
||||
|
||||
<div v-else-if="userInfo" class="profile-content">
|
||||
<div
|
||||
class="flex flex-col md:flex-row items-center mb-8 pb-6 border-b"
|
||||
>
|
||||
<el-avatar :size="80" class="mb-4 md:mb-0 md:mr-6">
|
||||
<img v-if="userInfo.avatar" :src="userInfo.avatar" alt="头像" />
|
||||
<user-filled v-else />
|
||||
</el-avatar>
|
||||
<div class="text-center md:text-left">
|
||||
<h2 class="text-2xl font-bold mb-2">
|
||||
{{ userInfo.nickname || userInfo.username }}
|
||||
</h2>
|
||||
<p class="text-gray-600 mb-2 text-sm">@{{ userInfo.username }}</p>
|
||||
<el-tag :type="getStatusInfo(userInfo.status).type" size="small">
|
||||
{{ getStatusInfo(userInfo.status).label }}
|
||||
</el-tag>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-descriptions title="基本信息" :column="1" border>
|
||||
<el-descriptions-item label="用户ID">
|
||||
{{ userInfo.id }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="用户名">
|
||||
{{ userInfo.username }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="昵称">
|
||||
{{ userInfo.nickname || "-" }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="性别">
|
||||
<div class="flex items-center">
|
||||
<male
|
||||
v-if="userInfo.gender === 1"
|
||||
class="text-blue-500 mr-1"
|
||||
:size="14"
|
||||
/>
|
||||
<female
|
||||
v-else-if="userInfo.gender === 2"
|
||||
class="text-pink-500 mr-1"
|
||||
:size="14"
|
||||
/>
|
||||
<span>{{ getGenderText(userInfo.gender) }}</span>
|
||||
</div>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="手机号">
|
||||
<div class="flex items-center">
|
||||
<iphone class="mr-2 text-gray-500" :size="14" />
|
||||
<span>{{ userInfo.phone || "-" }}</span>
|
||||
</div>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="邮箱">
|
||||
<div class="flex items-center">
|
||||
<message class="mr-2 text-gray-500" :size="14" />
|
||||
<span>{{ userInfo.email || "-" }}</span>
|
||||
</div>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="创建时间">
|
||||
{{ formatDateTime(userInfo.createTime) }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="更新时间">
|
||||
{{ formatDateTime(userInfo.updateTime) }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
|
||||
<div v-else class="text-center py-10">
|
||||
<p>无法加载用户信息</p>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.profile-page {
|
||||
min-height: 100vh;
|
||||
background-color: #f5f7fa;
|
||||
}
|
||||
|
||||
.profile-card {
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.profile-content {
|
||||
padding: 20px 0;
|
||||
}
|
||||
|
||||
:deep(.el-descriptions__label) {
|
||||
width: 100px !important;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
:deep(.el-descriptions__content) {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user