271 lines
6.9 KiB
Vue
271 lines
6.9 KiB
Vue
<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>
|