2025-04-27 18:22:46 +08:00

271 lines
6.9 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>
<a-layout style="min-height: 100vh">
<a-layout-sider
v-model:collapsed="collapsed"
:trigger="null"
collapsible
>
<div class="logo">
<img
src="../../assets/logo.png"
style="height: 30px"
/><span
style="
font-weight: 700;
font-size: 16px;
color: #32b768;
opacity: 1;
transition: opacity 1s;
animation: fade 1s;
"
v-if="!collapsed"
>景上出行</span>
</div>
<a-menu
v-model:openKeys="openKeys"
v-model:selectedKeys="selectedKeys"
mode="inline"
theme="dark"
:items="items"
@click="handleClick"
/>
</a-layout-sider>
<a-layout>
<a-layout-header style="background: #fff; padding: 0">
<!-- 菜单折叠 -->
<menu-unfold-outlined
v-if="collapsed"
class="trigger"
@click="() => (collapsed = !collapsed)"
/>
<menu-fold-outlined
v-else
class="trigger"
@click="() => (collapsed = !collapsed)"
/>
<!-- <a-button
type="primary"
@click="goBack"
>
返回
</a-button> -->
<!-- 登录 -->
<div class="topAvatar">
<template v-if="userdfrname != '' && username != 'admin'">
<a-dropdown>
<a class="ant-dropdown-link" @click.prevent>
当前区域:{{ userdfrname }} <DownOutlined />
</a>
<template #overlay>
<a-menu @click="onOperationClick">
<a-menu-item v-for="(item) in useroperation" :key="item.regionId" :data="item">{{ item.regionName }}</a-menu-item>
</a-menu>
</template>
</a-dropdown>
<a-divider type="vertical" />
<UserOutlined style="margin: 0px 5px;" />
</template>
<a-dropdown>
<a
class="ant-dropdown-link"
@click.prevent
>
{{ username }}
<DownOutlined />
</a>
<template #overlay>
<a-menu>
<!-- <a-menu-item>
<a href="javascript:;">个人中心</a>
</a-menu-item> -->
<a-popconfirm
placement="topRight"
@confirm="confirm"
@cancel="cancel"
title="确认退出吗?"
confirm-button-text="确认"
cancel-button-text="取消"
ok-text=""
cancel-text=""
>
<a-menu-item v-if="isLogin">退出登录</a-menu-item>
</a-popconfirm>
<a-menu-item
v-if="!isLogin"
@click="$router.push('/login')"
>去登录</a-menu-item>
</a-menu>
</template>
</a-dropdown>
</div>
</a-layout-header>
<a-layout-content :style="{ margin: '24px 16px', padding: '24px', background: '#fff', minHeight: '280px' }">
<!-- 二级路由出口(home等等通常放在main主区域) -->
<router-view />
</a-layout-content>
</a-layout>
</a-layout>
</template>
<script setup>
import {
MenuFoldOutlined,
MenuUnfoldOutlined
} from '@ant-design/icons-vue'
import { ref, onMounted } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { message } from 'ant-design-vue'
import { getMenus } from '../../pages';
import { getLogoutAPI } from '@/apis/login.js'
import { getCache, setCache, clearStorage } from '@/utils/authority';
const selectedKeys = ref(['1'])
const openKeys = ref(['1'])
const collapsed = ref(false)
const items = ref([])
//路由切换
const router = useRouter()
// 处理页面刷新之后高亮菜单和显示的组件不一致的情况
// 登录状态
const isLogin = ref(false)
const username = ref('')
const useroperation = ref([])
const userdfrname = ref('')
onMounted(() => {
isLogin.value = getCache('ebike-token') ? true : false
//跳转到登录页面
if (!isLogin.value) {
router.push('/login');
return;
}
console.log('isLogin', isLogin.value)
// 获取用户名
const userinfo = getCache('ebike-userinfo');
console.log('userinfo', userinfo)
username.value = userinfo.username ? userinfo.username : 'X'
//获取用户区域
const cuseroperation = getCache('ebike-useroperation');
if(cuseroperation){
useroperation.value = cuseroperation;
}
//获取默认区域
const cuserdefultoperation = getCache('ebike-userdefultoperation');
if(cuserdefultoperation){
userdfrname.value = cuserdefultoperation.regionName ? cuserdefultoperation.regionName : '';
}
const menus = getMenus()
items.value = menus
const route = useRoute()
let path = route.path;
const nodes = findNodeWithParents(items.value, 'path', path);
if (nodes.length > 0) {
const lastNode = nodes[nodes.length - 1];
selectedKeys.value = [lastNode.key];
openKeys.value = nodes.slice(1).map(node => node.key);
}
})
const handleClick = (e) => {
const nodes = findNodeWithParents(items.value, 'key', e.key);
if (nodes.length > 0) {
const lastNode = nodes[nodes.length - 1];
router.push(lastNode.path);
}
}
const findNodeWithParents = (obj, targetKey, targetValue, parents = []) => {
for (const [key, value] of Object.entries(obj)) {
if (key === targetKey && value === targetValue) {
return [...parents, obj];
}
if (typeof value === 'object' && value !== null) {
const result = findNodeWithParents(value, targetKey, targetValue, [...parents, obj]);
if (result.length > 0) {
return result;
}
}
}
return [];
}
const confirm = async (e) => {
const res = await getLogoutAPI()
if (res.code != 200) {
message.error(res.message)
return
}
clearStorage();
router.push('/login');
return
}
const cancel = (e) => {
console.log(e)
return
}
const onOperationClick = (e) => {
if(e.item && e.item.data){
const regionName = e.item.data.regionName;
userdfrname.value = regionName;
//存储默认区域
setCache('ebike-userdefultoperation', e.item.data);
}
}
</script>
<style>
.trigger {
font-size: 18px;
line-height: 64px;
padding: 0 24px;
cursor: pointer;
transition: color 0.3s;
}
.trigger:hover {
color: #1890ff;
}
.logo {
height: 32px;
/*background: rgba(255, 255, 255, 0.3);*/
margin: 16px;
color: #fff;
display: flex;
gap: 10px;
align-items: center;
padding-left: 10px;
}
.topAvatar {
font-size: 14px;
float: right;
margin-right: 40px;
div {
display: inline-block;
}
.el-dropdown-link {
color: #fff;
}
.el-avatar {
margin: 0 20px;
}
.logoutLink {
text-decoration: none;
}
}
@keyframes fade {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
</style>