Files
Code-Create/src/components/main-header.vue

225 lines
4.8 KiB
Vue
Raw Normal View History

2026-05-14 14:23:32 +08:00
<template>
2026-05-14 14:38:12 +08:00
<header class="main-header" v-scroll-progress>
2026-05-15 17:31:43 +08:00
<a href="/" class="logo"><img src="../assets/logo-full.png" alt="code-create" /></a>
2026-05-14 14:38:12 +08:00
<div class="center-nav">
2026-05-15 17:31:43 +08:00
<div class="nav-item" v-for="item in navList" :key="item.name">
2026-05-18 11:13:48 +08:00
<down-menu :title="$t(item.name)" v-if="item.children">
2026-05-19 10:36:33 +08:00
<router-link :to="child.path" v-for="(child) in item.children" :key="child.name">
2026-05-18 10:39:52 +08:00
{{ $t(child.name) }}
2026-05-15 10:48:15 +08:00
</router-link>
2026-05-15 17:31:43 +08:00
</down-menu>
2026-05-18 11:13:48 +08:00
<router-link class="link hover-bottom-animation" :to="item.path" v-else>{{
$t(item.name)
}}</router-link>
2026-05-14 14:38:12 +08:00
</div>
</div>
<div class="right">
2026-05-18 10:39:52 +08:00
<down-menu :title="langList.find((v) => v.value === locale)?.label || 'English'">
<router-link
class="link"
2026-05-18 16:46:55 +08:00
:to="`/${item.value}${path}`"
2026-05-18 10:39:52 +08:00
v-for="item in langList"
:key="item.value"
2026-05-18 11:13:48 +08:00
v-show="item.value !== locale"
2026-05-18 10:39:52 +08:00
>
{{ item.label }}
</router-link>
2026-05-15 17:31:43 +08:00
</down-menu>
2026-05-18 11:13:48 +08:00
<router-link class="link" to="/my-account">
<span class="iconfont icon-tubiao-"></span>
2026-05-18 15:22:08 +08:00
<span v-if="token">{{ $t('MainHeader.MyAccount') }}</span>
<span v-else>{{ $t('MainHeader.LoginOrSignin') }}</span>
2026-05-18 11:13:48 +08:00
</router-link>
2026-05-14 14:38:12 +08:00
</div>
</header>
2026-05-14 14:23:32 +08:00
</template>
<script setup lang="ts">
2026-05-18 10:39:52 +08:00
import { ref, watch, computed } from 'vue'
2026-05-15 17:31:43 +08:00
import DownMenu from './down-menu.vue'
2026-05-18 10:39:52 +08:00
import { setLang, LangType } from '../lang'
import { useI18n } from 'vue-i18n'
const { locale } = useI18n()
2026-05-15 17:31:43 +08:00
import { useRoute } from 'vue-router'
2026-05-18 15:22:08 +08:00
import { useUserInfoStore } from '@/stores/userInfo'
const userInfoStore = useUserInfoStore()
const token = computed(() => userInfoStore.state.token)
2026-05-15 17:31:43 +08:00
const route = useRoute()
2026-05-18 10:39:52 +08:00
const lang = computed(() => route.params.lang)
2026-05-18 16:46:55 +08:00
const path = computed(() => route.path.replace(new RegExp(`^/${lang.value}/`), '/'))
2026-05-18 10:39:52 +08:00
if (lang.value) setLang(lang.value)
watch(lang, (newVal) => {
2026-05-18 16:46:55 +08:00
if (lang.value) setLang(newVal)
2026-05-18 10:39:52 +08:00
})
const langList = ref([
{
label: 'English',
value: LangType.en
},
{
label: '简体中文',
value: LangType.zhCn
},
{
label: '繁體中文',
value: LangType.zhTw
}
])
2026-05-15 17:31:43 +08:00
2026-05-19 10:36:33 +08:00
const navList:any = ref([
2026-05-14 14:38:12 +08:00
{
2026-05-18 10:39:52 +08:00
name: 'MainHeader.Home',
2026-05-15 17:31:43 +08:00
path: '/'
2026-05-14 14:38:12 +08:00
},
{
2026-05-18 11:13:48 +08:00
name: 'MainHeader.AboutUs',
2026-05-15 17:31:43 +08:00
path: '/about-us'
2026-05-14 14:38:12 +08:00
},
{
2026-05-18 11:13:48 +08:00
name: 'MainHeader.OurSolutions',
2026-05-15 17:31:43 +08:00
path: '',
2026-05-15 10:48:15 +08:00
children: [
{
2026-05-20 10:55:54 +08:00
name: 'MainHeader.AiDA',
2026-05-15 17:31:43 +08:00
path: '/aida'
2026-05-15 10:48:15 +08:00
},
{
2026-05-18 11:13:48 +08:00
name: 'MainHeader.Mixi',
2026-05-15 17:31:43 +08:00
path: '/mixi'
}
]
2026-05-14 14:38:12 +08:00
},
{
2026-05-18 11:13:48 +08:00
name: 'MainHeader.Communities',
2026-05-15 17:31:43 +08:00
path: '',
2026-05-15 10:48:15 +08:00
children: [
{
2026-05-18 11:13:48 +08:00
name: 'MainHeader.Events',
2026-05-15 17:31:43 +08:00
path: '/events'
2026-05-15 10:48:15 +08:00
},
{
2026-05-18 11:13:48 +08:00
name: 'MainHeader.UserStories',
2026-05-15 17:31:43 +08:00
path: '/user-stories'
2026-05-15 10:48:15 +08:00
},
{
2026-05-18 11:13:48 +08:00
name: 'MainHeader.HelpCentre',
2026-05-15 17:31:43 +08:00
path: '/help-centre'
}
]
2026-05-14 14:38:12 +08:00
},
{
2026-05-18 11:13:48 +08:00
name: 'MainHeader.Media',
2026-05-15 17:31:43 +08:00
path: '/media'
2026-05-14 14:38:12 +08:00
},
{
2026-05-18 11:13:48 +08:00
name: 'MainHeader.ContactUs',
2026-05-15 17:31:43 +08:00
path: '/contact-us'
}
])
2026-05-14 14:23:32 +08:00
</script>
<style lang="less" scoped>
.main-header {
position: fixed;
width: 100%;
2026-05-18 15:22:08 +08:00
height: var(--main-header-height, 85px);
2026-05-14 14:38:12 +08:00
padding: 15px 30px;
2026-05-14 14:39:55 +08:00
box-sizing: border-box;
2026-05-14 14:23:32 +08:00
top: 0;
left: 0;
z-index: 10000;
transition: background-color 0.2s linear;
&.active {
background-color: #0a0a0a;
}
2026-05-14 14:38:12 +08:00
display: flex;
justify-content: space-between;
align-items: center;
> .logo {
height: 100%;
width: auto;
2026-05-15 17:31:43 +08:00
img {
width: auto;
height: 100%;
}
2026-05-14 14:38:12 +08:00
}
> .center-nav {
display: flex;
align-items: center;
justify-content: center;
> .nav-item {
2026-05-15 10:48:15 +08:00
position: relative;
2026-05-18 11:13:48 +08:00
&:deep(> .down-menu > .title),
2026-05-15 10:48:15 +08:00
> .link {
2026-05-14 14:38:12 +08:00
margin: 0 14px;
color: #fff;
2026-05-18 11:13:48 +08:00
font-size: 14px;
2026-05-15 10:48:15 +08:00
text-decoration: none;
line-height: 37px;
display: inline-block;
2026-05-14 14:38:12 +08:00
}
2026-05-15 10:48:15 +08:00
> .child {
position: absolute;
bottom: 0;
visibility: hidden;
width: 250px;
height: auto;
padding: 10px 0;
box-sizing: border-box;
border: 1px solid #e1e1e1;
background-color: #fff;
display: flex;
flex-direction: column;
transform: translateY(calc(100% + 5px));
> .child-link {
display: inline-block;
padding: 10px 15px;
color: #000;
font-size: 15px;
text-decoration: none;
text-align: left;
&:hover {
opacity: 0.5;
}
}
}
&:hover > .child {
animation: child-show 0.2s linear both;
}
@keyframes child-show {
0% {
visibility: hidden;
// opacity: 0;
}
100% {
// opacity: 1;
transform: translateY(100%);
visibility: visible;
}
}
}
}
> .right {
display: flex;
align-items: center;
justify-content: center;
2026-05-18 11:13:48 +08:00
> .link {
2026-05-15 10:48:15 +08:00
margin: 0 14px;
color: #fff;
2026-05-18 11:13:48 +08:00
font-size: 14px;
2026-05-15 10:48:15 +08:00
text-decoration: none;
line-height: 37px;
display: inline-block;
2026-05-18 11:13:48 +08:00
display: flex;
align-items: center;
justify-content: center;
&:hover {
opacity: 0.8;
}
> .iconfont {
margin-right: 5px;
font-size: 22px;
}
2026-05-14 14:38:12 +08:00
}
}
2026-05-14 14:23:32 +08:00
}
2026-05-15 16:41:52 +08:00
</style>