Compare commits

..

No commits in common. "5defd0e4d0408a713d3828d2de23dd56fd7a33e0" and "bb108d7ef700809889b806a1149d00be95e2d50c" have entirely different histories.

13 changed files with 325 additions and 499 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

View File

@ -5,15 +5,14 @@
:class="{ 'header-scrolled': isScrolled }" :class="{ 'header-scrolled': isScrolled }"
> >
<div class="header-container"> <div class="header-container">
<div class="logo" @click="handleToHome"> <div class="logo">
<NImage width="160" height="50" :src="FiEELogo" preview-disabled /> <NImage width="108" height="33" :src="FiEELogo" preview-disabled />
</div> </div>
<div class="header-menu"> <div class="header-menu">
<NMenu <NMenu
mode="horizontal" mode="horizontal"
:options="menuOptions" :options="menuOptions"
:inverted="isScrolled" :inverted="isScrolled"
v-model:value="selectedKey"
@update:value="handleMenuSelect" @update:value="handleMenuSelect"
/> />
</div> </div>
@ -22,21 +21,15 @@
</template> </template>
<script setup> <script setup>
import FiEELogo from '@/assets/image/header/logo.png' import FiEELogo from "@/assets/images/header/logo.png";
import { ref, onMounted, onUnmounted } from 'vue' import { ref, onMounted, onUnmounted } from "vue";
import { NMenu, NLayoutHeader, NImage } from 'naive-ui' import { NMenu, NLayoutHeader, NImage } from "naive-ui";
import { useI18n } from 'vue-i18n' import { useI18n } from "vue-i18n";
import { useRouter } from 'vue-router' import { useRouter } from "vue-router";
import { useHeaderMenuConfig } from '@/config/headerMenuConfig' const { t } = useI18n();
const router = useRouter();
const { t } = useI18n() const isScrolled = ref(false);
const router = useRouter()
// 使
const menuOptions = useHeaderMenuConfig()
const selectedKey = ref(null)
const isScrolled = ref(false)
// //
function findMenuOptionByKey(options, key) { function findMenuOptionByKey(options, key) {
@ -58,6 +51,107 @@ const handleMenuSelect = (key) => {
} }
}; };
//
const menuOptions = [
{
label: t("header_menu.corporate_information.title"),
key: "corporate_information",
children: [
{
label: t("header_menu.corporate_information.company_overview"),
key: "company_overview",
},
{
label: t("header_menu.corporate_information.business_introduction"),
key: "business_introduction",
},
{
label: t("header_menu.corporate_information.management"),
key: "management",
},
{
label: t("header_menu.corporate_information.board_of_directors"),
key: "board_of_directors",
},
{
label: t("header_menu.corporate_information.committee_appointments"),
key: "committee_appointments",
},
{
label: t("header_menu.corporate_information.governance"),
key: "governance",
},
{
label: t("header_menu.corporate_information.corporate_video"),
key: "corporate_video",
},
],
},
{
label: t("header_menu.financial_information.title"),
key: "financial_information",
children: [
{
label: t("header_menu.financial_information.sec_filings"),
key: "sec_filings",
href: "/secfilings",
},
{
label: t("header_menu.financial_information.quarterly_results"),
key: "quarterly_results",
href: "/quarterlyresults",
},
],
},
{
label: t("header_menu.stock_information.title"),
key: "stock_information",
children: [
{
label: t("header_menu.stock_information.stock_quote"),
key: "stock_quote",
},
{
label: t("header_menu.stock_information.historic_stock_price"),
key: "historic_stock_price",
},
{
label: t("header_menu.stock_information.investment_calculator"),
key: "investment_calculator",
},
],
},
{
label: t("header_menu.news_releases.title"),
key: "news_releases",
children: [
{
label: t("header_menu.news_releases.press_releases"),
key: "press_releases",
href: "/new-releases",
},
{
label: t("header_menu.news_releases.events_calendar"),
key: "events_calendar",
},
],
},
{
label: t("header_menu.investor_resources.title"),
key: "investor_resources",
children: [
{
label: t("header_menu.investor_resources.ir_contacts"),
key: "ir_contacts",
},
{
label: t("header_menu.investor_resources.email_alerts"),
key: "email_alerts",
},
],
},
];
// //
const handleScroll = () => { const handleScroll = () => {
//100pxheader //100pxheader
@ -69,20 +163,13 @@ onMounted(() => {
}); });
onUnmounted(() => { onUnmounted(() => {
window.removeEventListener('scroll', handleScroll) window.removeEventListener("scroll", handleScroll);
}) });
//
const handleToHome = () => {
router.push('/')
selectedKey.value = null //
}
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.custom-header { .custom-header {
--header-height: 80px; --header-height: 80px;
--primary-color: #8B59F7;
position: fixed; position: fixed;
top: 0; top: 0;
left: 0; left: 0;
@ -94,15 +181,14 @@ const handleToHome = () => {
&.header-scrolled { &.header-scrolled {
background: rgba(255, 255, 255, 0.95); background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(8px);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
} }
} }
.header-container { .header-container {
max-width: 1700px; max-width: 1200px;
margin: 0 auto; margin: 0 auto;
padding: 0 40px; padding: 0 20px;
height: 100%; height: 100%;
display: flex; display: flex;
align-items: center; align-items: center;
@ -111,115 +197,9 @@ const handleToHome = () => {
.logo { .logo {
flex-shrink: 0; flex-shrink: 0;
cursor: pointer;
transition: transform 0.3s ease;
margin-right: 100px;
&:hover {
transform: scale(1.05);
}
&:active {
transform: scale(0.98);
}
} }
.header-menu { .header-menu {
display: block; display: block;
flex: 1;
:deep(.n-menu) {
background: transparent;
justify-content: flex-end;
}
:deep(.n-menu-item) {
position: relative;
margin: 0 20px;
transition: all 0.3s ease;
font-weight: 700;
font-size: 16px;
min-width: 120px;
text-align: center;
&::after {
content: '';
position: absolute;
bottom: 0;
left: 50%;
width: 0;
height: 2px;
background: var(--primary-color);
transition: all 0.3s ease;
transform: translateX(-50%);
opacity: 0;
border-radius: 2px;
}
&:hover {
&::after {
width: 80px;
height: 3px;
opacity: 1;
}
}
//
&.n-menu-item--selected {
&::after {
width: 40px;
opacity: 1;
}
}
}
//
:deep(.n-submenu) {
.n-submenu-children {
backdrop-filter: blur(16px);
background: rgba(255, 255, 255, 0.9);
border-radius: 12px;
padding: 8px 0;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
transform-origin: top;
animation: dropDown 0.3s ease;
.n-menu-item {
position: relative;
overflow: hidden;
&::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: var(--primary-color);
transform: translateX(-100%);
transition: transform 0.3s ease;
opacity: 0.1;
z-index: -1;
}
&:hover {
&::before {
transform: translateX(0);
}
}
}
}
}
}
@keyframes dropDown {
from {
opacity: 0;
transform: translateY(-10px) scale(0.95);
}
to {
opacity: 1;
transform: translateY(0) scale(1);
}
} }
</style> </style>

View File

@ -5,19 +5,16 @@
:class="{ 'header-scrolled': isScrolled }" :class="{ 'header-scrolled': isScrolled }"
> >
<div class="header-container"> <div class="header-container">
<div class="logo" @click="handleToHome"> <div class="logo">
<NImage <NImage
style="width: 108px; height: 33px; max-width: 100%" style="width: 108px; height: 33px; max-width: 100%"
:src="FiEELogo" :src="FiEELogo"
preview-disabled preview-disabled
/> />
</div> </div>
<div class="menu-btn" :class="{ 'menu-open': showMenu }" @click="toggleMenu"> <div class="menu-btn" @click="toggleMenu">
<n-icon size="28" class="menu-icon menu-icon-menu"> <n-icon size="28">
<menu-sharp /> <menu-outline />
</n-icon>
<n-icon size="28" class="menu-icon menu-icon-close">
<close-sharp />
</n-icon> </n-icon>
</div> </div>
</div> </div>
@ -30,7 +27,6 @@
:inverted="isScrolled" :inverted="isScrolled"
class="mobile-menu" class="mobile-menu"
accordion accordion
v-model:value="selectedKey"
@update:value="handleMenuSelect" @update:value="handleMenuSelect"
/> />
</div> </div>
@ -38,20 +34,17 @@
</template> </template>
<script setup> <script setup>
import FiEELogo from '@/assets/image/header/logo.png' import FiEELogo from "@/assets/images/header/logo.png";
import { ref, onMounted, onUnmounted } from 'vue' import { ref, onMounted, onUnmounted } from "vue";
import { NMenu, NLayoutHeader, NImage, NIcon } from 'naive-ui' import { NMenu, NLayoutHeader, NImage, NIcon } from "naive-ui";
import { MenuSharp, CloseSharp } from '@vicons/ionicons5' import { MenuOutline } from "@vicons/ionicons5";
import { useI18n } from 'vue-i18n' import { useI18n } from "vue-i18n";
import { useRouter } from 'vue-router' import { useRouter } from "vue-router";
import { useHeaderMenuConfig } from '@/config/headerMenuConfig' const { t } = useI18n();
const router = useRouter();
const { t } = useI18n() const isScrolled = ref(false);
const router = useRouter() const showMenu = ref(false);
const isScrolled = ref(false)
const showMenu = ref(false)
const selectedKey = ref(null)
const toggleMenu = () => { const toggleMenu = () => {
showMenu.value = !showMenu.value; showMenu.value = !showMenu.value;
@ -81,8 +74,106 @@ const handleMenuSelect = (key) => {
} }
}; };
// 使 //
const menuOptions = useHeaderMenuConfig() const menuOptions = [
{
label: t("header_menu.corporate_information.title"),
key: "corporate_information",
children: [
{
label: t("header_menu.corporate_information.company_overview"),
key: "company_overview",
},
{
label: t("header_menu.corporate_information.business_introduction"),
key: "business_introduction",
},
{
label: t("header_menu.corporate_information.management"),
key: "management",
},
{
label: t("header_menu.corporate_information.board_of_directors"),
key: "board_of_directors",
},
{
label: t("header_menu.corporate_information.committee_appointments"),
key: "committee_appointments",
},
{
label: t("header_menu.corporate_information.governance"),
key: "governance",
},
{
label: t("header_menu.corporate_information.corporate_video"),
key: "corporate_video",
},
],
},
{
label: t("header_menu.financial_information.title"),
key: "financial_information",
children: [
{
label: t("header_menu.financial_information.sec_filings"),
key: "sec_filings",
href: "/secfilings",
},
{
label: t("header_menu.financial_information.quarterly_results"),
key: "quarterly_results",
href: "/quarterlyresults",
},
],
},
{
label: t("header_menu.stock_information.title"),
key: "stock_information",
children: [
{
label: t("header_menu.stock_information.stock_quote"),
key: "stock_quote",
},
{
label: t("header_menu.stock_information.historic_stock_price"),
key: "historic_stock_price",
},
{
label: t("header_menu.stock_information.investment_calculator"),
key: "investment_calculator",
},
],
},
{
label: t("header_menu.news_releases.title"),
key: "news_releases",
children: [
{
label: t("header_menu.news_releases.press_releases"),
key: "press_releases",
href: "/new-releases",
},
{
label: t("header_menu.news_releases.events_calendar"),
key: "events_calendar",
},
],
},
{
label: t("header_menu.investor_resources.title"),
key: "investor_resources",
children: [
{
label: t("header_menu.investor_resources.ir_contacts"),
key: "ir_contacts",
},
{
label: t("header_menu.investor_resources.email_alerts"),
key: "email_alerts",
},
],
},
];
// //
const handleScroll = () => { const handleScroll = () => {
@ -95,15 +186,8 @@ onMounted(() => {
}); });
onUnmounted(() => { onUnmounted(() => {
window.removeEventListener('scroll', handleScroll) window.removeEventListener("scroll", handleScroll);
}) });
//
const handleToHome = () => {
router.push('/')
selectedKey.value = null //
showMenu.value = false //
}
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@ -151,40 +235,17 @@ const handleToHome = () => {
align-items: center; align-items: center;
justify-content: center; justify-content: center;
cursor: pointer; cursor: pointer;
color: #465564;
font-size: 75px; font-size: 75px;
padding: 40px 70px; padding: 40px 70px;
border-radius: 30px; border-radius: 30px;
background: transparent; background: #f7f8fa;
box-shadow: 0 5px 20px rgba(0, 0, 0, 0.03);
user-select: none; user-select: none;
transition: background 0.2s; transition: background 0.2s;
position: relative; }
.menu-btn:active {
.menu-icon { background: #ececec;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%) rotate(0deg);
opacity: 1;
transition:
opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1),
transform 0.4s cubic-bezier(0.4, 0, 0.2, 1);
pointer-events: none;
}
.menu-icon-close {
opacity: 0;
transform: translate(-50%, -50%) rotate(-90deg) scale(0.8);
}
&.menu-open {
.menu-icon-menu {
opacity: 0;
transform: translate(-50%, -50%) rotate(90deg) scale(0.8);
}
.menu-icon-close {
opacity: 1;
transform: translate(-50%, -50%) rotate(0deg) scale(1);
}
}
} }
.mobile-menu-wrapper { .mobile-menu-wrapper {
@ -198,9 +259,6 @@ const handleToHome = () => {
padding: 40px 0 80px 0; padding: 40px 0 80px 0;
max-height: 1500px; max-height: 1500px;
overflow-y: auto; overflow-y: auto;
:deep(.n-menu-item) {
font-weight: 600;
}
} }
.fade-slide-enter-active, .fade-slide-enter-active,

View File

@ -1,105 +0,0 @@
import { useI18n } from 'vue-i18n'
export const useHeaderMenuConfig = () => {
const { t } = useI18n()
return [
{
label: t('header_menu.corporate_information.title'),
key: 'corporate_information',
children: [
{
label: t('header_menu.corporate_information.company_overview'),
key: 'company_overview',
},
{
label: t('header_menu.corporate_information.business_introduction'),
key: 'business_introduction',
},
{
label: t('header_menu.corporate_information.management'),
key: 'management',
},
{
label: t('header_menu.corporate_information.board_of_directors'),
key: 'board_of_directors',
},
{
label: t('header_menu.corporate_information.committee_appointments'),
key: 'committee_appointments',
},
{
label: t('header_menu.corporate_information.governance'),
key: 'governance',
},
{
label: t('header_menu.corporate_information.corporate_video'),
key: 'corporate_video',
},
],
},
{
label: t('header_menu.financial_information.title'),
key: 'financial_information',
children: [
{
label: t('header_menu.financial_information.sec_filings'),
key: 'sec_filings',
href: "/secfilings",
},
{
label: t('header_menu.financial_information.quarterly_results'),
key: 'quarterly_results',
href: "/quarterlyresults",
},
],
},
{
label: t('header_menu.stock_information.title'),
key: 'stock_information',
children: [
{
label: t('header_menu.stock_information.stock_quote'),
key: 'stock_quote',
},
{
label: t('header_menu.stock_information.historic_stock_price'),
key: 'historic_stock_price',
},
{
label: t('header_menu.stock_information.investment_calculator'),
key: 'investment_calculator',
},
],
},
{
label: t('header_menu.news_releases.title'),
key: 'news_releases',
children: [
{
label: t('header_menu.news_releases.press_releases'),
key: 'press_releases',
href: '/press-releases',
},
{
label: t('header_menu.news_releases.events_calendar'),
key: 'events_calendar',
},
],
},
{
label: t('header_menu.investor_resources.title'),
key: 'investor_resources',
children: [
{
label: t('header_menu.investor_resources.ir_contacts'),
key: 'ir_contacts',
},
{
label: t('header_menu.investor_resources.email_alerts'),
key: 'email_alerts',
},
],
},
]
}

View File

@ -1,83 +1,77 @@
// router/index.js // router/index.js
import { createRouter, createWebHistory } from 'vue-router' import { createRouter, createWebHistory } from 'vue-router';
import { setupRouterGuards } from './router-guards' import { setupRouterGuards } from './router-guards';
const routes = [ const routes = [
{ {
path: '/', path: '/',
name: 'index',
component: () => import('@/views/index/index.vue'),
// beforeEnter: (to, from, next) => {
// localStorage.clear()
// next()
// }
children: [
{
path: 'home',
name: 'home', name: 'home',
component: () => import('@/views/home/index.vue'), component: () => import('@/views/home/index.vue'),
}, // beforeEnter: (to, from, next) => {
{
path: 'press-releases', // localStorage.clear()
name: 'press-releases', // next()
component: () => import('@/views/press-releases/index.vue'), // }
}, children: [
{ {
path: '/quarterlyresults', path: 'new-releases',
name: 'QuarterlyResults', name: 'new-releases',
component: () => component: () => import('@/views/new-releases/index.vue')
import('@/views/financialinformation/quarterlyresults/index.vue'), },
}, {
{ path: '/quarterlyresults',
path: '/secfilings', name: 'QuarterlyResults',
name: 'SecFilings', component: () => import('@/views/financialinformation/quarterlyresults/index.vue'),
component: () => },
import('@/views/financialinformation/secfilings/index.vue'), {
}, path: '/secfilings',
], name: 'SecFilings',
}, component: () => import('@/views/financialinformation/secfilings/index.vue'),
{ },
path: '/contacts', ]
name: 'contacts', },
component: () => import('@/views/contacts/index.vue'), {
}, path: '/contacts',
// { name: 'contacts',
// path: '/companyprofil', component: () => import('@/views/contacts/index.vue'),
// name: 'Companyprofil', },
// component: () => import('@/views/companyprofil/index.vue'), // {
// }, // path: '/companyprofil',
// { // name: 'Companyprofil',
// path: '/companyprofildetail', // component: () => import('@/views/companyprofil/index.vue'),
// name: 'Companyprofildetail', // },
// component: () => import('@/views/companyprofildetail/index.vue'), // {
// }, // path: '/companyprofildetail',
// { // name: 'Companyprofildetail',
// path: '/businessintroduction', // component: () => import('@/views/companyprofildetail/index.vue'),
// name: 'Businessintroduction', // },
// component: () => import('@/views/businessintroduction/index.vue'), // {
// }, // path: '/businessintroduction',
// { // name: 'Businessintroduction',
// path: '/investor', // component: () => import('@/views/businessintroduction/index.vue'),
// name: 'Investor', // },
// component: () => import('@/views/investor/index.vue'), // {
// }, // path: '/investor',
// { // name: 'Investor',
// path: '/investorhandbook', // component: () => import('@/views/investor/index.vue'),
// name: 'Investorhandbook', // },
// component: () => import('@/views/investorhandbook/index.vue'), // {
// }, // path: '/investorhandbook',
] // name: 'Investorhandbook',
// component: () => import('@/views/investorhandbook/index.vue'),
// },
];
const router = createRouter({ const router = createRouter({
history: createWebHistory(), history: createWebHistory(),
routes, routes
}) });
router.beforeEach((to, from, next) => { router.beforeEach((to, from, next) => {
if (to.meta?.title) { if (to.meta?.title) {
document.title = to.meta.title document.title = to.meta.title;
} }
next() next()
}) });
setupRouterGuards(router) setupRouterGuards(router);
export default router export default router;

View File

@ -7,10 +7,15 @@ import customFooter from '@/components/customFooter/index.vue'
</script> </script>
<template> <template>
<header className="header"> <!-- <header className="header">
1920 1920
</header> </header> -->
<main ref="main"></main> <!-- <main ref="main"></main> -->
<customHeader />
<div style="margin: 80px 0;">
<router-view />
</div>
<customFooter />
</template> </template>
<style scoped lang="scss"> <style scoped lang="scss">

View File

@ -7,10 +7,16 @@ import customFooter from '@/components/customFooter/index.vue'
</script> </script>
<template> <template>
<header className="header"> <!-- <header className="header">
375 375
</header> </header> -->
<main ref="main"></main> <!-- <main ref="main"></main> -->
<customHeader />
<div style="margin: 80px 0;">
<router-view />
</div>
<customFooter />
</template> </template>
<style scoped lang="scss"> <style scoped lang="scss">

View File

@ -1,22 +0,0 @@
<script setup>
import size1920 from '@/views/index/size1920/index.vue'
import size375 from '@/views/index/size375/index.vue'
import { computed } from 'vue'
import { useWindowSize } from '@vueuse/core'
const { width } = useWindowSize()
const viewComponent = computed(() => {
const viewWidth = width.value
if (viewWidth <= 450) {
return size375
} else if (viewWidth <= 1920 || viewWidth > 1920) {
return size1920
}
})
</script>
<template>
<component :is="viewComponent" />
</template>
<style scoped lang="scss"></style>

View File

@ -1,21 +0,0 @@
<script setup>
import { NCarousel, NDivider, NMarquee, NPopselect } from 'naive-ui'
import { onUnmounted, ref, watch, onMounted, computed } from 'vue'
import customHeader from '@/components/customHeader/index.vue'
import customFooter from '@/components/customFooter/index.vue'
</script>
<template>
<customHeader></customHeader>
<div style="margin: 80px 0;">
<router-view />
</div>
<customFooter></customFooter>
</template>
<style scoped lang="scss">
main {
padding: var(--header-height, 80px) 0 0;
}
</style>

View File

@ -1,26 +0,0 @@
<script setup>
import { NCarousel, NDivider, NMarquee, NPopselect } from 'naive-ui'
import { onUnmounted, ref, watch, onMounted, computed } from 'vue'
import customHeader from '@/components/customHeader/index.vue'
import customFooter from '@/components/customFooter/index.vue'
</script>
<template>
<!-- <header className="header">
375
</header> -->
<!-- <main ref="main"></main> -->
<customHeader />
<div style="margin: 80px 0;">
<router-view />
</div>
<customFooter />
</template>
<style scoped lang="scss">
main {
padding: var(--header-height, 80px) 0 0;
}
</style>

View File

@ -1,23 +0,0 @@
<template>
<div class="new-releases-page">
<component :is="viewComponent" />
</div>
</template>
<script setup>
import size1920 from '@/views/press-releases/size1920/index.vue'
import size375 from '@/views/press-releases/size375/index.vue'
import { computed } from 'vue'
import { useWindowSize } from '@vueuse/core'
const { width } = useWindowSize()
const viewComponent = computed(() => {
const viewWidth = width.value
if (viewWidth <= 450) {
return size375
} else if (viewWidth <= 1920 || viewWidth > 1920) {
return size1920
}
})
</script>
<style scoped lang="scss"></style>

View File

@ -1,10 +0,0 @@
<template>
<div class="new-releases-page">
<customDefaultPage></customDefaultPage>
</div>
</template>
<script setup>
import customDefaultPage from '@/components/customDefaultPage/index.vue'
</script>
<style scoped lang="scss"></style>

View File

@ -1,10 +0,0 @@
<template>
<div class="new-releases-page">
<customDefaultPage></customDefaultPage>
</div>
</template>
<script setup>
import customDefaultPage from '@/components/customDefaultPage/index.vue'
</script>
<style scoped lang="scss"></style>