Merge branch 'main' of http://172.16.100.91:3000/scout666/fiee-official-website
# Conflicts: # src/router/index.js
This commit is contained in:
commit
6d1d22171a
@ -13,6 +13,8 @@
|
||||
"dependencies": {
|
||||
"@fingerprintjs/fingerprintjs": "^4.4.3",
|
||||
"@unocss/reset": "^0.61.9",
|
||||
"@vicons/ionicons5": "^0.13.0",
|
||||
"@vicons/utils": "^0.1.4",
|
||||
"axios": "^1.7.3",
|
||||
"cnjm-postcss-px-to-viewport": "^1.0.1",
|
||||
"echarts": "^5.6.0",
|
||||
|
@ -14,6 +14,12 @@ importers:
|
||||
'@unocss/reset':
|
||||
specifier: ^0.61.9
|
||||
version: 0.61.9
|
||||
'@vicons/ionicons5':
|
||||
specifier: ^0.13.0
|
||||
version: 0.13.0
|
||||
'@vicons/utils':
|
||||
specifier: ^0.1.4
|
||||
version: 0.1.4(vue@3.4.35)
|
||||
axios:
|
||||
specifier: ^1.7.3
|
||||
version: 1.7.3
|
||||
@ -1341,6 +1347,9 @@ packages:
|
||||
'@types/minimatch@5.1.2':
|
||||
resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==}
|
||||
|
||||
'@types/node@14.14.45':
|
||||
resolution: {integrity: sha512-DssMqTV9UnnoxDWu959sDLZzfvqCF0qDNRjaWeYSui9xkFe61kKo4l1TWNTQONpuXEm+gLMRvdlzvNHBamzmEw==}
|
||||
|
||||
'@types/node@22.13.10':
|
||||
resolution: {integrity: sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw==}
|
||||
|
||||
@ -1450,6 +1459,14 @@ packages:
|
||||
peerDependencies:
|
||||
vue: ^3.0.0
|
||||
|
||||
'@vicons/ionicons5@0.13.0':
|
||||
resolution: {integrity: sha512-zvZKBPjEXKN7AXNo2Na2uy+nvuv6SP4KAMQxpKL2vfHMj0fSvuw7JZcOPCjQC3e7ayssKnaoFVAhbYcW6v41qQ==}
|
||||
|
||||
'@vicons/utils@0.1.4':
|
||||
resolution: {integrity: sha512-OHI19qVNN6i+uPQ+Y3f2s0dUxwsYnOCcKBW7XOU4yXXO1aU3ZoKpblCc3+4N0qmgoJs5rWKRAaMisipqEXJwAg==}
|
||||
peerDependencies:
|
||||
vue: ^3.0.6
|
||||
|
||||
'@vitejs/plugin-legacy@5.4.1':
|
||||
resolution: {integrity: sha512-kee0l7dVevCNs1l3u2PnihVunvQ0WTJL2UJ/siQGD3Iht546mR9NO16tCv32uCP6lcGO1QDLqlPqInJtV1FE7A==}
|
||||
engines: {node: ^18.0.0 || >=20.0.0}
|
||||
@ -1505,6 +1522,9 @@ packages:
|
||||
'@vueuse/shared@10.11.0':
|
||||
resolution: {integrity: sha512-fyNoIXEq3PfX1L3NkNhtVQUSRtqYwJtJg+Bp9rIzculIZWHTkKSysujrOk2J+NrRulLTQH9+3gGSfYLWSEWU1A==}
|
||||
|
||||
'@xicons/utils@0.1.4':
|
||||
resolution: {integrity: sha512-uXxKDLz9abr80yJC05XSTq6wlyFcdW+N/1IYJkeHjzzXVc4VQ0sEYMoMMTjAH7HQBOyOkzOB4pf5NGF72lwa8Q==}
|
||||
|
||||
acorn@8.12.1:
|
||||
resolution: {integrity: sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==}
|
||||
engines: {node: '>=0.4.0'}
|
||||
@ -1819,6 +1839,9 @@ packages:
|
||||
peerDependencies:
|
||||
postcss: ^8.4
|
||||
|
||||
css-render@0.13.9:
|
||||
resolution: {integrity: sha512-n3C4ZH59rveBrUlAD7n0Ze9/gUMKa4dlH1C9CWKpGcIHR/xRcIVXzBGy1iw8WWq2ySmn2/ZqOpySQNAK5Pb6sw==}
|
||||
|
||||
css-render@0.15.14:
|
||||
resolution: {integrity: sha512-9nF4PdUle+5ta4W5SyZdLCCmFd37uVimSjg1evcTqKJCyvCEEj12WKzOSBNak6r4im4J4iYXKH1OWpUV5LBYFg==}
|
||||
|
||||
@ -5147,6 +5170,8 @@ snapshots:
|
||||
|
||||
'@types/minimatch@5.1.2': {}
|
||||
|
||||
'@types/node@14.14.45': {}
|
||||
|
||||
'@types/node@22.13.10':
|
||||
dependencies:
|
||||
undici-types: 6.20.0
|
||||
@ -5329,6 +5354,13 @@ snapshots:
|
||||
dependencies:
|
||||
vue: 3.4.35
|
||||
|
||||
'@vicons/ionicons5@0.13.0': {}
|
||||
|
||||
'@vicons/utils@0.1.4(vue@3.4.35)':
|
||||
dependencies:
|
||||
'@xicons/utils': 0.1.4
|
||||
vue: 3.4.35
|
||||
|
||||
'@vitejs/plugin-legacy@5.4.1(terser@5.31.3)(vite@5.3.5(@types/node@22.13.10)(sass@1.77.8)(terser@5.31.3))':
|
||||
dependencies:
|
||||
'@babel/core': 7.25.2
|
||||
@ -5424,6 +5456,10 @@ snapshots:
|
||||
- '@vue/composition-api'
|
||||
- vue
|
||||
|
||||
'@xicons/utils@0.1.4':
|
||||
dependencies:
|
||||
css-render: 0.13.9
|
||||
|
||||
acorn@8.12.1: {}
|
||||
|
||||
agent-base@7.1.1:
|
||||
@ -5782,6 +5818,12 @@ snapshots:
|
||||
dependencies:
|
||||
postcss: 8.4.40
|
||||
|
||||
css-render@0.13.9:
|
||||
dependencies:
|
||||
'@emotion/hash': 0.8.0
|
||||
'@types/node': 14.14.45
|
||||
csstype: 3.0.11
|
||||
|
||||
css-render@0.15.14:
|
||||
dependencies:
|
||||
'@emotion/hash': 0.8.0
|
||||
|
15
src/App.vue
15
src/App.vue
@ -1,10 +1,10 @@
|
||||
<script setup>
|
||||
import { ref } from "vue";
|
||||
import { ref } from 'vue'
|
||||
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { NConfigProvider, NDropdown } from "naive-ui";
|
||||
const { locale } = useI18n();
|
||||
const primaryColor = ref("#2B69A1");
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { NConfigProvider, NDropdown } from 'naive-ui'
|
||||
const { locale } = useI18n()
|
||||
const primaryColor = ref('#8B59F7')
|
||||
const themeOverrides = ref({
|
||||
common: {
|
||||
primaryColorPressed: primaryColor,
|
||||
@ -15,10 +15,7 @@ const themeOverrides = ref({
|
||||
primaryColor: primaryColor,
|
||||
primaryColorHover: primaryColor,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
BIN
src/assets/file/2025 Q1 Quarterly Results.pdf
Normal file
BIN
src/assets/file/2025 Q1 Quarterly Results.pdf
Normal file
Binary file not shown.
BIN
src/assets/image/bg-375.png
Normal file
BIN
src/assets/image/bg-375.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 156 KiB |
BIN
src/assets/image/bg.png
Normal file
BIN
src/assets/image/bg.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 272 KiB |
1
src/assets/image/download.svg
Normal file
1
src/assets/image/download.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="19" height="19" viewBox="0 0 19 19"><defs><style>.a{fill:#fff;stroke:#707070;}.b{clip-path:url(#a);}.c{fill:#2c2c2c;}</style><clipPath id="a"><rect class="a" width="19" height="19" transform="translate(333.601 660.601)"/></clipPath></defs><g class="b" transform="translate(-333.601 -660.601)"><g transform="translate(333.591 664.087)"><path class="c" d="M19.237,22.964H2.325a.922.922,0,0,1-.922-.922V15.408a.922.922,0,1,1,1.844,0V21.12H18.315V15.408a.922.922,0,1,1,1.844,0v6.634A.922.922,0,0,1,19.237,22.964Z" transform="translate(-1.403 -7.061)"/><path class="c" d="M12.451,13.284c-.509,0-.922-.311-.922-.694V1.332c0-.384.413-.694.922-.694s.922.311.922.694V12.589C13.373,12.973,12.96,13.284,12.451,13.284Z" transform="translate(-3.073 -0.638)"/><path class="c" d="M11.833,20.248a.922.922,0,0,1-.748-.384L7.956,15.51a.922.922,0,1,1,1.5-1.076l2.381,3.313,2.38-3.313a.922.922,0,1,1,1.5,1.076l-3.129,4.355A.921.921,0,0,1,11.833,20.248Z" transform="translate(-2.455 -6.989)"/></g></g></svg>
|
After Width: | Height: | Size: 1.1 KiB |
BIN
src/assets/image/header/logo.png
Normal file
BIN
src/assets/image/header/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.2 KiB |
BIN
src/assets/image/pdf.png
Normal file
BIN
src/assets/image/pdf.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.2 KiB |
BIN
src/assets/images/header/logo.png
Normal file
BIN
src/assets/images/header/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.2 KiB |
34
src/components/customDefaultPage/index.vue
Normal file
34
src/components/customDefaultPage/index.vue
Normal file
@ -0,0 +1,34 @@
|
||||
<script setup>
|
||||
import { computed } from 'vue'
|
||||
import { useWindowSize } from '@vueuse/core'
|
||||
|
||||
import size375 from '@/components/customDefaultPage/size375/index.vue'
|
||||
import size1920 from '@/components/customDefaultPage/size1920/index.vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
const router = useRouter()
|
||||
const { width } = useWindowSize()
|
||||
const { t } = useI18n()
|
||||
|
||||
const viewComponent = computed(() => {
|
||||
const viewWidth = width.value
|
||||
if (viewWidth <= 450) {
|
||||
return size375
|
||||
}
|
||||
// else if (viewWidth <= 1100) {
|
||||
// return size768;
|
||||
// } else if (viewWidth <= 1500) {
|
||||
// return size1440;
|
||||
// }
|
||||
else if (viewWidth <= 1920 || viewWidth > 1920) {
|
||||
return size1920
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<component :is="viewComponent" />
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss"></style>
|
18
src/components/customDefaultPage/size1920/index.vue
Normal file
18
src/components/customDefaultPage/size1920/index.vue
Normal file
@ -0,0 +1,18 @@
|
||||
<template>
|
||||
<!-- 通用缺省页 -->
|
||||
<div class="custom-default-page">
|
||||
<div class="search-area">
|
||||
<customSelectSearch></customSelectSearch>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import customSelectSearch from '@/components/customSelectSearch/index.vue'
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.search-area {
|
||||
width: 300px;
|
||||
margin: 100px 300px;
|
||||
}
|
||||
</style>
|
||||
|
18
src/components/customDefaultPage/size375/index.vue
Normal file
18
src/components/customDefaultPage/size375/index.vue
Normal file
@ -0,0 +1,18 @@
|
||||
<template>
|
||||
<!-- 通用缺省页 -->
|
||||
<div class="custom-default-page">
|
||||
<div class="search-area">
|
||||
<customSelectSearch></customSelectSearch>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import customSelectSearch from '@/components/customSelectSearch/index.vue'
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.search-area {
|
||||
width: 1500px;
|
||||
margin: 500px 200px;
|
||||
}
|
||||
</style>
|
||||
|
34
src/components/customFooter/index.vue
Normal file
34
src/components/customFooter/index.vue
Normal file
@ -0,0 +1,34 @@
|
||||
<script setup>
|
||||
import { computed } from 'vue'
|
||||
import { useWindowSize } from '@vueuse/core'
|
||||
|
||||
import size375 from '@/components/customFooter/size375/index.vue'
|
||||
import size1920 from '@/components/customFooter/size1920/index.vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
const router = useRouter()
|
||||
const { width } = useWindowSize()
|
||||
const { t } = useI18n()
|
||||
|
||||
const viewComponent = computed(() => {
|
||||
const viewWidth = width.value
|
||||
if (viewWidth <= 450) {
|
||||
return size375
|
||||
}
|
||||
// else if (viewWidth <= 1100) {
|
||||
// return size768;
|
||||
// } else if (viewWidth <= 1500) {
|
||||
// return size1440;
|
||||
// }
|
||||
else if (viewWidth <= 1920 || viewWidth > 1920) {
|
||||
return size1920
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<component :is="viewComponent" />
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss"></style>
|
26
src/components/customFooter/size1920/index.vue
Normal file
26
src/components/customFooter/size1920/index.vue
Normal file
@ -0,0 +1,26 @@
|
||||
<template>
|
||||
<!-- 通用页脚 -->
|
||||
<div class="custom-footer">
|
||||
<span>Copyright © 2024-2027 FiEE</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup></script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.custom-footer {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
padding: 24px 0;
|
||||
color: #888;
|
||||
font-size: 15px;
|
||||
background: #f7f8fa;
|
||||
letter-spacing: 1px;
|
||||
border-top: 1px solid #ececec;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
z-index: 100;
|
||||
}
|
||||
</style>
|
||||
|
26
src/components/customFooter/size375/index.vue
Normal file
26
src/components/customFooter/size375/index.vue
Normal file
@ -0,0 +1,26 @@
|
||||
<template>
|
||||
<!-- 通用页脚 -->
|
||||
<div class="custom-footer">
|
||||
<span>Copyright © 2024-2027 FiEE</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup></script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.custom-footer {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
padding: 120px 0;
|
||||
color: #888;
|
||||
font-size: 75px;
|
||||
background: #f7f8fa;
|
||||
letter-spacing: 5px;
|
||||
border-top: 5px solid #ececec;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
z-index: 100;
|
||||
}
|
||||
</style>
|
||||
|
34
src/components/customHeader/index.vue
Normal file
34
src/components/customHeader/index.vue
Normal file
@ -0,0 +1,34 @@
|
||||
<script setup>
|
||||
import { computed } from 'vue'
|
||||
import { useWindowSize } from '@vueuse/core'
|
||||
|
||||
import size375 from '@/components/customHeader/size375/index.vue'
|
||||
import size1920 from '@/components/customHeader/size1920/index.vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
const router = useRouter()
|
||||
const { width } = useWindowSize()
|
||||
const { t } = useI18n()
|
||||
|
||||
const viewComponent = computed(() => {
|
||||
const viewWidth = width.value
|
||||
if (viewWidth <= 450) {
|
||||
return size375
|
||||
}
|
||||
// else if (viewWidth <= 1100) {
|
||||
// return size768;
|
||||
// } else if (viewWidth <= 1500) {
|
||||
// return size1440;
|
||||
// }
|
||||
else if (viewWidth <= 1920 || viewWidth > 1920) {
|
||||
return size1920
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<component :is="viewComponent" />
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss"></style>
|
225
src/components/customHeader/size1920/index.vue
Normal file
225
src/components/customHeader/size1920/index.vue
Normal file
@ -0,0 +1,225 @@
|
||||
<template>
|
||||
<!-- 通用页头 -->
|
||||
<NLayoutHeader
|
||||
class="custom-header"
|
||||
:class="{ 'header-scrolled': isScrolled }"
|
||||
>
|
||||
<div class="header-container">
|
||||
<div class="logo" @click="handleToHome">
|
||||
<NImage width="160" height="50" :src="FiEELogo" preview-disabled />
|
||||
</div>
|
||||
<div class="header-menu">
|
||||
<NMenu
|
||||
mode="horizontal"
|
||||
:options="menuOptions"
|
||||
:inverted="isScrolled"
|
||||
v-model:value="selectedKey"
|
||||
@update:value="handleMenuSelect"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</NLayoutHeader>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import FiEELogo from '@/assets/image/header/logo.png'
|
||||
import { ref, onMounted, onUnmounted } from 'vue'
|
||||
import { NMenu, NLayoutHeader, NImage } from 'naive-ui'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useHeaderMenuConfig } from '@/config/headerMenuConfig'
|
||||
|
||||
const { t } = useI18n()
|
||||
const router = useRouter()
|
||||
|
||||
// 使用统一的菜单配置
|
||||
const menuOptions = useHeaderMenuConfig()
|
||||
const selectedKey = ref(null)
|
||||
|
||||
const isScrolled = ref(false)
|
||||
|
||||
// 递归查找菜单项
|
||||
function findMenuOptionByKey(options, key) {
|
||||
for (const option of options) {
|
||||
if (option.key === key) return option;
|
||||
if (option.children) {
|
||||
const found = findMenuOptionByKey(option.children, key);
|
||||
if (found) return found;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// 菜单点击跳转
|
||||
const handleMenuSelect = (key) => {
|
||||
const option = findMenuOptionByKey(menuOptions, key);
|
||||
if (option && option.href) {
|
||||
router.push(option.href);
|
||||
}
|
||||
};
|
||||
|
||||
// 监听滚动事件
|
||||
const handleScroll = () => {
|
||||
//滚动距离大于100px时,处理对应的header样式
|
||||
isScrolled.value = window.scrollY >= 100;
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
window.addEventListener("scroll", handleScroll);
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener('scroll', handleScroll)
|
||||
})
|
||||
|
||||
//点击回到首页
|
||||
const handleToHome = () => {
|
||||
router.push('/')
|
||||
selectedKey.value = null // 重置菜单选中状态
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.custom-header {
|
||||
--header-height: 80px;
|
||||
--primary-color: #8B59F7;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 1000;
|
||||
transition: all 0.3s ease;
|
||||
background: transparent;
|
||||
height: var(--header-height);
|
||||
|
||||
&.header-scrolled {
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
backdrop-filter: blur(8px);
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
}
|
||||
|
||||
.header-container {
|
||||
max-width: 1700px;
|
||||
margin: 0 auto;
|
||||
padding: 0 40px;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.logo {
|
||||
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 {
|
||||
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>
|
215
src/components/customHeader/size375/index.vue
Normal file
215
src/components/customHeader/size375/index.vue
Normal file
@ -0,0 +1,215 @@
|
||||
<template>
|
||||
<!-- 通用页头 -->
|
||||
<NLayoutHeader
|
||||
class="custom-header"
|
||||
:class="{ 'header-scrolled': isScrolled }"
|
||||
>
|
||||
<div class="header-container">
|
||||
<div class="logo" @click="handleToHome">
|
||||
<NImage
|
||||
style="width: 108px; height: 33px; max-width: 100%"
|
||||
:src="FiEELogo"
|
||||
preview-disabled
|
||||
/>
|
||||
</div>
|
||||
<div class="menu-btn" :class="{ 'menu-open': showMenu }" @click="toggleMenu">
|
||||
<n-icon size="28" class="menu-icon menu-icon-menu">
|
||||
<menu-sharp />
|
||||
</n-icon>
|
||||
<n-icon size="28" class="menu-icon menu-icon-close">
|
||||
<close-sharp />
|
||||
</n-icon>
|
||||
</div>
|
||||
</div>
|
||||
</NLayoutHeader>
|
||||
<transition name="fade-slide">
|
||||
<div v-if="showMenu" class="mobile-menu-wrapper" @click.self="closeMenu">
|
||||
<NMenu
|
||||
mode="vertical"
|
||||
:options="menuOptions"
|
||||
:inverted="isScrolled"
|
||||
class="mobile-menu"
|
||||
accordion
|
||||
v-model:value="selectedKey"
|
||||
@update:value="handleMenuSelect"
|
||||
/>
|
||||
</div>
|
||||
</transition>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import FiEELogo from '@/assets/image/header/logo.png'
|
||||
import { ref, onMounted, onUnmounted } from 'vue'
|
||||
import { NMenu, NLayoutHeader, NImage, NIcon } from 'naive-ui'
|
||||
import { MenuSharp, CloseSharp } from '@vicons/ionicons5'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useHeaderMenuConfig } from '@/config/headerMenuConfig'
|
||||
|
||||
const { t } = useI18n()
|
||||
const router = useRouter()
|
||||
|
||||
const isScrolled = ref(false)
|
||||
const showMenu = ref(false)
|
||||
const selectedKey = ref(null)
|
||||
|
||||
const toggleMenu = () => {
|
||||
showMenu.value = !showMenu.value;
|
||||
};
|
||||
const closeMenu = () => {
|
||||
showMenu.value = false;
|
||||
};
|
||||
|
||||
// 递归查找菜单项
|
||||
function findMenuOptionByKey(options, key) {
|
||||
for (const option of options) {
|
||||
if (option.key === key) return option;
|
||||
if (option.children) {
|
||||
const found = findMenuOptionByKey(option.children, key);
|
||||
if (found) return found;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// 菜单点击跳转
|
||||
const handleMenuSelect = (key) => {
|
||||
const option = findMenuOptionByKey(menuOptions, key);
|
||||
if (option && option.href) {
|
||||
router.push(option.href);
|
||||
showMenu.value = false; // 跳转后收起菜单
|
||||
}
|
||||
};
|
||||
|
||||
// 使用统一的菜单配置
|
||||
const menuOptions = useHeaderMenuConfig()
|
||||
|
||||
// 监听滚动事件
|
||||
const handleScroll = () => {
|
||||
//滚动距离大于100px时,处理对应的header样式
|
||||
isScrolled.value = window.scrollY >= 100;
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
window.addEventListener("scroll", handleScroll);
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener('scroll', handleScroll)
|
||||
})
|
||||
|
||||
//点击回到首页
|
||||
const handleToHome = () => {
|
||||
router.push('/')
|
||||
selectedKey.value = null // 重置菜单选中状态
|
||||
showMenu.value = false // 在移动端同时关闭菜单
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.custom-header {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 1000;
|
||||
transition: all 0.3s ease;
|
||||
background: transparent;
|
||||
height: 320px;
|
||||
|
||||
&.header-scrolled {
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
}
|
||||
|
||||
.header-container {
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
box-sizing: border-box;
|
||||
padding: 0 80px;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.logo {
|
||||
flex-shrink: 0;
|
||||
margin-right: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.logo :deep(.n-image) {
|
||||
max-width: 100px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.menu-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
font-size: 75px;
|
||||
padding: 40px 70px;
|
||||
border-radius: 30px;
|
||||
background: transparent;
|
||||
user-select: none;
|
||||
transition: background 0.2s;
|
||||
position: relative;
|
||||
|
||||
.menu-icon {
|
||||
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 {
|
||||
position: fixed;
|
||||
top: 320px;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
background: #fff;
|
||||
z-index: 1100;
|
||||
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.08);
|
||||
padding: 40px 0 80px 0;
|
||||
max-height: 1500px;
|
||||
overflow-y: auto;
|
||||
:deep(.n-menu-item) {
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
.fade-slide-enter-active,
|
||||
.fade-slide-leave-active {
|
||||
transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
.fade-slide-enter-from,
|
||||
.fade-slide-leave-to {
|
||||
opacity: 0;
|
||||
transform: translateY(-50px);
|
||||
}
|
||||
</style>
|
38
src/components/customSelectSearch/index.vue
Normal file
38
src/components/customSelectSearch/index.vue
Normal file
@ -0,0 +1,38 @@
|
||||
<template>
|
||||
<div class="custom-select-search">
|
||||
<n-select
|
||||
:options="state.selectOptions"
|
||||
v-model:value="state.selectedValue"
|
||||
/>
|
||||
<n-input
|
||||
v-model:value="state.inputValue"
|
||||
type="text"
|
||||
placeholder="Search"
|
||||
/>
|
||||
<n-button type="primary">Go</n-button>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { reactive } from 'vue'
|
||||
import { NSelect, NInput, NButton } from 'naive-ui'
|
||||
|
||||
const state = reactive({
|
||||
selectedValue: 'all_years', //选中值
|
||||
selectOptions: [
|
||||
{
|
||||
label: 'All Years',
|
||||
value: 'all_years',
|
||||
},
|
||||
], //下拉选项
|
||||
inputValue: '', //输入值
|
||||
})
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.custom-select-search {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
gap: 10px;
|
||||
}
|
||||
</style>
|
105
src/config/headerMenuConfig.js
Normal file
105
src/config/headerMenuConfig.js
Normal file
@ -0,0 +1,105 @@
|
||||
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',
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
}
|
@ -463,5 +463,66 @@ export default {
|
||||
],
|
||||
note: 'Minim representatives (other than authorized speakers) who receive inquiries from the media, market professionals, or shareholders should not respond to such inquiries but should refer the inquirer to an authorized speaker. However, Minim representatives assigned to the Investor Relations and Marketing teams may respond to routine inquiries about public information in accordance with guidelines established by authorized speakers from time to time.'
|
||||
}
|
||||
},
|
||||
|
||||
financialinformation: {
|
||||
secfilings: {
|
||||
title: 'Financials',
|
||||
overview: {
|
||||
title: 'Company Financial Overview',
|
||||
desc: 'This page offers access to our <strong>Annual Reports</strong> and <strong>SEC Filings</strong>. These sections provide key financial data and regulatory documents, keeping you informed about our financial performance and compliance.'
|
||||
},
|
||||
annual_reports: {
|
||||
title: 'Annual Reports',
|
||||
file_name: 'File Name',
|
||||
view: 'View'
|
||||
},
|
||||
sec: {
|
||||
title: 'SEC Filings',
|
||||
desc: 'To Access All Of Our Fillings With Sec Sites, Please',
|
||||
click_here: 'Click Here'
|
||||
}
|
||||
},
|
||||
quarterlyresults: {
|
||||
title: 'Quarterly Results',
|
||||
search: {
|
||||
placeholder: 'Search',
|
||||
button: 'Go'
|
||||
},
|
||||
download: 'Download'
|
||||
}
|
||||
},
|
||||
header_menu: {
|
||||
corporate_information: {
|
||||
title: 'Corporate Information',
|
||||
company_overview: 'Company Overview',
|
||||
business_introduction: 'Business Introduction',
|
||||
management: 'Management',
|
||||
board_of_directors: 'Board of Directors',
|
||||
committee_appointments: 'Committee Appointments',
|
||||
governance: 'Governance',
|
||||
corporate_video: 'Corporate Video'
|
||||
},
|
||||
financial_information: {
|
||||
title: 'Financial Information',
|
||||
sec_filings: 'SEC Filings',
|
||||
quarterly_results: 'Quarterly Results',
|
||||
},
|
||||
stock_information: {
|
||||
title: 'Stock Information',
|
||||
stock_quote: 'Stock Quote',
|
||||
historic_stock_price: 'Historic Stock Price',
|
||||
investment_calculator: 'Investment Calculator'
|
||||
},
|
||||
news_releases: {
|
||||
title: 'News Releases',
|
||||
press_releases: 'Press Releases',
|
||||
events_calendar: 'Events Calendar'
|
||||
},
|
||||
investor_resources: {
|
||||
title: 'Investor Resources',
|
||||
ir_contacts: 'IR Contacts',
|
||||
email_alerts: 'Email Alerts'
|
||||
}
|
||||
}
|
||||
}
|
@ -1,14 +1,20 @@
|
||||
// router/index.js
|
||||
import { createRouter, createWebHistory } from 'vue-router';
|
||||
import { setupRouterGuards } from './router-guards';
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
import { setupRouterGuards } from './router-guards'
|
||||
|
||||
const routes = [
|
||||
{
|
||||
path: '/',
|
||||
redirect: 'home'
|
||||
},
|
||||
name: 'index',
|
||||
component: () => import('@/views/index/index.vue'),
|
||||
// beforeEnter: (to, from, next) => {
|
||||
|
||||
// localStorage.clear()
|
||||
// next()
|
||||
// }
|
||||
children: [
|
||||
{
|
||||
path: '/home',
|
||||
path: 'home',
|
||||
name: 'home',
|
||||
component: () => import('@/views/home/index.vue'),
|
||||
// beforeEnter: (to, from, next) => {
|
||||
@ -38,16 +44,67 @@ const routes = [
|
||||
component: () => import('@/views/email-alerts/index.vue'),
|
||||
},
|
||||
];
|
||||
},
|
||||
{
|
||||
path: 'press-releases',
|
||||
name: 'press-releases',
|
||||
component: () => import('@/views/press-releases/index.vue'),
|
||||
},
|
||||
{
|
||||
path: '/quarterlyresults',
|
||||
name: 'QuarterlyResults',
|
||||
component: () =>
|
||||
import('@/views/financialinformation/quarterlyresults/index.vue'),
|
||||
},
|
||||
{
|
||||
path: '/secfilings',
|
||||
name: 'SecFilings',
|
||||
component: () =>
|
||||
import('@/views/financialinformation/secfilings/index.vue'),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: '/contacts',
|
||||
name: 'contacts',
|
||||
component: () => import('@/views/contacts/index.vue'),
|
||||
},
|
||||
// {
|
||||
// path: '/companyprofil',
|
||||
// name: 'Companyprofil',
|
||||
// component: () => import('@/views/companyprofil/index.vue'),
|
||||
// },
|
||||
// {
|
||||
// path: '/companyprofildetail',
|
||||
// name: 'Companyprofildetail',
|
||||
// component: () => import('@/views/companyprofildetail/index.vue'),
|
||||
// },
|
||||
// {
|
||||
// path: '/businessintroduction',
|
||||
// name: 'Businessintroduction',
|
||||
// component: () => import('@/views/businessintroduction/index.vue'),
|
||||
// },
|
||||
// {
|
||||
// path: '/investor',
|
||||
// name: 'Investor',
|
||||
// component: () => import('@/views/investor/index.vue'),
|
||||
// },
|
||||
// {
|
||||
// path: '/investorhandbook',
|
||||
// name: 'Investorhandbook',
|
||||
// component: () => import('@/views/investorhandbook/index.vue'),
|
||||
// },
|
||||
]
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(),
|
||||
routes
|
||||
});
|
||||
routes,
|
||||
})
|
||||
router.beforeEach((to, from, next) => {
|
||||
if (to.meta?.title) {
|
||||
document.title = to.meta.title;
|
||||
document.title = to.meta.title
|
||||
}
|
||||
next()
|
||||
});
|
||||
setupRouterGuards(router);
|
||||
export default router;
|
||||
})
|
||||
setupRouterGuards(router)
|
||||
export default router
|
||||
|
34
src/views/financialinformation/quarterlyresults/index.vue
Normal file
34
src/views/financialinformation/quarterlyresults/index.vue
Normal file
@ -0,0 +1,34 @@
|
||||
<script setup>
|
||||
import { computed } from "vue";
|
||||
import { useWindowSize } from "@vueuse/core";
|
||||
|
||||
import size375 from "@/views/financialinformation/quarterlyresults/size375/index.vue";
|
||||
import size768 from "@/views/financialinformation/quarterlyresults/size1920/index.vue";
|
||||
import size1440 from "@/views/financialinformation/quarterlyresults/size1920/index.vue";
|
||||
import size1920 from "@/views/financialinformation/quarterlyresults/size1920/index.vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import { useI18n } from "vue-i18n";
|
||||
|
||||
const router = useRouter();
|
||||
const { width } = useWindowSize();
|
||||
const { t } = useI18n();
|
||||
|
||||
const viewComponent = computed(() => {
|
||||
const viewWidth = width.value;
|
||||
if (viewWidth <= 450) {
|
||||
return size375;
|
||||
} else if (viewWidth <= 1100) {
|
||||
return size768;
|
||||
} else if (viewWidth <= 1500) {
|
||||
return size1440;
|
||||
} else if (viewWidth <= 1920 || viewWidth > 1920) {
|
||||
return size1920;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<component :is="viewComponent" />
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss"></style>
|
@ -0,0 +1,153 @@
|
||||
<template>
|
||||
<header></header>
|
||||
<main class="p-[35px] max-w-[1200px] mx-auto">
|
||||
<div class="title mb-[20px]">
|
||||
{{ t("financialinformation.quarterlyresults.title") }}
|
||||
</div>
|
||||
<div class="search-container">
|
||||
<input
|
||||
type="text"
|
||||
:placeholder="
|
||||
t('financialinformation.quarterlyresults.search.placeholder')
|
||||
"
|
||||
v-model="searchQuery"
|
||||
class="search-input"
|
||||
/>
|
||||
<button class="search-button" @click="handleSearch">
|
||||
{{ t("financialinformation.quarterlyresults.search.button") }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="results-list">
|
||||
<div
|
||||
v-for="(item, index) in filteredList"
|
||||
:key="index"
|
||||
class="result-item"
|
||||
>
|
||||
<div class="content">
|
||||
<a :href="item.url" class="result-title subtitle">{{ item.title }}</a>
|
||||
<p class="result-description content-text">{{ item.description }}</p>
|
||||
</div>
|
||||
<div class="pdf-icon">
|
||||
<a :href="item.url" target="_blank">
|
||||
<img src="@/assets/image/pdf.png" alt="PDF" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<footer></footer>
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref, watch, onMounted, computed, reactive } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
|
||||
const { t } = useI18n();
|
||||
const searchQuery = ref("");
|
||||
|
||||
const state = reactive({
|
||||
list: [
|
||||
{
|
||||
title: "2025 Q1 Quarterly Results",
|
||||
description:
|
||||
"Unaudited First Quarter and Full Year 2025 Financial Results",
|
||||
url: "/src/assets/file/2025 Q1 Quarterly Results.pdf",
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
onMounted(async () => {});
|
||||
const filteredList = computed(() => {
|
||||
if (!searchQuery.value) return state.list;
|
||||
const query = searchQuery.value.toLowerCase();
|
||||
return state.list.filter(
|
||||
(item) =>
|
||||
item.title.toLowerCase().includes(query) ||
|
||||
item.description.toLowerCase().includes(query)
|
||||
);
|
||||
});
|
||||
|
||||
const handleSearch = () => {
|
||||
// 搜索处理逻辑
|
||||
console.log("搜索:", searchQuery.value);
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.title {
|
||||
font-size: 40px;
|
||||
color: #333;
|
||||
}
|
||||
.subtitle {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
}
|
||||
.content-text {
|
||||
font-size: 16px;
|
||||
}
|
||||
.search-container {
|
||||
margin-bottom: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
padding: 8px 12px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
width: 240px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.search-button {
|
||||
padding: 8px 16px;
|
||||
background-color: #f0f0f0;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.results-list {
|
||||
padding-right: 20px;
|
||||
margin-top: 20px;
|
||||
max-height: 1200px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.result-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
padding: 15px 0;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
.content {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.result-title {
|
||||
color: #0078d7;
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
margin-bottom: 5px;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
.result-description {
|
||||
color: #666;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.pdf-icon {
|
||||
margin-left: 15px;
|
||||
|
||||
img {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -0,0 +1,217 @@
|
||||
<template>
|
||||
<header></header>
|
||||
<main class="p-[80px] mx-auto" style="max-width: 100vw; min-width: 375px">
|
||||
<div class="page-title mb-[24px]">
|
||||
{{ t("financialinformation.quarterlyresults.title") }}
|
||||
</div>
|
||||
<div class="search-container">
|
||||
<n-input
|
||||
v-model:value="searchQuery"
|
||||
:placeholder="
|
||||
t('financialinformation.quarterlyresults.search.placeholder')
|
||||
"
|
||||
clearable
|
||||
:font-size="72"
|
||||
/>
|
||||
<n-button
|
||||
type="primary"
|
||||
@click="handleSearch"
|
||||
:font-size="72"
|
||||
class="ml-[10px]"
|
||||
>
|
||||
{{ t("financialinformation.quarterlyresults.search.button") }}
|
||||
</n-button>
|
||||
</div>
|
||||
|
||||
<div class="results-list">
|
||||
<div
|
||||
v-for="(item, index) in filteredList"
|
||||
:key="index"
|
||||
class="result-item flex items-center mt-[20px] mb-[20px]"
|
||||
>
|
||||
<img
|
||||
src="@/assets/image/pdf.png"
|
||||
alt="PDF"
|
||||
style="width: 20px; height: 20px"
|
||||
/>
|
||||
<div class="content">
|
||||
<div class="result-title">{{ item.title }}</div>
|
||||
</div>
|
||||
|
||||
<img
|
||||
src="@/assets/image/download.svg"
|
||||
style="width: 20px; height: 20px"
|
||||
@click="handleDownload(item.url)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<footer></footer>
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref, watch, onMounted, computed, reactive } from "vue";
|
||||
import { NButton, NInput, NTooltip } from "naive-ui";
|
||||
import { useI18n } from "vue-i18n";
|
||||
|
||||
const { t } = useI18n();
|
||||
const searchQuery = ref("");
|
||||
|
||||
const state = reactive({
|
||||
list: [
|
||||
{
|
||||
title: "2025 Q1 Quarterly Results",
|
||||
description:
|
||||
"Unaudited First Quarter and Full Year 2025 Financial Results",
|
||||
url: "/src/assets/file/2025 Q1 Quarterly Results.pdf",
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
onMounted(async () => {});
|
||||
const filteredList = computed(() => {
|
||||
if (!searchQuery.value) return state.list;
|
||||
const query = searchQuery.value.toLowerCase();
|
||||
return state.list.filter(
|
||||
(item) =>
|
||||
item.title.toLowerCase().includes(query) ||
|
||||
item.description.toLowerCase().includes(query)
|
||||
);
|
||||
});
|
||||
|
||||
const handleSearch = () => {
|
||||
// 搜索处理逻辑
|
||||
console.log("搜索:", searchQuery.value);
|
||||
};
|
||||
|
||||
const handleDownload = (url) => {
|
||||
// 下载处理逻辑
|
||||
console.log("下载:", url);
|
||||
|
||||
// 创建一个隐藏的a元素
|
||||
const link = document.createElement("a");
|
||||
link.href = url;
|
||||
link.download = url.split("/").pop(); // 从URL提取文件名
|
||||
link.target = "_blank";
|
||||
|
||||
// 对于移动设备,我们需要特殊处理
|
||||
const isMobile =
|
||||
/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
|
||||
navigator.userAgent
|
||||
);
|
||||
|
||||
if (isMobile) {
|
||||
// 在移动设备上,可能需要使用fetch下载文件并创建blob
|
||||
fetch(url)
|
||||
.then((response) => response.blob())
|
||||
.then((blob) => {
|
||||
const objectUrl = URL.createObjectURL(blob);
|
||||
link.href = objectUrl;
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
|
||||
// 清理
|
||||
setTimeout(() => {
|
||||
document.body.removeChild(link);
|
||||
URL.revokeObjectURL(objectUrl);
|
||||
}, 100);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("下载文件时出错:", error);
|
||||
// 如果fetch失败,回退到window.open
|
||||
window.open(url, "_blank");
|
||||
});
|
||||
} else {
|
||||
// 桌面设备上直接点击链接
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.page-title {
|
||||
font-size: 113px;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
text-align: center;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.search-container {
|
||||
margin-bottom: 24px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background-color: #f6f7f9;
|
||||
border-radius: 8px;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.results-list {
|
||||
margin-top: 46px;
|
||||
max-height: 3000px;
|
||||
overflow-y: auto;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.result-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 46px;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
transition: background-color 0.2s;
|
||||
|
||||
&:hover {
|
||||
background-color: #f9fafc;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
.result-title {
|
||||
color: #2979ff;
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
margin-bottom: 8px;
|
||||
font-size: 92px;
|
||||
font-weight: 600;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
.result-description {
|
||||
color: #666;
|
||||
margin: 0;
|
||||
font-size: 72px;
|
||||
line-height: 1.4;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.pdf-icon {
|
||||
margin-left: 16px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
.pdf-link {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
text-decoration: none;
|
||||
color: #ff5252;
|
||||
font-size: 50px;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
34
src/views/financialinformation/secfilings/index.vue
Normal file
34
src/views/financialinformation/secfilings/index.vue
Normal file
@ -0,0 +1,34 @@
|
||||
<script setup>
|
||||
import { computed } from "vue";
|
||||
import { useWindowSize } from "@vueuse/core";
|
||||
|
||||
import size375 from "@/views/financialinformation/secfilings/size375/index.vue";
|
||||
import size768 from "@/views/financialinformation/secfilings/size1920/index.vue";
|
||||
import size1440 from "@/views/financialinformation/secfilings/size1920/index.vue";
|
||||
import size1920 from "@/views/financialinformation/secfilings/size1920/index.vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import { useI18n } from "vue-i18n";
|
||||
|
||||
const router = useRouter();
|
||||
const { width } = useWindowSize();
|
||||
const { t } = useI18n();
|
||||
|
||||
const viewComponent = computed(() => {
|
||||
const viewWidth = width.value;
|
||||
if (viewWidth <= 450) {
|
||||
return size375;
|
||||
} else if (viewWidth <= 1100) {
|
||||
return size768;
|
||||
} else if (viewWidth <= 1500) {
|
||||
return size1440;
|
||||
} else if (viewWidth <= 1920 || viewWidth > 1920) {
|
||||
return size1920;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<component :is="viewComponent" />
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss"></style>
|
262
src/views/financialinformation/secfilings/size1920/index.vue
Normal file
262
src/views/financialinformation/secfilings/size1920/index.vue
Normal file
@ -0,0 +1,262 @@
|
||||
<template>
|
||||
<div class="page-container">
|
||||
<div class="financials-container">
|
||||
<!-- 标题 -->
|
||||
<div class="financials-title">
|
||||
{{ t("financialinformation.secfilings.title") }}
|
||||
</div>
|
||||
|
||||
<!-- 公司财务概览 -->
|
||||
<section class="section">
|
||||
<div class="section-title">
|
||||
{{ t("financialinformation.secfilings.overview.title") }}
|
||||
</div>
|
||||
<p
|
||||
class="overview-text"
|
||||
v-html="t('financialinformation.secfilings.overview.desc')"
|
||||
></p>
|
||||
</section>
|
||||
|
||||
<!-- 年度报告 -->
|
||||
<section class="section">
|
||||
<div class="section-title">
|
||||
{{ t("financialinformation.secfilings.annual_reports.title") }}
|
||||
</div>
|
||||
|
||||
<!-- 报告表格 -->
|
||||
<div class="reports-table">
|
||||
<div class="table-header">
|
||||
<div class="column file-name">
|
||||
{{
|
||||
t("financialinformation.secfilings.annual_reports.file_name")
|
||||
}}
|
||||
</div>
|
||||
<div class="column download"></div>
|
||||
</div>
|
||||
|
||||
<!-- 报告列表 -->
|
||||
<div class="reports-list">
|
||||
<div
|
||||
class="table-row"
|
||||
v-for="(report, index) in annualReports"
|
||||
:key="index"
|
||||
>
|
||||
<div class="column file-name">{{ report.fileName }}</div>
|
||||
<div class="column download">
|
||||
<a :href="report.downloadUrl" class="download-link">{{
|
||||
t("financialinformation.secfilings.annual_reports.view")
|
||||
}}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- SEC文件 -->
|
||||
<section class="section">
|
||||
<div class="section-title">
|
||||
{{ t("financialinformation.secfilings.sec.title") }}
|
||||
</div>
|
||||
<p class="sec-text">
|
||||
{{ t("financialinformation.secfilings.sec.desc") }}
|
||||
<a
|
||||
href="https://www.sec.gov/cgi-bin/browse-edgar?company=&CIK=NCTY&filenum=&State=&SIC=&owner=include&action=getcompany"
|
||||
class="link"
|
||||
>{{ t("financialinformation.secfilings.sec.click_here") }}</a
|
||||
>.
|
||||
</p>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
// 年度报告数据
|
||||
const annualReports = ref([
|
||||
{
|
||||
fileName: "fieeinc_10q",
|
||||
downloadUrl:
|
||||
"https://www.sec.gov/ix?doc=/Archives/edgar/data/1467761/000182912625003706/fieeinc_10q.htm",
|
||||
},
|
||||
{
|
||||
fileName: "fieeinc_ex31-1",
|
||||
downloadUrl:
|
||||
"https://www.sec.gov/Archives/edgar/data/1467761/000182912625003706/fieeinc_ex31-1.htm",
|
||||
},
|
||||
{
|
||||
fileName: "fieeinc_ex31-2",
|
||||
downloadUrl:
|
||||
"https://www.sec.gov/Archives/edgar/data/1467761/000182912625003706/fieeinc_ex31-2.htm",
|
||||
},
|
||||
{
|
||||
fileName: "fieeinc_ex32-1",
|
||||
downloadUrl:
|
||||
"https://www.sec.gov/Archives/edgar/data/1467761/000182912625003706/fieeinc_ex32-1.htm",
|
||||
},
|
||||
{
|
||||
fileName: "fieeinc_ex32-2",
|
||||
downloadUrl:
|
||||
"https://www.sec.gov/Archives/edgar/data/1467761/000182912625003706/fieeinc_ex32-2.htm",
|
||||
},
|
||||
{
|
||||
fileName: " ownership",
|
||||
downloadUrl:
|
||||
"https://www.sec.gov/Archives/edgar/data/1467761/000182912625003622/xslF345X05/ownership.xml",
|
||||
},
|
||||
{
|
||||
fileName: "primary_doc",
|
||||
downloadUrl:
|
||||
"https://www.sec.gov/Archives/edgar/data/1467761/000182912625003620/xslSCHEDULE_13D_X01/primary_doc.xml",
|
||||
},
|
||||
{
|
||||
fileName: "fieeinc_ex1",
|
||||
downloadUrl:
|
||||
"https://www.sec.gov/Archives/edgar/data/1467761/000182912625003620/fieeinc_ex1.htm",
|
||||
},
|
||||
{
|
||||
fileName: "fiee_8ka",
|
||||
downloadUrl:
|
||||
"https://www.sec.gov/ix?doc=/Archives/edgar/data/1467761/000182912625003580/fiee_8ka.htm",
|
||||
},
|
||||
{
|
||||
fileName: "fiee_ex4-1",
|
||||
downloadUrl:
|
||||
"https://www.sec.gov/Archives/edgar/data/1467761/000182912625003580/fiee_ex4-1.htm",
|
||||
},
|
||||
{
|
||||
fileName: "fiee_ex10-1",
|
||||
downloadUrl:
|
||||
"https://www.sec.gov/Archives/edgar/data/1467761/000182912625003580/fiee_ex10-1.htm",
|
||||
},
|
||||
]);
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.page-container {
|
||||
background-image: url("@/assets/image/bg.png");
|
||||
background-size: 100% 100%;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
.financials-container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.financials-title {
|
||||
font-size: 40px;
|
||||
text-align: center;
|
||||
margin-bottom: 60px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.section {
|
||||
margin-bottom: 60px;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 18px;
|
||||
margin-bottom: 20px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.overview-text {
|
||||
font-size: 16px;
|
||||
line-height: 1.6;
|
||||
color: #333;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.tabs {
|
||||
display: flex;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.tab {
|
||||
padding: 10px 20px;
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
border-bottom: 2px solid transparent;
|
||||
|
||||
&.active {
|
||||
border-bottom: 2px solid #333;
|
||||
}
|
||||
}
|
||||
|
||||
.reports-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.table-header {
|
||||
display: flex;
|
||||
padding: 10px 0;
|
||||
border-bottom: 1px solid #ccc;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.table-row {
|
||||
display: flex;
|
||||
padding: 15px 0;
|
||||
border-bottom: 1px solid #eee;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.reports-list {
|
||||
// max-height: 600px;
|
||||
// overflow-y: auto;
|
||||
}
|
||||
.column {
|
||||
&.format {
|
||||
width: 10%;
|
||||
}
|
||||
|
||||
&.item {
|
||||
width: 15%;
|
||||
}
|
||||
|
||||
&.file-name {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
&.download {
|
||||
width: 25%;
|
||||
text-align: right;
|
||||
margin-right: 50px;
|
||||
}
|
||||
}
|
||||
|
||||
.pdf-icon {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
}
|
||||
|
||||
.download-link {
|
||||
color: #0078d7;
|
||||
text-decoration: none;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
.sec-text {
|
||||
font-size: 16px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.link {
|
||||
color: #f00;
|
||||
text-decoration: none;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
</style>
|
261
src/views/financialinformation/secfilings/size375/index.vue
Normal file
261
src/views/financialinformation/secfilings/size375/index.vue
Normal file
@ -0,0 +1,261 @@
|
||||
<template>
|
||||
<div class="page-container">
|
||||
<div class="financials-container">
|
||||
<!-- 标题 -->
|
||||
<div class="financials-title">
|
||||
{{ t("financialinformation.secfilings.title") }}
|
||||
</div>
|
||||
|
||||
<!-- 公司财务概览 -->
|
||||
<section class="section">
|
||||
<div class="section-title">
|
||||
{{ t("financialinformation.secfilings.overview.title") }}
|
||||
</div>
|
||||
<p
|
||||
class="overview-text"
|
||||
v-html="t('financialinformation.secfilings.overview.desc')"
|
||||
></p>
|
||||
</section>
|
||||
|
||||
<!-- 年度报告 -->
|
||||
<section class="section">
|
||||
<div class="section-title">
|
||||
{{ t("financialinformation.secfilings.annual_reports.title") }}
|
||||
</div>
|
||||
|
||||
<!-- 报告表格 -->
|
||||
<div class="reports-table">
|
||||
<div class="table-header">
|
||||
<div class="column file-name">
|
||||
{{
|
||||
t("financialinformation.secfilings.annual_reports.file_name")
|
||||
}}
|
||||
</div>
|
||||
<div class="column download"></div>
|
||||
</div>
|
||||
|
||||
<!-- 报告列表 -->
|
||||
<div class="reports-list">
|
||||
<div
|
||||
class="table-row"
|
||||
v-for="(report, index) in annualReports"
|
||||
:key="index"
|
||||
>
|
||||
<div class="column file-name">{{ report.fileName }}</div>
|
||||
<div class="column download">
|
||||
<a :href="report.downloadUrl" class="download-link">{{
|
||||
t("financialinformation.secfilings.annual_reports.view")
|
||||
}}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- SEC文件 -->
|
||||
<section class="section">
|
||||
<div class="section-title">
|
||||
{{ t("financialinformation.secfilings.sec.title") }}
|
||||
</div>
|
||||
<p class="sec-text">
|
||||
{{ t("financialinformation.secfilings.sec.desc") }}
|
||||
<a
|
||||
href="https://www.sec.gov/cgi-bin/browse-edgar?company=&CIK=NCTY&filenum=&State=&SIC=&owner=include&action=getcompany"
|
||||
class="link"
|
||||
>{{ t("financialinformation.secfilings.sec.click_here") }}</a
|
||||
>.
|
||||
</p>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
// 年度报告数据
|
||||
const annualReports = ref([
|
||||
{
|
||||
fileName: "fieeinc_10q",
|
||||
downloadUrl:
|
||||
"https://www.sec.gov/ix?doc=/Archives/edgar/data/1467761/000182912625003706/fieeinc_10q.htm",
|
||||
},
|
||||
{
|
||||
fileName: "fieeinc_ex31-1",
|
||||
downloadUrl:
|
||||
"https://www.sec.gov/Archives/edgar/data/1467761/000182912625003706/fieeinc_ex31-1.htm",
|
||||
},
|
||||
{
|
||||
fileName: "fieeinc_ex31-2",
|
||||
downloadUrl:
|
||||
"https://www.sec.gov/Archives/edgar/data/1467761/000182912625003706/fieeinc_ex31-2.htm",
|
||||
},
|
||||
{
|
||||
fileName: "fieeinc_ex32-1",
|
||||
downloadUrl:
|
||||
"https://www.sec.gov/Archives/edgar/data/1467761/000182912625003706/fieeinc_ex32-1.htm",
|
||||
},
|
||||
{
|
||||
fileName: "fieeinc_ex32-2",
|
||||
downloadUrl:
|
||||
"https://www.sec.gov/Archives/edgar/data/1467761/000182912625003706/fieeinc_ex32-2.htm",
|
||||
},
|
||||
{
|
||||
fileName: " ownership",
|
||||
downloadUrl:
|
||||
"https://www.sec.gov/Archives/edgar/data/1467761/000182912625003622/xslF345X05/ownership.xml",
|
||||
},
|
||||
{
|
||||
fileName: "primary_doc",
|
||||
downloadUrl:
|
||||
"https://www.sec.gov/Archives/edgar/data/1467761/000182912625003620/xslSCHEDULE_13D_X01/primary_doc.xml",
|
||||
},
|
||||
{
|
||||
fileName: "fieeinc_ex1",
|
||||
downloadUrl:
|
||||
"https://www.sec.gov/Archives/edgar/data/1467761/000182912625003620/fieeinc_ex1.htm",
|
||||
},
|
||||
{
|
||||
fileName: "fiee_8ka",
|
||||
downloadUrl:
|
||||
"https://www.sec.gov/ix?doc=/Archives/edgar/data/1467761/000182912625003580/fiee_8ka.htm",
|
||||
},
|
||||
{
|
||||
fileName: "fiee_ex4-1",
|
||||
downloadUrl:
|
||||
"https://www.sec.gov/Archives/edgar/data/1467761/000182912625003580/fiee_ex4-1.htm",
|
||||
},
|
||||
{
|
||||
fileName: "fiee_ex10-1",
|
||||
downloadUrl:
|
||||
"https://www.sec.gov/Archives/edgar/data/1467761/000182912625003580/fiee_ex10-1.htm",
|
||||
},
|
||||
]);
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.page-container {
|
||||
background-image: url("@/assets/image/bg-375.png");
|
||||
background-size: 100% 100%;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
.financials-container {
|
||||
margin: 0 auto;
|
||||
padding: 80px;
|
||||
}
|
||||
|
||||
.financials-title {
|
||||
font-size: 113px;
|
||||
font-weight: 600;
|
||||
text-align: center;
|
||||
margin-bottom: 60px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.section {
|
||||
margin-bottom: 60px;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 92px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 20px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.overview-text {
|
||||
font-size: 72px;
|
||||
line-height: 1.6;
|
||||
color: #333;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.tabs {
|
||||
display: flex;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.tab {
|
||||
padding: 10px 20px;
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
border-bottom: 2px solid transparent;
|
||||
|
||||
&.active {
|
||||
border-bottom: 2px solid #333;
|
||||
}
|
||||
}
|
||||
|
||||
.reports-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.table-header {
|
||||
display: flex;
|
||||
padding: 10px 0;
|
||||
border-bottom: 1px solid #ccc;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.table-row {
|
||||
display: flex;
|
||||
padding: 45px 0;
|
||||
border-bottom: 1px solid #eee;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.reports-list {
|
||||
// max-height: 600px;
|
||||
// overflow-y: auto;
|
||||
}
|
||||
.column {
|
||||
&.format {
|
||||
width: 10%;
|
||||
}
|
||||
|
||||
&.item {
|
||||
width: 15%;
|
||||
}
|
||||
|
||||
&.file-name {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
&.download {
|
||||
margin-right: 100px;
|
||||
}
|
||||
}
|
||||
|
||||
.pdf-icon {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
}
|
||||
|
||||
.download-link {
|
||||
color: #0078d7;
|
||||
text-decoration: none;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
.sec-text {
|
||||
font-size: 72px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.link {
|
||||
color: #f00;
|
||||
text-decoration: none;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -1,30 +1,18 @@
|
||||
<script setup>
|
||||
import { computed } from "vue";
|
||||
import { useWindowSize } from "@vueuse/core";
|
||||
|
||||
import size375 from "@/views/home/size375/index.vue";
|
||||
import size768 from "@/views/home/size768/index.vue";
|
||||
import size1440 from "@/views/home/size1440/index.vue";
|
||||
import size1920 from "@/views/home/size1920/index.vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import { useI18n } from "vue-i18n";
|
||||
|
||||
const router = useRouter();
|
||||
const { width } = useWindowSize();
|
||||
const { t } = useI18n();
|
||||
import size1920 from '@/views/home/size1920/index.vue'
|
||||
import size375 from '@/views/home/size375/index.vue'
|
||||
import { computed } from 'vue'
|
||||
import { useWindowSize } from '@vueuse/core'
|
||||
|
||||
const { width } = useWindowSize()
|
||||
const viewComponent = computed(() => {
|
||||
const viewWidth = width.value;
|
||||
const viewWidth = width.value
|
||||
if (viewWidth <= 450) {
|
||||
return size375;
|
||||
} else if (viewWidth <= 1100) {
|
||||
return size768;
|
||||
} else if (viewWidth <= 1500) {
|
||||
return size1440;
|
||||
return size375
|
||||
} else if (viewWidth <= 1920 || viewWidth > 1920) {
|
||||
return size1920;
|
||||
return size1920
|
||||
}
|
||||
});
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -1,22 +1,20 @@
|
||||
<script setup>
|
||||
import { NCarousel, NDivider, NMarquee, NPopselect } from "naive-ui";
|
||||
import { onUnmounted, ref, watch, onMounted, computed } from "vue";
|
||||
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">
|
||||
1920
|
||||
</header>
|
||||
<main ref="main">
|
||||
|
||||
</main>
|
||||
<footer>
|
||||
|
||||
</footer>
|
||||
<main ref="main"></main>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
main {
|
||||
padding: var(--header-height, 80px) 0 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
@ -1,22 +1,20 @@
|
||||
<script setup>
|
||||
import { NCarousel, NDivider, NMarquee, NPopselect } from "naive-ui";
|
||||
import { onUnmounted, ref, watch, onMounted, computed } from "vue";
|
||||
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>
|
||||
<footer>
|
||||
|
||||
</footer>
|
||||
<main ref="main"></main>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
main {
|
||||
padding: var(--header-height, 80px) 0 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
22
src/views/index/index.vue
Normal file
22
src/views/index/index.vue
Normal file
@ -0,0 +1,22 @@
|
||||
<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>
|
21
src/views/index/size1920/index.vue
Normal file
21
src/views/index/size1920/index.vue
Normal file
@ -0,0 +1,21 @@
|
||||
<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>
|
26
src/views/index/size375/index.vue
Normal file
26
src/views/index/size375/index.vue
Normal file
@ -0,0 +1,26 @@
|
||||
<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>
|
23
src/views/new-releases/index.vue
Normal file
23
src/views/new-releases/index.vue
Normal file
@ -0,0 +1,23 @@
|
||||
<template>
|
||||
<div class="new-releases-page">
|
||||
<component :is="viewComponent" />
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import size1920 from '@/views/new-releases/size1920/index.vue'
|
||||
import size375 from '@/views/new-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>
|
10
src/views/new-releases/size1920/index.vue
Normal file
10
src/views/new-releases/size1920/index.vue
Normal file
@ -0,0 +1,10 @@
|
||||
<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>
|
10
src/views/new-releases/size375/index.vue
Normal file
10
src/views/new-releases/size375/index.vue
Normal file
@ -0,0 +1,10 @@
|
||||
<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>
|
23
src/views/press-releases/index.vue
Normal file
23
src/views/press-releases/index.vue
Normal file
@ -0,0 +1,23 @@
|
||||
<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>
|
10
src/views/press-releases/size1920/index.vue
Normal file
10
src/views/press-releases/size1920/index.vue
Normal file
@ -0,0 +1,10 @@
|
||||
<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>
|
10
src/views/press-releases/size375/index.vue
Normal file
10
src/views/press-releases/size375/index.vue
Normal file
@ -0,0 +1,10 @@
|
||||
<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>
|
Loading…
Reference in New Issue
Block a user