Files
Study/web/src/view/layout/index.vue
T
2023-10-10 16:46:08 +08:00

384 lines
12 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>
<el-container class="layout-cont">
<el-container :class="[isSider?'openside':'hideside',isMobile ? 'mobile': '']">
<el-row
:class="[isShadowBg && isMobile?'bg-black opacity-30 w-full h-full absolute top-0 left-0 z-[1001]':'']"
@click="changeShadow()"
/>
<el-aside
class="main-cont gva-aside"
:style="{width:asideWidth()}"
>
<div
class="min-h-[60px] text-center transition-all duration-300 flex items-center justify-center gap-2"
:style="{background: backgroundColor}"
>
<img
alt
class="w-9 h-9 p-1 bg-white rounded-full"
:src="$GIN_VUE_ADMIN.appLogo"
>
<div
v-if="isSider"
class="inline-flex font-bold text-2xl"
:style="{color:textColor}"
>{{ $GIN_VUE_ADMIN.appName }}</div>
</div>
<Aside class="aside" />
</el-aside>
<!-- 分块滑动功能 -->
<el-main class="main-cont main-right">
<transition
:duration="{ enter: 800, leave: 100 }"
mode="out-in"
name="el-fade-in-linear"
>
<div
:style="{width: `calc(100% - ${getAsideWidth()})`}"
class="fixed top-0 box-border z-50"
>
<el-row>
<el-col>
<el-header class="header-cont">
<el-row class="p-0 h-full">
<el-col
:xs="2"
:lg="1"
:md="1"
:sm="1"
:xl="1"
class="z-50 flex items-center pl-3"
>
<div
class="text-black cursor-pointer text-lg leading-5"
@click="totalCollapse"
>
<div
v-if="isCollapse"
class="gvaIcon gvaIcon-arrow-double-right"
/>
<div
v-else
class="gvaIcon gvaIcon-arrow-double-left"
/>
</div>
</el-col>
<el-col
:xs="10"
:lg="14"
:md="14"
:sm="9"
:xl="14"
:pull="1"
class="flex items-center"
>
<!-- 修改为手机端不显示顶部标签 -->
<el-breadcrumb
v-show="!isMobile"
class="breadcrumb"
>
<el-breadcrumb-item
v-for="item in matched.slice(1,matched.length)"
:key="item.path"
>{{ fmtTitle(item.meta.title,route) }}</el-breadcrumb-item>
</el-breadcrumb>
</el-col>
<el-col
:xs="12"
:lg="9"
:md="9"
:sm="14"
:xl="9"
class="flex items-center justify-end"
>
<div class="mr-1.5 flex items-center">
<Search />
<el-dropdown>
<div class="flex justify-center items-center h-full w-full">
<span class="cursor-pointer flex justify-center items-center">
<CustomPic />
<span
v-show="!isMobile"
style="margin-left: 5px"
>{{ userStore.userInfo.nickName }}</span>
<el-icon>
<arrow-down />
</el-icon>
</span>
</div>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item>
<span class="font-bold">
当前角色:{{ userStore.userInfo.authority.authorityName }}
</span>
</el-dropdown-item>
<template v-if="userStore.userInfo.authorities">
<el-dropdown-item
v-for="item in userStore.userInfo.authorities.filter(i=>i.authorityId!==userStore.userInfo.authorityId)"
:key="item.authorityId"
@click="changeUserAuth(item.authorityId)"
>
<span>
切换为:{{ item.authorityName }}
</span>
</el-dropdown-item>
</template>
<el-dropdown-item icon="avatar">
<div
class="command-box"
style="display: flex"
@click="handleCommand"
>
<div>指令菜单</div>
<div style="margin-left: 8px">
<span class="button">{{ first }}</span>
+
<span class="button">K</span>
</div>
</div>
</el-dropdown-item>
<el-dropdown-item
icon="avatar"
@click="toPerson"
>个人信息</el-dropdown-item>
<el-dropdown-item
icon="reading-lamp"
@click="userStore.LoginOut"
>登 出</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
</el-col>
</el-row>
</el-header>
</el-col>
</el-row>
<!-- 当前面包屑用路由自动生成可根据需求修改 -->
<!--
:to="{ path: item.path }" 暂时注释不用-->
<HistoryComponent ref="layoutHistoryComponent" />
</div>
</transition>
<router-view
v-if="reloadFlag"
v-slot="{ Component }"
class="admin-box"
>
<div
v-loading="loadingFlag"
element-loading-text="正在加载中"
>
<transition
mode="out-in"
name="el-fade-in-linear"
>
<keep-alive :include="routerStore.keepAliveRouters">
<component :is="Component" />
</keep-alive>
</transition>
</div>
</router-view>
<BottomInfo />
<setting />
<CommandMenu ref="command" />
</el-main>
</el-container>
</el-container>
</template>
<script setup>
import Aside from '@/view/layout/aside/index.vue'
import HistoryComponent from '@/view/layout/aside/historyComponent/history.vue'
import Search from '@/view/layout/search/search.vue'
import BottomInfo from '@/view/layout/bottomInfo/bottomInfo.vue'
import CustomPic from '@/components/customPic/index.vue'
import CommandMenu from '@/components/commandMenu/index.vue'
import Setting from './setting/index.vue'
import { setUserAuthority } from '@/api/user'
import { emitter } from '@/utils/bus.js'
import { computed, ref, onMounted, nextTick } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { useRouterStore } from '@/pinia/modules/router'
import { fmtTitle } from '@/utils/fmtRouterTitle'
import { useUserStore } from '@/pinia/modules/user'
defineOptions({
name: 'Layout',
})
const router = useRouter()
const route = useRoute()
const routerStore = useRouterStore()
// 三种窗口适配
const isCollapse = ref(false)
const isSider = ref(true)
const isMobile = ref(false)
const first = ref('')
const dialogVisible = ref(false)
const initPage = () => {
// 判断当前用户的操作系统
if (window.localStorage.getItem('osType') === 'WIN') {
first.value = 'Ctrl'
} else {
first.value = '⌘'
}
// 当用户同时按下ctrl和k键的时候
const handleKeyDown = (e) => {
if (e.ctrlKey && e.key === 'k') {
// 阻止浏览器默认事件
e.preventDefault()
handleCommand()
}
}
window.addEventListener('keydown', handleKeyDown)
const screenWidth = document.body.clientWidth
if (screenWidth < 1000) {
isMobile.value = true
isSider.value = false
isCollapse.value = true
} else if (screenWidth >= 1000 && screenWidth < 1200) {
isMobile.value = false
isSider.value = false
isCollapse.value = true
} else {
isMobile.value = false
isSider.value = true
isCollapse.value = false
}
}
initPage()
const command = ref()
const handleCommand = () => {
command.value.open()
}
const loadingFlag = ref(false)
onMounted(() => {
// 挂载一些通用的事件
emitter.emit('collapse', isCollapse.value)
emitter.emit('mobile', isMobile.value)
emitter.on('reload', reload)
emitter.on('showLoading', () => {
loadingFlag.value = true
})
emitter.on('closeLoading', () => {
loadingFlag.value = false
})
window.onresize = () => {
return (() => {
initPage()
emitter.emit('collapse', isCollapse.value)
emitter.emit('mobile', isMobile.value)
})()
}
if (userStore.loadingInstance) {
userStore.loadingInstance.close()
}
})
const userStore = useUserStore()
const asideWidth = () => {
if (isMobile.value) {
return isCollapse.value ? '0px' : '220px'
}
return isCollapse.value ? '54px' : '220px'
}
const getAsideWidth = () => {
if (isMobile.value) return '0px'
return isCollapse.value ? '54px' : '220px'
}
const textColor = computed(() => {
if (userStore.sideMode === 'dark') {
return '#fff'
} else if (userStore.sideMode === 'light') {
return '#191a23'
} else {
return userStore.baseColor
}
})
const backgroundColor = computed(() => {
if (userStore.sideMode === 'dark') {
return '#191a23'
} else if (userStore.sideMode === 'light') {
return '#fff'
} else {
return userStore.sideMode
}
})
const matched = computed(() => route.meta.matched)
const changeUserAuth = async(id) => {
const res = await setUserAuthority({
authorityId: id
})
if (res.code === 0) {
window.sessionStorage.setItem('needCloseAll', 'true')
window.location.reload()
}
}
const reloadFlag = ref(true)
let reloadTimer = null
const reload = async() => {
if (reloadTimer) {
window.clearTimeout(reloadTimer)
}
reloadTimer = window.setTimeout(async() => {
if (route.meta.keepAlive) {
reloadFlag.value = false
await nextTick()
reloadFlag.value = true
} else {
const title = route.meta.title
router.push({ name: 'Reload', params: { title }})
}
}, 400)
}
const isShadowBg = ref(false)
const totalCollapse = () => {
isCollapse.value = !isCollapse.value
isSider.value = !isCollapse.value
isShadowBg.value = !isCollapse.value
emitter.emit('collapse', isCollapse.value)
}
const toPerson = () => {
router.push({ name: 'person' })
}
const changeShadow = () => {
isShadowBg.value = !isShadowBg.value
isSider.value = !!isCollapse.value
totalCollapse()
}
</script>
<style lang="scss">
.button {
font-size: 12px;
color: #666;
background: rgb(250,250,250);
width: 25px!important;
padding: 4px 8px !important;
border: 1px solid #eaeaea;
margin-right: 4px;
border-radius: 4px;
}
:deep .el-overlay {
background-color: hsla(0,0%,100%,.9) !important;
}
</style>