2025-10-27 23:13:08 +08:00

179 lines
4.6 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<header class="common-header">
<div class="logo" @click="goHome" style="cursor: pointer;">
<slot name="logo">
<img src="@/assets/imgs/logo.webp" alt="Logo" />
</slot>
</div>
<nav class="nav">
<slot name="nav"></slot>
</nav>
<div class="actions">
<slot name="actions">
<el-dropdown @command="handleCommand" placement="bottom-end">
<div class="user-info cursor-pointer">
<img
:src="getAvatarUrl()"
alt="User Avatar"
style="
height: 32px;
width: 32px;
border-radius: 50%;
margin-right: 8px;
"
/>
<span>{{ getUserName() }}</span>
</div>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item command="profile">
<!-- <el-icon><user /></el-icon> -->
<i class="fas fa-user"></i>
<span>个人中心</span>
</el-dropdown-item>
<el-dropdown-item command="logout" divided>
<!-- <el-icon><arrow-right /></el-icon> -->
<i class="fas fa-sign-out-alt"></i>
<span>退出登录</span>
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</slot>
</div>
</header>
</template>
<script setup lang="ts">
// 安全获取头像URL
defineOptions({ name: "CommonHeader" });
import { useRouter } from "vue-router";
import { User, ArrowRight } from "@element-plus/icons-vue";
import { ElMessage } from "element-plus";
import { authAPI } from "@/services/api";
const router = useRouter();
// 创建一个函数来安全地访问 localStorage
const getAvatarUrl = () => {
try {
// 检查 window 和 localStorage 是否存在
if (typeof window !== "undefined" && window.localStorage) {
try {
const userItem = window.localStorage.getItem("user");
const userInfo = userItem ? JSON.parse(userItem) : {};
return userInfo.avatar || "/src/assets/imgs/default_avatar.png";
} catch (error) {
console.warn("解析用户信息失败:", error);
return "/src/assets/imgs/default_avatar.png";
}
}
// 如果 localStorage 不可用,返回默认头像
return "/src/assets/imgs/default_avatar.png";
} catch (error) {
console.warn("获取头像失败:", error);
return "/src/assets/imgs/default_avatar.png";
}
};
// 创建一个函数来安全地访问 localStorage 中的用户名
const getUserName = () => {
try {
// 检查 window 和 localStorage 是否存在
if (typeof window !== "undefined" && window.localStorage) {
return JSON.parse(window.localStorage.getItem("user") || "{}").nickname;
}
// 如果 localStorage 不可用,返回默认用户名
return "用户";
} catch (error) {
console.warn("获取用户名失败:", error);
return "用户";
}
};
// 点击logo返回首页
const goHome = () => {
router.push('/');
};
// 处理下拉菜单命令
const handleCommand = (command: string) => {
switch (command) {
case "profile":
handleProfile();
break;
case "logout":
handleLogout();
break;
}
};
// 个人中心处理函数
const handleProfile = () => {
// 这里可以根据实际项目情况跳转到个人中心页面
ElMessage.success("跳转到个人中心");
// 示例router.push('/profile');
};
// 登出处理函数
const handleLogout = async () => {
try {
// 调用登出API
await authAPI.logout();
// 清除本地登录状态
if (typeof window !== "undefined" && window.localStorage) {
window.localStorage.removeItem("user");
window.localStorage.removeItem("token");
window.localStorage.removeItem("isAuthenticated");
window.localStorage.removeItem("token");
}
// 跳转到登录页面
router.push("/login");
ElMessage.success("退出登录成功");
} catch (error) {
console.error("退出登录失败:", error);
ElMessage.error("退出登录失败");
}
};
</script>
<style lang="scss" scoped>
.common-header {
display: flex;
align-items: center;
justify-content: space-between;
height: 64px;
padding: 0 24px;
background: #fff;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
}
.logo img {
height: 40px;
}
.nav {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
}
.actions {
display: flex;
align-items: center;
gap: 16px;
.user-info {
display: flex;
align-items: center;
gap: 8px;
}
.cursor-pointer {
cursor: pointer;
}
}
</style>