chat-pc/src/layout/component/Menu.vue

281 lines
5.3 KiB
Vue

<script lang="ts" setup>
import { reactive, computed, markRaw } from 'vue'
import { useRouter } from 'vue-router'
import { useUserStore, useSettingsStore, useTalkStore } from '@/store'
import { NPopover } from 'naive-ui'
import AccountCard from './AccountCard.vue'
import {
GithubOne,
SettingTwo,
Message,
NotebookAndPen,
People
// SmartOptimization
} from '@icon-park/vue-next'
defineProps({
index: {
type: Number,
default: 0
}
})
const userStore = useUserStore()
const talkStore = useTalkStore()
const router = useRouter()
const settingsStore = useSettingsStore()
const color = computed(() => {
return settingsStore.darkTheme ? '#ffffff' : '#333'
})
const menus = reactive([
{
link: '/message',
icon: markRaw(Message),
title: '消息',
hotspot: computed(() => talkStore.talkUnreadNum > 0)
},
{
link: '/contact',
icon: markRaw(People),
title: '通讯录',
hotspot: computed(() => userStore.isContactApply || userStore.isGroupApply)
},
{
link: '/note',
icon: markRaw(NotebookAndPen),
title: '笔记'
},
// {
// link: '/settings',
// icon: markRaw(SmartOptimization),
// title: 'Ai助手'
// },
{
link: '/settings',
icon: markRaw(SettingTwo),
title: '设置'
}
])
const onLogout = () => {
userStore.logoutLogin()
}
const onClickMenu = (menu) => {
if (menu.external) {
window.open(menu.link)
} else {
router.push(menu.link)
}
}
const isActive = (menu) => {
return router.currentRoute.value.path.indexOf(menu.link) >= 0
}
</script>
<template>
<section class="menu">
<header class="menu-header" :url="router.currentRoute.value.path">
<n-popover
placement="right"
trigger="hover"
:raw="true"
style="margin-left: 16px; border-radius: 8px; overflow: hidden"
>
<template #trigger>
<im-avatar
class="logo"
:size="35"
:src="userStore.avatar"
:username="userStore.nickname"
/>
</template>
<AccountCard />
</n-popover>
<span class="online-status" :class="{ online: userStore.online }">
{{ userStore.online ? '在线' : '连接中...' }}
</span>
</header>
<main class="menu-main">
<div
v-for="nav in menus"
:key="nav.link"
:class="{
'menu-items': true,
active: isActive(nav)
}"
@click="onClickMenu(nav)"
>
<!-- 消息提示 -->
<div class="hotspot" v-if="nav.hotspot" />
<p>
<component
:is="nav.icon"
:theme="isActive(nav) ? 'filled' : 'outline'"
:fill="isActive(nav) ? '#1890ff' : color"
:strokeWidth="2"
:size="22"
/>
</p>
<span>{{ nav.title }}</span>
</div>
</main>
<footer class="menu-footer">
<div>
<a class="pointer" href="https://github.com/gzydong/IM" target="_blank">
<github-one theme="outline" size="22" :fill="color" :strokeWidth="2" />
</a>
</div>
<div @click="onLogout" class="pointer">退出</div>
</footer>
</section>
</template>
<style lang="less" scoped>
.menu {
height: 100%;
width: 100%;
display: flex;
flex-direction: column;
box-sizing: border-box;
.menu-header {
height: 90px;
width: 100%;
flex-shrink: 0;
display: flex;
align-items: center;
flex-direction: column;
padding-top: 18px;
box-sizing: border-box;
cursor: pointer;
.online-status {
margin-top: 5px;
font-size: 13px;
font-weight: 300;
color: rgb(185, 181, 181);
&.online {
color: #65c468;
}
}
}
.menu-main {
flex: auto;
width: 100%;
overflow: hidden;
}
.menu-footer {
height: 90px;
width: 100%;
div {
height: 38px;
display: flex;
align-items: center;
justify-content: center;
}
}
}
.menu-items {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
user-select: none;
cursor: pointer;
border-radius: 3px;
font-size: 12px;
width: 54px;
height: 54px;
margin: 8px auto;
border-radius: 10px;
// &.active {
// &::after {
// position: absolute;
// content: '';
// width: 0;
// height: 0;
// right: -8px;
// border-top: 8px solid transparent;
// border-bottom: 8px solid transparent;
// border-right: 8px solid #ffffff;
// }
// }
.hotspot {
width: 5px;
height: 5px;
--hotspot: #ff1e1e;
background: var(--hotspot);
display: inline-block;
border-radius: 5px;
position: absolute;
right: 5px;
top: 9px;
animation: notifymove 3s infinite;
animation-direction: alternate;
-webkit-animation: notifymove 3s infinite;
}
}
@keyframes notifymove {
0% {
background: var(--hotspot);
}
25% {
background: transparent;
}
50% {
background: var(--hotspot);
}
75% {
background: transparent;
}
100% {
background: var(--hotspot);
}
}
@-webkit-keyframes notifymove {
0% {
background: #ff1e1e;
}
25% {
background: transparent;
}
50% {
background: #ff1e1e;
}
75% {
background: transparent;
}
100% {
background: #ff1e1e;
}
}
</style>