290 lines
9.5 KiB
Vue
290 lines
9.5 KiB
Vue
<script setup>
|
||
import { ref, onMounted, onUnmounted } from 'vue';
|
||
import {
|
||
Management,
|
||
Promotion,
|
||
UserFilled,
|
||
User,
|
||
Crop,
|
||
EditPen,
|
||
SwitchButton,
|
||
CaretBottom
|
||
} from '@element-plus/icons-vue';
|
||
import avatar from '@/assets/default.png';
|
||
import { userInfoService } from '@/api/user.js';
|
||
import useUserInfoStore from '@/stores/userInfo.js';
|
||
import { useTokenStore } from '@/stores/token.js';
|
||
import { useRouter } from 'vue-router';
|
||
import { ElMessage, ElMessageBox } from 'element-plus';
|
||
|
||
const tokenStore = useTokenStore();
|
||
const userInfoStore = useUserInfoStore();
|
||
const router = useRouter();
|
||
const isPortrait = ref(false);
|
||
|
||
const getUserInfo = async () => {
|
||
let result = await userInfoService();
|
||
userInfoStore.setInfo(result.data);
|
||
};
|
||
|
||
const handleCommand = (command) => {
|
||
if (command === 'logout') {
|
||
ElMessageBox.confirm(
|
||
'您确认要退出吗?',
|
||
'温馨提示',
|
||
{
|
||
confirmButtonText: '确认',
|
||
cancelButtonText: '取消',
|
||
type: 'warning',
|
||
}
|
||
)
|
||
.then(async () => {
|
||
tokenStore.removeToken();
|
||
userInfoStore.removeInfo();
|
||
router.push('/login');
|
||
ElMessage({
|
||
type: 'success',
|
||
message: '退出登录成功',
|
||
});
|
||
})
|
||
.catch(() => {
|
||
ElMessage({
|
||
type: 'info',
|
||
message: '用户取消了退出登录',
|
||
});
|
||
});
|
||
} else {
|
||
router.push('/user/' + command);
|
||
}
|
||
};
|
||
|
||
const checkIsPortrait = () => {
|
||
isPortrait.value = window.innerWidth / window.innerHeight < 1;
|
||
};
|
||
|
||
onMounted(() => {
|
||
checkIsPortrait();
|
||
window.addEventListener('resize', checkIsPortrait);
|
||
});
|
||
|
||
onUnmounted(() => {
|
||
window.removeEventListener('resize', checkIsPortrait);
|
||
});
|
||
|
||
getUserInfo();
|
||
</script>
|
||
|
||
<template>
|
||
<el-container class="layout-container">
|
||
<!-- 左侧菜单(宽高比大于1时显示) -->
|
||
<el-aside v-if="!isPortrait" width="200px">
|
||
<div class="el-aside__logo"></div>
|
||
<el-menu active-text-color="#ffd04b" background-color="#232323" text-color="#fff" router>
|
||
<el-menu-item index="/article/category">
|
||
<el-icon>
|
||
<Management />
|
||
</el-icon>
|
||
<span>文章分类</span>
|
||
</el-menu-item>
|
||
<el-menu-item index="/article/manage">
|
||
<el-icon>
|
||
<Promotion />
|
||
</el-icon>
|
||
<span>文章管理</span>
|
||
</el-menu-item>
|
||
<el-sub-menu>
|
||
<template #title>
|
||
<el-icon>
|
||
<UserFilled />
|
||
</el-icon>
|
||
<span>个人中心</span>
|
||
</template>
|
||
<el-menu-item index="/user/info">
|
||
<el-icon>
|
||
<User />
|
||
</el-icon>
|
||
<span>基本资料</span>
|
||
</el-menu-item>
|
||
<el-menu-item index="/user/avatar">
|
||
<el-icon>
|
||
<Crop />
|
||
</el-icon>
|
||
<span>更换头像</span>
|
||
</el-menu-item>
|
||
<el-menu-item index="/user/resetPassword">
|
||
<el-icon>
|
||
<EditPen />
|
||
</el-icon>
|
||
<span>重置密码</span>
|
||
</el-menu-item>
|
||
</el-sub-menu>
|
||
</el-menu>
|
||
</el-aside>
|
||
<!-- 顶部菜单(宽高比小于1时显示) -->
|
||
<el-header v-if="isPortrait" class="mobile-header">
|
||
<el-menu mode="horizontal" active-text-color="#ffd04b" background-color="#232323" text-color="#fff" router>
|
||
<el-menu-item index="/article/category">
|
||
<el-icon>
|
||
<Management />
|
||
</el-icon>
|
||
<span>文章分类</span>
|
||
</el-menu-item>
|
||
<el-menu-item index="/article/manage">
|
||
<el-icon>
|
||
<Promotion />
|
||
</el-icon>
|
||
<span>文章管理</span>
|
||
</el-menu-item>
|
||
<el-sub-menu>
|
||
<template #title>
|
||
<el-icon>
|
||
<UserFilled />
|
||
</el-icon>
|
||
<span>个人中心</span>
|
||
</template>
|
||
<el-menu-item index="/user/info">
|
||
<el-icon>
|
||
<User />
|
||
</el-icon>
|
||
<span>基本资料</span>
|
||
</el-menu-item>
|
||
<el-menu-item index="/user/avatar">
|
||
<el-icon>
|
||
<Crop />
|
||
</el-icon>
|
||
<span>更换头像</span>
|
||
</el-menu-item>
|
||
<el-menu-item index="/user/resetPassword">
|
||
<el-icon>
|
||
<EditPen />
|
||
</el-icon>
|
||
<span>重置密码</span>
|
||
</el-menu-item>
|
||
</el-sub-menu>
|
||
</el-menu>
|
||
<el-dropdown placement="bottom-end" @command="handleCommand">
|
||
<span class="el-dropdown__box">
|
||
<el-avatar :src="userInfoStore.info.userPic ? userInfoStore.info.userPic : avatar" />
|
||
<el-icon>
|
||
<CaretBottom />
|
||
</el-icon>
|
||
</span>
|
||
<template #dropdown>
|
||
<el-dropdown-menu>
|
||
<el-dropdown-item command="info" :icon="User">基本资料</el-dropdown-item>
|
||
<el-dropdown-item command="avatar" :icon="Crop">更换头像</el-dropdown-item>
|
||
<el-dropdown-item command="resetPassword" :icon="EditPen">重置密码</el-dropdown-item>
|
||
<el-dropdown-item command="logout" :icon="SwitchButton">退出登录</el-dropdown-item>
|
||
</el-dropdown-menu>
|
||
</template>
|
||
</el-dropdown>
|
||
</el-header>
|
||
<!-- 右侧主区域 -->
|
||
<el-container>
|
||
<!-- 头部区域 -->
|
||
<el-header v-if="!isPortrait">
|
||
<div>程序员:<strong>{{ userInfoStore.info.nickname }}</strong></div>
|
||
<el-dropdown placement="bottom-end" @command="handleCommand">
|
||
<span class="el-dropdown__box">
|
||
<el-avatar :src="userInfoStore.info.userPic ? userInfoStore.info.userPic : avatar" />
|
||
<el-icon>
|
||
<CaretBottom />
|
||
</el-icon>
|
||
</span>
|
||
<template #dropdown>
|
||
<el-dropdown-menu>
|
||
<el-dropdown-item command="info" :icon="User">基本资料</el-dropdown-item>
|
||
<el-dropdown-item command="avatar" :icon="Crop">更换头像</el-dropdown-item>
|
||
<el-dropdown-item command="resetPassword" :icon="EditPen">重置密码</el-dropdown-item>
|
||
<el-dropdown-item command="logout" :icon="SwitchButton">退出登录</el-dropdown-item>
|
||
</el-dropdown-menu>
|
||
</template>
|
||
</el-dropdown>
|
||
</el-header>
|
||
<!-- 中间区域 -->
|
||
<el-main>
|
||
<router-view></router-view>
|
||
</el-main>
|
||
<!-- 底部区域 -->
|
||
<el-footer>大事件 ©2025 Created by xclele</el-footer>
|
||
</el-container>
|
||
</el-container>
|
||
</template>
|
||
|
||
<style lang="scss" scoped>
|
||
.layout-container {
|
||
height: 100vh;
|
||
|
||
.el-aside {
|
||
background-color: #232323;
|
||
|
||
&__logo {
|
||
height: 120px;
|
||
background: url('@/assets/logo.png') no-repeat center / 120px auto;
|
||
}
|
||
|
||
.el-menu {
|
||
border-right: none;
|
||
}
|
||
}
|
||
|
||
.el-header {
|
||
background-color: #fff;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
|
||
.el-dropdown__box {
|
||
display: flex;
|
||
align-items: center;
|
||
|
||
.el-icon {
|
||
color: #999;
|
||
margin-left: 10px;
|
||
}
|
||
|
||
&:active,
|
||
&:focus {
|
||
outline: none;
|
||
}
|
||
}
|
||
}
|
||
|
||
.el-footer {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 14px;
|
||
color: #666;
|
||
}
|
||
|
||
@media (orientation: portrait) {
|
||
.el-aside {
|
||
display: none;
|
||
}
|
||
|
||
.mobile-header {
|
||
display: flex;
|
||
background-color: #232323;
|
||
.el-menu {
|
||
width: 100%;
|
||
}
|
||
.el-dropdown__box {
|
||
display: flex;
|
||
align-items: center;
|
||
|
||
.el-icon {
|
||
color: #999;
|
||
margin-left: 10px;
|
||
}
|
||
|
||
&:active,
|
||
&:focus {
|
||
outline: none;
|
||
}
|
||
}
|
||
}
|
||
|
||
}
|
||
}
|
||
</style> |