refactor: 重构header
This commit is contained in:
parent
2338ded165
commit
958589edd0
@ -16,6 +16,7 @@ export { default as IconExpandRight } from '~icons/mdi/arrow-expand-right'
|
||||
export { default as IconMenuTable } from '~icons/mdi/table'
|
||||
export { default as IconMenuCollapse } from '~icons/mdi/format-indent-decrease'
|
||||
export { default as IconMenuExpand } from '~icons/mdi/format-indent-increase'
|
||||
export { default as IconExit } from '~icons/mdi/exit-to-app'
|
||||
|
||||
export { default as IconFullscreen } from '~icons/ant-design/fullscreen-outlined'
|
||||
export { default as IconFullscreenExit } from '~icons/ant-design/fullscreen-exit-outlined'
|
||||
|
@ -1,109 +0,0 @@
|
||||
<template>
|
||||
<div class="actions-wrapper">
|
||||
<n-icon mr20 size="18" style="cursor: pointer" @click="toggle">
|
||||
<IconFullscreenExit v-if="isFullscreen" />
|
||||
<IconFullscreen v-else />
|
||||
</n-icon>
|
||||
<n-dropdown :options="options" @select="handleSelect">
|
||||
<div class="avatar">
|
||||
<img :src="userStore.avatar" />
|
||||
<span>{{ userStore.name }}</span>
|
||||
</div>
|
||||
</n-dropdown>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { IconFullscreen, IconFullscreenExit } from '@/components/AppIcons'
|
||||
import { useUserStore } from '@/store/modules/user'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { resetRouter } from '@/router'
|
||||
import { usePermissionStore } from '@/store/modules/permission'
|
||||
import { NOT_FOUND_ROUTE } from '@/router/routes'
|
||||
import { useFullscreen } from '@vueuse/core'
|
||||
|
||||
const userStore = useUserStore()
|
||||
const router = useRouter()
|
||||
const { isFullscreen, toggle } = useFullscreen()
|
||||
|
||||
const options = [
|
||||
{
|
||||
label: '切换角色',
|
||||
key: 'switchRole',
|
||||
},
|
||||
{
|
||||
label: '退出登录',
|
||||
key: 'logout',
|
||||
},
|
||||
]
|
||||
|
||||
function handleSelect(key) {
|
||||
if (key === 'logout') {
|
||||
logout()
|
||||
} else if (key === 'switchRole') {
|
||||
switchRole()
|
||||
}
|
||||
}
|
||||
|
||||
function logout() {
|
||||
userStore.logout()
|
||||
$message.success('已退出登录')
|
||||
router.push({ path: '/login' })
|
||||
}
|
||||
|
||||
function switchRole() {
|
||||
const permissionStore = usePermissionStore()
|
||||
|
||||
const users = [
|
||||
{
|
||||
id: 1,
|
||||
name: '大脸怪(admin)',
|
||||
avatar: 'https://assets.qszone.com/images/avatar.jpg',
|
||||
email: 'Ronnie@123.com',
|
||||
role: ['admin'],
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '大脸怪(editor)',
|
||||
avatar: 'https://assets.qszone.com/images/avatar.jpg',
|
||||
email: 'Ronnie@123.com',
|
||||
role: ['editor'],
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: '访客(guest)',
|
||||
avatar: 'https://assets.qszone.com/images/avatar.jpg',
|
||||
role: [],
|
||||
},
|
||||
]
|
||||
|
||||
const switchUser = users[+userStore.userId % users.length]
|
||||
resetRouter()
|
||||
userStore.setUserInfo(switchUser)
|
||||
const accessRoutes = permissionStore.generateRoutes(switchUser.role)
|
||||
accessRoutes.forEach((route) => {
|
||||
!router.hasRoute(route.name) && router.addRoute(route)
|
||||
})
|
||||
router.addRoute(NOT_FOUND_ROUTE)
|
||||
$message.success(`${switchUser.name}`)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.actions-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.avatar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
img {
|
||||
width: 100%;
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
border-radius: 50%;
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -7,8 +7,7 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { useRouter } from 'vue-router'
|
||||
const router = useRouter()
|
||||
import { router } from '@/router'
|
||||
const { currentRoute } = router
|
||||
|
||||
function handleBreadClick(path) {
|
15
src/layout/components/header/components/FullScreen.vue
Normal file
15
src/layout/components/header/components/FullScreen.vue
Normal file
@ -0,0 +1,15 @@
|
||||
<template>
|
||||
<n-icon mr20 size="18" style="cursor: pointer" @click="toggle">
|
||||
<IconFullscreenExit v-if="isFullscreen" />
|
||||
<IconFullscreen v-else />
|
||||
</n-icon>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { IconFullscreen, IconFullscreenExit } from '@/components/AppIcons'
|
||||
import { useFullscreen } from '@vueuse/core'
|
||||
|
||||
const { isFullscreen, toggle } = useFullscreen()
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
15
src/layout/components/header/components/MenuCollapse.vue
Normal file
15
src/layout/components/header/components/MenuCollapse.vue
Normal file
@ -0,0 +1,15 @@
|
||||
<template>
|
||||
<n-icon size="20" style="cursor: pointer" @click="appStore.switchCollapsed">
|
||||
<IconMenuExpand v-if="appStore.collapsed" />
|
||||
<IconMenuCollapse v-else />
|
||||
</n-icon>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { IconMenuCollapse, IconMenuExpand } from '@/components/AppIcons'
|
||||
import { useAppStore } from '@/store/modules/app'
|
||||
|
||||
const appStore = useAppStore()
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
54
src/layout/components/header/components/UserAvatar.vue
Normal file
54
src/layout/components/header/components/UserAvatar.vue
Normal file
@ -0,0 +1,54 @@
|
||||
<template>
|
||||
<n-dropdown :options="options" @select="handleSelect">
|
||||
<div class="avatar">
|
||||
<img :src="userStore.avatar" />
|
||||
<span>{{ userStore.name }}</span>
|
||||
</div>
|
||||
</n-dropdown>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { router } from '@/router'
|
||||
import { useUserStore } from '@/store/modules/user'
|
||||
import { IconExit } from '@/components/AppIcons'
|
||||
import { renderIcon } from '@/utils/icon'
|
||||
|
||||
const userStore = useUserStore()
|
||||
|
||||
const options = [
|
||||
{
|
||||
label: '退出登录',
|
||||
key: 'logout',
|
||||
icon: renderIcon(IconExit, { size: '14px' }),
|
||||
},
|
||||
]
|
||||
|
||||
function handleSelect(key) {
|
||||
console.log(router)
|
||||
if (key === 'logout') {
|
||||
$dialog.confirm({
|
||||
content: '确认退出?',
|
||||
confirm() {
|
||||
userStore.logout()
|
||||
$message.success('已退出登录')
|
||||
router.push({ path: '/login' })
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.avatar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
img {
|
||||
width: 100%;
|
||||
width: 35px;
|
||||
height: 35px;
|
||||
border-radius: 50%;
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -1,24 +1,21 @@
|
||||
<template>
|
||||
<header class="header">
|
||||
<div class="h-left">
|
||||
<n-icon size="20" style="cursor: pointer" @click="appStore.switchCollapsed">
|
||||
<IconMenuExpand v-if="appStore.collapsed" />
|
||||
<IconMenuCollapse v-else />
|
||||
</n-icon>
|
||||
<MenuCollapse />
|
||||
<BreadCrumb ml-15 />
|
||||
</div>
|
||||
|
||||
<HeaderAction />
|
||||
<div class="h-right">
|
||||
<FullScreen />
|
||||
<UserAvatar />
|
||||
</div>
|
||||
</header>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { useAppStore } from '@/store/modules/app'
|
||||
import BreadCrumb from './BreadCrumb.vue'
|
||||
import HeaderAction from './HeaderAction.vue'
|
||||
import { IconMenuCollapse, IconMenuExpand } from '@/components/AppIcons'
|
||||
|
||||
const appStore = useAppStore()
|
||||
import BreadCrumb from './components/BreadCrumb.vue'
|
||||
import MenuCollapse from './components/MenuCollapse.vue'
|
||||
import FullScreen from './components/FullScreen.vue'
|
||||
import UserAvatar from './components/UserAvatar.vue'
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@ -32,5 +29,9 @@ const appStore = useAppStore()
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.h-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
Loading…
Reference in New Issue
Block a user